Merge "Correctly unregister listeners when MMTEL moves to not ready"
diff --git a/proto/src/persist_atoms.proto b/proto/src/persist_atoms.proto
index d7cc58f..f0c2111 100644
--- a/proto/src/persist_atoms.proto
+++ b/proto/src/persist_atoms.proto
@@ -196,6 +196,7 @@
     optional int32 deactivate_reason = 16;
     optional int64 duration_minutes = 17;
     optional bool ongoing = 18;
+    optional int32 band_at_end = 19;
 }
 
 message CellularServiceState {
diff --git a/src/java/com/android/internal/telephony/CommandsInterface.java b/src/java/com/android/internal/telephony/CommandsInterface.java
index 7e212a5..25ae049 100644
--- a/src/java/com/android/internal/telephony/CommandsInterface.java
+++ b/src/java/com/android/internal/telephony/CommandsInterface.java
@@ -32,7 +32,9 @@
 import android.telephony.RadioAccessSpecifier;
 import android.telephony.SignalThresholdInfo;
 import android.telephony.TelephonyManager;
+import android.telephony.data.DataCallResponse;
 import android.telephony.data.DataProfile;
+import android.telephony.data.SliceInfo;
 import android.telephony.emergency.EmergencyNumber;
 
 import com.android.internal.telephony.cdma.CdmaSmsBroadcastConfigInfo;
@@ -1848,10 +1850,16 @@
      *            data connection
      * @param result
      *            Callback message
+     * @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}.
      */
     void setupDataCall(int accessNetworkType, DataProfile dataProfile, boolean isRoaming,
                        boolean allowRoaming, int reason, LinkProperties linkProperties,
-                       int pduSessionId, Message result);
+                       int pduSessionId, SliceInfo sliceInfo, Message result);
 
     /**
      * Deactivate packet data connection
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index 65bd62f..e22debb 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -56,6 +56,7 @@
 import android.hardware.radio.V1_5.IndicationFilter;
 import android.hardware.radio.V1_5.PersoSubstate;
 import android.hardware.radio.V1_5.RadioAccessNetworks;
+import android.hardware.radio.V1_6.OptionalSliceInfo;
 import android.hardware.radio.deprecated.V1_0.IOemHook;
 import android.net.InetAddresses;
 import android.net.KeepalivePacketData;
@@ -106,6 +107,7 @@
 import android.telephony.data.DataService;
 import android.telephony.data.Qos;
 import android.telephony.data.QosSession;
+import android.telephony.data.SliceInfo;
 import android.telephony.emergency.EmergencyNumber;
 import android.text.TextUtils;
 import android.util.Log;
@@ -1883,6 +1885,38 @@
         return dpi;
     }
 
+    private OptionalSliceInfo convertToHalSliceInfo16(@Nullable SliceInfo sliceInfo) {
+        OptionalSliceInfo optionalSliceInfo = new OptionalSliceInfo();
+        if (sliceInfo == null) {
+            return optionalSliceInfo;
+        }
+
+        android.hardware.radio.V1_6.SliceInfo si = new android.hardware.radio.V1_6.SliceInfo();
+        si.sst = (byte) sliceInfo.getSliceServiceType();
+        si.mappedHplmnSst = (byte) sliceInfo.getMappedHplmnSliceServiceType();
+        si.sliceDifferentiator = sliceInfo.getSliceDifferentiator();
+        si.mappedHplmnSD = sliceInfo.getMappedHplmnSliceDifferentiator();
+        optionalSliceInfo.value(si);
+        return optionalSliceInfo;
+    }
+
+    private ArrayList<android.hardware.radio.V1_5.LinkAddress> convertToHalLinkProperties15(
+            LinkProperties linkProperties) {
+        ArrayList<android.hardware.radio.V1_5.LinkAddress> addresses15 = new ArrayList<>();
+        if (linkProperties != null) {
+            for (LinkAddress la : linkProperties.getAllLinkAddresses()) {
+                android.hardware.radio.V1_5.LinkAddress linkAddress =
+                        new android.hardware.radio.V1_5.LinkAddress();
+                linkAddress.address = la.getAddress().getHostAddress();
+                linkAddress.properties = la.getFlags();
+                linkAddress.deprecationTime = la.getDeprecationTime();
+                linkAddress.expirationTime = la.getExpirationTime();
+                addresses15.add(linkAddress);
+            }
+        }
+        return addresses15;
+    }
+
     /**
      * Convert to DataProfileInfo defined in radio/1.5/types.hal
      * @param dp Data profile
@@ -1944,7 +1978,7 @@
     @Override
     public void setupDataCall(int accessNetworkType, DataProfile dataProfile, boolean isRoaming,
                               boolean allowRoaming, int reason, LinkProperties linkProperties,
-                              int pduSessionId, Message result) {
+                              int pduSessionId, SliceInfo sliceInfo, Message result) {
         IRadio radioProxy = getRadioProxy(result);
 
         if (radioProxy != null) {
@@ -1973,19 +2007,11 @@
                     android.hardware.radio.V1_5.DataProfileInfo dpi =
                             convertToHalDataProfile15(dataProfile);
 
+                    android.hardware.radio.V1_6.OptionalSliceInfo sliceInfo16 =
+                            convertToHalSliceInfo16(sliceInfo);
+
                     ArrayList<android.hardware.radio.V1_5.LinkAddress> addresses15 =
-                            new ArrayList<>();
-                    if (linkProperties != null) {
-                        for (LinkAddress la : linkProperties.getAllLinkAddresses()) {
-                            android.hardware.radio.V1_5.LinkAddress linkAddress =
-                                    new android.hardware.radio.V1_5.LinkAddress();
-                            linkAddress.address = la.getAddress().getHostAddress();
-                            linkAddress.properties = la.getFlags();
-                            linkAddress.deprecationTime = la.getDeprecationTime();
-                            linkAddress.expirationTime = la.getExpirationTime();
-                            addresses15.add(linkAddress);
-                        }
-                    }
+                            convertToHalLinkProperties15(linkProperties);
 
                     if (RILJ_LOGD) {
                         riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
@@ -1993,11 +2019,11 @@
                                 + AccessNetworkType.toString(accessNetworkType) + ",isRoaming="
                                 + isRoaming + ",allowRoaming=" + allowRoaming + "," + dataProfile
                                 + ",addresses=" + addresses15 + ",dnses=" + dnses
-                                + ",pduSessionId=" + pduSessionId);
+                                + ",pduSessionId=" + pduSessionId + ",sliceInfo=" + sliceInfo16);
                     }
 
                     radioProxy16.setupDataCall_1_6(rr.mSerial, accessNetworkType, dpi, allowRoaming,
-                            reason, addresses15, dnses, pduSessionId);
+                            reason, addresses15, dnses, pduSessionId, sliceInfo16);
                 } else if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_5)) {
                     // IRadio V1.5
                     android.hardware.radio.V1_5.IRadio radioProxy15 =
@@ -2008,18 +2034,7 @@
                             convertToHalDataProfile15(dataProfile);
 
                     ArrayList<android.hardware.radio.V1_5.LinkAddress> addresses15 =
-                            new ArrayList<>();
-                    if (linkProperties != null) {
-                        for (LinkAddress la : linkProperties.getAllLinkAddresses()) {
-                            android.hardware.radio.V1_5.LinkAddress linkAddress =
-                                    new android.hardware.radio.V1_5.LinkAddress();
-                            linkAddress.address = la.getAddress().getHostAddress();
-                            linkAddress.properties = la.getFlags();
-                            linkAddress.deprecationTime = la.getDeprecationTime();
-                            linkAddress.expirationTime = la.getExpirationTime();
-                            addresses15.add(linkAddress);
-                        }
-                    }
+                            convertToHalLinkProperties15(linkProperties);
 
                     if (RILJ_LOGD) {
                         riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
@@ -7367,6 +7382,7 @@
 
         List<LinkAddress> laList = new ArrayList<>();
         List<QosSession> qosSessions = new ArrayList<>();
+        SliceInfo sliceInfo = null;
 
         if (dcResult instanceof android.hardware.radio.V1_0.SetupDataCallResult) {
             final android.hardware.radio.V1_0.SetupDataCallResult result =
@@ -7445,7 +7461,6 @@
             laList = result.addresses.stream().map(la -> createLinkAddressFromString(
                     la.address, la.properties, la.deprecationTime, la.expirationTime))
                     .collect(Collectors.toList());
-
             dnses = result.dnses.stream().toArray(String[]::new);
             gateways = result.gateways.stream().toArray(String[]::new);
             pcscfs = result.pcscf.stream().toArray(String[]::new);
@@ -7457,6 +7472,7 @@
             defaultQos = Qos.create(result.defaultQos);
             qosSessions = result.qosSessions.stream().map(session ->
                     QosSession.create(session)).collect(Collectors.toList());
+            sliceInfo = convertToSliceInfo(result.sliceInfo);
         } else {
             Rlog.e(RILJ_LOG_TAG, "Unsupported SetupDataCallResult " + dcResult);
             return null;
@@ -7525,9 +7541,28 @@
                 .setPduSessionId(pduSessionId)
                 .setDefaultQos(defaultQos)
                 .setQosSessions(qosSessions)
+                .setSliceInfo(sliceInfo)
                 .build();
     }
 
+    private static SliceInfo convertToSliceInfo(OptionalSliceInfo optionalSliceInfo) {
+        if (optionalSliceInfo.getDiscriminator() == OptionalSliceInfo.hidl_discriminator.noinit) {
+            return null;
+        }
+
+        android.hardware.radio.V1_6.SliceInfo si = optionalSliceInfo.value();
+        SliceInfo.Builder builder =
+                new SliceInfo.Builder()
+                .setSliceServiceType(si.sst)
+                .setMappedHplmnSliceServiceType(si.mappedHplmnSst);
+        if (si.sliceDifferentiator != SliceInfo.SLICE_DIFFERENTIATOR_NO_SLICE) {
+            builder
+                .setSliceDifferentiator(si.sliceDifferentiator)
+                .setMappedHplmnSliceDifferentiator(si.mappedHplmnSD);
+        }
+        return builder.build();
+    }
+
     /**
      * Convert SetupDataCallResult defined in 1.0 or 1.4/types.hal into DataCallResponse
      * @param dataCallResultList List of SetupDataCallResult defined in 1.0 or 1.4/types.hal
diff --git a/src/java/com/android/internal/telephony/SubscriptionController.java b/src/java/com/android/internal/telephony/SubscriptionController.java
index 9251198..2b103e6 100644
--- a/src/java/com/android/internal/telephony/SubscriptionController.java
+++ b/src/java/com/android/internal/telephony/SubscriptionController.java
@@ -1627,12 +1627,20 @@
      * Insert an empty SubInfo record into the database.
      *
      * <p>NOTE: This is not accessible to external processes, so it does not need a permission
-     * check. It is only intended for use by {@link SubscriptionInfoUpdater}.
+     * check. It is only intended for use by {@link SubscriptionInfoUpdater}. If there is a
+     * subscription record exist with the same ICCID, no new empty record will be created.
      *
-     * <p>Precondition: No record exists with this iccId.
+     * @return the URL of the newly created row. Return <code>null</code> if no new empty record is
+     * created.
      */
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    @Nullable
     public Uri insertEmptySubInfoRecord(String iccId, int slotIndex) {
+        if (getSubInfoForIccId(iccId) != null) {
+            loge("insertEmptySubInfoRecord: Found existing record by ICCID. Do not create a "
+                    + "new empty entry.");
+            return null;
+        }
         return insertEmptySubInfoRecord(iccId, null, slotIndex,
                 SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM);
     }
diff --git a/src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java b/src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java
index 18d42b6..ddbc6ca 100644
--- a/src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java
+++ b/src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java
@@ -410,6 +410,26 @@
 
     protected void handleSimReady(int phoneId) {
         List<Integer> cardIds = new ArrayList<>();
+        logd("handleSimReady: phoneId: " + phoneId);
+
+        if (sIccId[phoneId] != null && sIccId[phoneId].equals(ICCID_STRING_FOR_NO_SIM)) {
+            logd(" SIM" + (phoneId + 1) + " hot plug in");
+            sIccId[phoneId] = null;
+        }
+
+        // ICCID is not available in IccRecords by the time SIM Ready event received
+        // hence get ICCID from UiccSlot.
+        UiccSlot uiccSlot = UiccController.getInstance().getUiccSlotForPhone(phoneId);
+        String iccId = (uiccSlot != null) ? IccUtils.stripTrailingFs(uiccSlot.getIccId()) : null;
+        if (!TextUtils.isEmpty(iccId)) {
+            // Call updateSubscriptionInfoByIccId() only if was
+            // not done earlier from SIM Locked event
+            if (sIccId[phoneId] == null) {
+                sIccId[phoneId] = iccId;
+
+                updateSubscriptionInfoByIccId(phoneId, true /* updateEmbeddedSubs */);
+            }
+        }
 
         cardIds.add(getCardIdFromPhoneId(phoneId));
         updateEmbeddedSubscriptions(cardIds, (hasChanges) -> {
@@ -422,7 +442,6 @@
         broadcastSimApplicationStateChanged(phoneId, TelephonyManager.SIM_STATE_NOT_READY);
     }
 
-
     protected void handleSimNotReady(int phoneId) {
         logd("handleSimNotReady: phoneId: " + phoneId);
         boolean isFinalState = false;
@@ -485,9 +504,14 @@
             logd("handleSimLoaded: IccID null");
             return;
         }
-        sIccId[phoneId] = IccUtils.stripTrailingFs(records.getFullIccId());
 
-        updateSubscriptionInfoByIccId(phoneId, true /* updateEmbeddedSubs */);
+        // Call updateSubscriptionInfoByIccId() only if was not done earlier from SIM READY event
+        if (sIccId[phoneId] == null) {
+            sIccId[phoneId] = IccUtils.stripTrailingFs(records.getFullIccId());
+
+            updateSubscriptionInfoByIccId(phoneId, true /* updateEmbeddedSubs */);
+        }
+
         List<SubscriptionInfo> subscriptionInfos =
                 mSubscriptionController.getSubInfoUsingSlotIndexPrivileged(phoneId);
         if (subscriptionInfos == null || subscriptionInfos.isEmpty()) {
diff --git a/src/java/com/android/internal/telephony/dataconnection/CellularDataService.java b/src/java/com/android/internal/telephony/dataconnection/CellularDataService.java
index 593167f..6f36835 100644
--- a/src/java/com/android/internal/telephony/dataconnection/CellularDataService.java
+++ b/src/java/com/android/internal/telephony/dataconnection/CellularDataService.java
@@ -29,6 +29,7 @@
 import android.telephony.data.DataProfile;
 import android.telephony.data.DataService;
 import android.telephony.data.DataServiceCallback;
+import android.telephony.data.SliceInfo;
 
 import com.android.internal.telephony.CommandException;
 import com.android.internal.telephony.Phone;
@@ -158,7 +159,7 @@
         @Override
         public void setupDataCall(int accessNetworkType, DataProfile dataProfile,
                 boolean isRoaming, boolean allowRoaming, int reason, LinkProperties linkProperties,
-                int pduSessionId, DataServiceCallback callback) {
+                int pduSessionId, SliceInfo sliceInfo, DataServiceCallback callback) {
             if (DBG) log("setupDataCall " + getSlotIndex());
 
             Message message = null;
@@ -170,7 +171,7 @@
             }
 
             mPhone.mCi.setupDataCall(accessNetworkType, dataProfile, isRoaming, allowRoaming,
-                    reason, linkProperties, pduSessionId, message);
+                    reason, linkProperties, pduSessionId, sliceInfo, message);
         }
 
         @Override
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
index 5b4c85c..9efd8eb 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
@@ -68,6 +68,7 @@
 import android.telephony.data.DataServiceCallback;
 import android.telephony.data.Qos;
 import android.telephony.data.QosSession;
+import android.telephony.data.SliceInfo;
 import android.text.TextUtils;
 import android.util.LocalLog;
 import android.util.Pair;
@@ -301,6 +302,7 @@
     private int mUplinkBandwidth = 14;
     private Qos mDefaultQos = null;
     private List<QosSession> mQosSessions = new ArrayList<>();
+    private SliceInfo mSliceInfo;
 
     /** The corresponding network agent for this data connection. */
     private DcNetworkAgent mNetworkAgent;
@@ -598,11 +600,23 @@
         return mPduSessionId;
     }
 
+    public SliceInfo getSliceInfo() {
+        return mSliceInfo;
+    }
+
     public void updateQosParameters(DataCallResponse response) {
         mDefaultQos = response.getDefaultQos();
         mQosSessions = response.getQosSessions();
     }
 
+    /**
+     * Update the latest slice info on this data connection with
+     * {@link DataCallResponse#getSliceInfo}.
+     */
+    public void updateSliceInfo(DataCallResponse response) {
+        mSliceInfo = response.getSliceInfo();
+    }
+
     @VisibleForTesting
     public UpdateLinkPropertyResult updateLinkProperty(DataCallResponse newState) {
         UpdateLinkPropertyResult result = new UpdateLinkPropertyResult(mLinkProperties);
@@ -861,6 +875,7 @@
                 reason,
                 linkProperties,
                 DataCallResponse.PDU_SESSION_ID_NOT_SET,
+                null,
                 msg);
         TelephonyMetrics.getInstance().writeSetupDataCall(mPhone.getPhoneId(), cp.mRilRat,
                 dp.getProfileId(), dp.getApn(), dp.getProtocolType());
@@ -937,6 +952,7 @@
                 reason,
                 linkProperties,
                 srcDc.getPduSessionId(),
+                srcDc.getSliceInfo(),
                 msg);
         TelephonyMetrics.getInstance().writeSetupDataCall(mPhone.getPhoneId(), cp.mRilRat,
                 dp.getProfileId(), dp.getApn(), dp.getProtocolType());
@@ -1216,6 +1232,7 @@
             mCid = response.getId();
             updatePcscfAddr(response);
             updateQosParameters(response);
+            updateSliceInfo(response);
             result = updateLinkProperty(response).setupResult;
 
             setPduSessionId(response.getPduSessionId());
@@ -2005,10 +2022,7 @@
                                 + " drs=" + mDataRegState
                                 + " mRilRat=" + mRilRat);
                     }
-                    // this is for DRS or RAT changes, so only call onRatChanged if RAT is changed
-                    if (mRilRat != 0) {
-                        mDataCallSessionStats.onRatChanged(mRilRat);
-                    }
+                    mDataCallSessionStats.onDrsOrRatChanged(mRilRat);
                     break;
 
                 case EVENT_START_HANDOVER:  //calls startHandover()
@@ -2241,10 +2255,10 @@
     private class DcActivatingState extends State {
         @Override
         public void enter() {
+            int apnTypeBitmask = mApnSetting != null ? mApnSetting.getApnTypeBitmask() : 0;
             TelephonyStatsLog.write(TelephonyStatsLog.MOBILE_CONNECTION_STATE_CHANGED,
                     TelephonyStatsLog.MOBILE_CONNECTION_STATE_CHANGED__STATE__ACTIVATING,
-                    mPhone.getPhoneId(), mId,
-                    mApnSetting != null ? (long) mApnSetting.getApnTypeBitmask() : 0L,
+                    mPhone.getPhoneId(), mId, (long) apnTypeBitmask,
                     mApnSetting != null
                         ? mApnSetting.canHandleType(ApnSetting.TYPE_DEFAULT) : false);
             setHandoverState(HANDOVER_STATE_IDLE);
@@ -2261,7 +2275,7 @@
                     .registerCarrierPrivilegesListener(
                             getHandler(), EVENT_CARRIER_PRIVILEGED_UIDS_CHANGED, null);
             notifyDataConnectionState();
-            mDataCallSessionStats.onSetupDataCall(mApnSetting.getApnTypeBitmask());
+            mDataCallSessionStats.onSetupDataCall(apnTypeBitmask);
         }
         @Override
         public boolean processMessage(Message msg) {
@@ -2547,7 +2561,7 @@
 
             TelephonyMetrics.getInstance().writeRilDataCallEvent(mPhone.getPhoneId(),
                     mCid, mApnSetting.getApnTypeBitmask(), RilDataCall.State.DISCONNECTED);
-            mDataCallSessionStats.onDataCallDisconnected(mCid);
+            mDataCallSessionStats.onDataCallDisconnected();
 
             mPhone.getCarrierPrivilegesTracker().unregisterCarrierPrivilegesListener(getHandler());
         }
@@ -2659,10 +2673,7 @@
                         mNetworkAgent.sendLinkProperties(mLinkProperties, DataConnection.this);
                     }
                     retVal = HANDLED;
-                    // this is for DRS or RAT changes, so only call onRatChanged if RAT is changed
-                    if (mRilRat != 0) {
-                        mDataCallSessionStats.onRatChanged(mRilRat);
-                    }
+                    mDataCallSessionStats.onDrsOrRatChanged(mRilRat);
                     break;
                 }
                 case EVENT_NR_FREQUENCY_CHANGED:
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataServiceManager.java b/src/java/com/android/internal/telephony/dataconnection/DataServiceManager.java
index 82180a1..c67ce1c 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DataServiceManager.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DataServiceManager.java
@@ -51,6 +51,7 @@
 import android.telephony.data.DataServiceCallback;
 import android.telephony.data.IDataService;
 import android.telephony.data.IDataServiceCallback;
+import android.telephony.data.SliceInfo;
 import android.text.TextUtils;
 
 import com.android.internal.telephony.Phone;
@@ -613,12 +614,15 @@
      * @param pduSessionId The pdu session id to be used for this data call.  A value of -1 means
      *                     no pdu session id was attached to this call.
      *                     Reference: 3GPP TS 24.007 section 11.2.3.1b
+     * @param sliceInfo The slice that represents S-NSSAI.
+     *                  Reference: 3GPP TS 24.501
      * @param onCompleteMessage The result message for this request. Null if the client does not
      *        care about the result.
      */
     public void setupDataCall(int accessNetworkType, DataProfile dataProfile, boolean isRoaming,
                               boolean allowRoaming, int reason, LinkProperties linkProperties,
-                              int pduSessionId, Message onCompleteMessage) {
+                              int pduSessionId, @Nullable  SliceInfo sliceInfo,
+                              Message onCompleteMessage) {
         if (DBG) log("setupDataCall");
         if (!mBound) {
             loge("setupDataCall: Data service not bound.");
@@ -634,7 +638,8 @@
             sendMessageDelayed(obtainMessage(EVENT_WATCHDOG_TIMEOUT, callback),
                     REQUEST_UNRESPONDED_TIMEOUT);
             mIDataService.setupDataCall(mPhone.getPhoneId(), accessNetworkType, dataProfile,
-                    isRoaming, allowRoaming, reason, linkProperties, pduSessionId, callback);
+                    isRoaming, allowRoaming, reason, linkProperties, pduSessionId, sliceInfo,
+                    callback);
         } catch (RemoteException e) {
             loge("setupDataCall: Cannot invoke setupDataCall on data service.");
             mMessageMap.remove(callback.asBinder());
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcController.java b/src/java/com/android/internal/telephony/dataconnection/DcController.java
index 95d35bf..6f5d8ee 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DcController.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcController.java
@@ -304,6 +304,7 @@
                     // Its active so update the DataConnections link properties
                     UpdateLinkPropertyResult result = dc.updateLinkProperty(newState);
                     dc.updateQosParameters(newState);
+                    dc.updateSliceInfo(newState);
                     if (result.oldLp.equals(result.newLp)) {
                         if (DBG) log("onDataStateChanged: no change");
                     } else {
diff --git a/src/java/com/android/internal/telephony/euicc/EuiccConnector.java b/src/java/com/android/internal/telephony/euicc/EuiccConnector.java
index f135e62..d58c5d4 100644
--- a/src/java/com/android/internal/telephony/euicc/EuiccConnector.java
+++ b/src/java/com/android/internal/telephony/euicc/EuiccConnector.java
@@ -404,6 +404,8 @@
 
         start();
 
+        // All app package changes could trigger the package monitor receiver. It is not limited to
+        // apps extended from EuiccService.
         mPackageMonitor.register(mContext, null /* thread */, null /* user */);
         mContext.registerReceiver(
                 mUserUnlockedReceiver, new IntentFilter(Intent.ACTION_USER_UNLOCKED));
@@ -555,10 +557,10 @@
                 mSelectedComponent = findBestComponent();
                 if (mSelectedComponent != null) {
                     transitionTo(mAvailableState);
+                    updateSubscriptionInfoListForAllAccessibleEuiccs();
                 } else if (getCurrentState() != mUnavailableState) {
                     transitionTo(mUnavailableState);
                 }
-                updateSubscriptionInfoListForAllAccessibleEuiccs();
                 return HANDLED;
             } else if (isEuiccCommand(message.what)) {
                 BaseEuiccCommandCallback callback = getCallback(message);
@@ -651,11 +653,16 @@
                 if (bestComponent == null) {
                     isSameComponent = mSelectedComponent != null;
                 } else {
+                    // Checks whether the bound component is the same as the best component. If it
+                    // is not, set isSameComponent to false and the connector will bind the best
+                    // component instead.
                     isSameComponent = mSelectedComponent == null
                             || Objects.equals(new ComponentName(bestComponent.packageName,
                             bestComponent.name),
                         new ComponentName(mSelectedComponent.packageName, mSelectedComponent.name));
                 }
+                // Checks whether the bound component is impacted by the package changes. If it is,
+                // change the forceRebind to true so the connector will re-bind the component.
                 boolean forceRebind = bestComponent != null
                         && Objects.equals(bestComponent.packageName, affectedPackage);
                 if (!isSameComponent || forceRebind) {
@@ -666,8 +673,8 @@
                     } else {
                         transitionTo(mBindingState);
                     }
+                    updateSubscriptionInfoListForAllAccessibleEuiccs();
                 }
-                updateSubscriptionInfoListForAllAccessibleEuiccs();
                 return HANDLED;
             } else if (message.what == CMD_CONNECT_TIMEOUT) {
                 transitionTo(mAvailableState);
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCommandInterface.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCommandInterface.java
index 8383085..3ca6e87 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCommandInterface.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCommandInterface.java
@@ -26,6 +26,7 @@
 import android.telephony.SignalThresholdInfo;
 import android.telephony.TelephonyManager;
 import android.telephony.data.DataProfile;
+import android.telephony.data.SliceInfo;
 import android.telephony.emergency.EmergencyNumber;
 
 import com.android.internal.telephony.BaseCommands;
@@ -284,7 +285,7 @@
     @Override
     public void setupDataCall(int accessNetworkType, DataProfile dataProfile, boolean isRoaming,
                               boolean allowRoaming, int reason, LinkProperties linkProperties,
-                              int pduSessionId, Message result) {
+                              int pduSessionId, SliceInfo sliceInfo, Message result) {
     }
 
     @Override
diff --git a/src/java/com/android/internal/telephony/metrics/DataCallSessionStats.java b/src/java/com/android/internal/telephony/metrics/DataCallSessionStats.java
index a846d9d..3b4fc69 100644
--- a/src/java/com/android/internal/telephony/metrics/DataCallSessionStats.java
+++ b/src/java/com/android/internal/telephony/metrics/DataCallSessionStats.java
@@ -22,15 +22,19 @@
 import static com.android.internal.telephony.TelephonyStatsLog.DATA_CALL_SESSION__DEACTIVATE_REASON__DEACTIVATE_REASON_UNKNOWN;
 import static com.android.internal.telephony.TelephonyStatsLog.DATA_CALL_SESSION__IP_TYPE__APN_PROTOCOL_IPV4;
 
+import android.os.SystemClock;
 import android.telephony.Annotation.ApnType;
 import android.telephony.Annotation.NetworkType;
 import android.telephony.DataFailCause;
 import android.telephony.ServiceState;
+import android.telephony.ServiceState.RilRadioTechnology;
+import android.telephony.TelephonyManager;
 import android.telephony.data.ApnSetting.ProtocolType;
 import android.telephony.data.DataCallResponse;
 import android.telephony.data.DataService;
 import android.telephony.data.DataService.DeactivateDataReason;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneFactory;
 import com.android.internal.telephony.ServiceStateTracker;
@@ -40,7 +44,7 @@
 
 import java.util.Random;
 
-/** Collects data call change events per DcTracker for the pulled atom. */
+/** Collects data call change events per DataConnection for the pulled atom. */
 public class DataCallSessionStats {
     private static final String TAG = DataCallSessionStats.class.getSimpleName();
 
@@ -58,22 +62,18 @@
         mPhone = phone;
     }
 
-    /** create a new ongoing atom when data cal is set up */
+    /** Creates a new ongoing atom when data call is set up. */
     public synchronized void onSetupDataCall(@ApnType int apnTypeBitMask) {
         if (!mOnRatChangedCalledBeforeSetup) {
-            // there shouldn't be an ongoing dataCall here, if that's the case, it means that
+            // there shouldn't be an ongoing data call here, if that's the case, it means that
             // deactivateDataCall hasn't been processed properly, so we save the previous atom here
             // and move on to create a new atom.
             if (mOngoingDataCall != null) {
                 mOngoingDataCall.failureCause = DataFailCause.UNKNOWN;
-                mOngoingDataCall.durationMinutes =
-                        convertMillisToMinutes(System.currentTimeMillis() - mStartTime);
-                mOngoingDataCall.ongoing = false;
-                mAtomsStorage.addDataCallSession(mOngoingDataCall);
-                mOngoingDataCall = null;
+                onDataCallDisconnected();
             }
             mOngoingDataCall = getDefaultProto(apnTypeBitMask);
-            mStartTime = System.currentTimeMillis();
+            mStartTime = getTimeMillis();
         } else {
             // if onRatChanged was called before onSetupDataCall, the atom is already initialized
             // but apnTypeBitMask is initialized to 0, so we need to update it
@@ -83,7 +83,8 @@
     }
 
     /**
-     * update the ongoing dataCall's atom for data call response event
+     * Updates the ongoing dataCall's atom for data call response event.
+     *
      * @param response setup Data call response
      * @param radioTechnology The data call RAT
      * @param apnTypeBitmask APN type bitmask
@@ -92,7 +93,7 @@
      */
     public synchronized void onSetupDataCallResponse(
             DataCallResponse response,
-            @ServiceState.RilRadioTechnology int radioTechnology,
+            @RilRadioTechnology int radioTechnology,
             @ApnType int apnTypeBitmask,
             @ProtocolType int protocol,
             int failureCause) {
@@ -102,8 +103,7 @@
             loge("onSetupDataCallResponse: no DataCallSession atom has been initiated.");
             return;
         }
-        mOngoingDataCall.ratAtEnd =
-                ServiceState.rilRadioTechnologyToNetworkType(radioTechnology);
+        mOngoingDataCall.ratAtEnd = ServiceState.rilRadioTechnologyToNetworkType(radioTechnology);
 
         // only set if apn hasn't been set during setup
         if (mOngoingDataCall.apnTypeBitmask == 0) {
@@ -128,11 +128,11 @@
     }
 
     /**
-     * update the ongoing dataCall's atom when data call is deactivated
+     * Updates the ongoing dataCall's atom when data call is deactivated.
      *
      * @param reason Deactivate reason
      */
-    public void setDeactivateDataCallReason(@DeactivateDataReason int reason) {
+    public synchronized void setDeactivateDataCallReason(@DeactivateDataReason int reason) {
         // there should've been another call to initiate the atom,
         // so this method is being called out of order -> no metric will be logged
         if (mOngoingDataCall == null) {
@@ -161,42 +161,43 @@
         mOngoingDataCall.oosAtEnd = getIsOos();
     }
 
-    /**
-     * store the atom, when DataConnection reaches DISCONNECTED state
-     *
-     * @param cid Context Id, uniquely identifies the call
-     */
-    public void onDataCallDisconnected(int cid) {
+    /** Stores the atom when DataConnection reaches DISCONNECTED state. */
+    public synchronized void onDataCallDisconnected() {
         // there should've been another call to initiate the atom,
         // so this method is being called out of order -> no atom will be saved
         if (mOngoingDataCall == null) {
             loge("onSetupDataCallResponse: no DataCallSession atom has been initiated.");
             return;
         }
-        mOngoingDataCall.carrierId = cid;
         mOngoingDataCall.ongoing = false;
-        mOngoingDataCall.durationMinutes =
-                convertMillisToMinutes(System.currentTimeMillis() - mStartTime);
+        mOngoingDataCall.durationMinutes = convertMillisToMinutes(getTimeMillis() - mStartTime);
         // store for the data call list event, after DataCall is disconnected and entered into
         // inactive mode
         mAtomsStorage.addDataCallSession(mOngoingDataCall);
         mOngoingDataCall = null;
     }
 
-    /** Updates this RAT when it changes. */
-    public synchronized void onRatChanged(@ServiceState.RilRadioTechnology int radioTechnology) {
+    /**
+     * Updates the atom when data registration state or RAT changes.
+     *
+     * <p>NOTE: in {@link ServiceStateTracker}, change of channel number will trigger data
+     * registration state change.
+     */
+    public synchronized void onDrsOrRatChanged(@RilRadioTechnology int radioTechnology) {
+        @NetworkType int rat = ServiceState.rilRadioTechnologyToNetworkType(radioTechnology);
         // if no data call is initiated, or we have a new data call while the last one has ended
         // because onRatChanged might be called before onSetupDataCall
         if (mOngoingDataCall == null) {
             mOngoingDataCall = getDefaultProto(0);
-            mStartTime = System.currentTimeMillis();
+            mOngoingDataCall.ratAtEnd = rat;
+            mStartTime = getTimeMillis();
             mOnRatChangedCalledBeforeSetup = true;
         }
-        @NetworkType int rat = ServiceState.rilRadioTechnologyToNetworkType(radioTechnology);
-        if (mOngoingDataCall.ratAtEnd != rat) {
+        if (rat != TelephonyManager.NETWORK_TYPE_UNKNOWN && mOngoingDataCall.ratAtEnd != rat) {
             mOngoingDataCall.ratSwitchCount++;
             mOngoingDataCall.ratAtEnd = rat;
         }
+        mOngoingDataCall.bandAtEnd = ServiceStateStats.getBand(mPhone, rat);
     }
 
     private static long convertMillisToMinutes(long millis) {
@@ -249,4 +250,9 @@
     private void loge(String format, Object... args) {
         Rlog.e(TAG, "[" + mPhone.getPhoneId() + "]" + String.format(format, args));
     }
+
+    @VisibleForTesting
+    protected long getTimeMillis() {
+        return SystemClock.elapsedRealtime();
+    }
 }
diff --git a/src/java/com/android/internal/telephony/metrics/DataStallRecoveryStats.java b/src/java/com/android/internal/telephony/metrics/DataStallRecoveryStats.java
index 7ee6675..77892bb 100644
--- a/src/java/com/android/internal/telephony/metrics/DataStallRecoveryStats.java
+++ b/src/java/com/android/internal/telephony/metrics/DataStallRecoveryStats.java
@@ -43,13 +43,14 @@
 
         int carrierId = phone.getCarrierId();
         int rat = getRat(phone);
+        int band = ServiceStateStats.getBand(phone, rat);
         // the number returned here matches the SignalStrength enum we have
         int signalStrength = phone.getSignalStrength().getLevel();
         boolean isOpportunistic = getIsOpportunistic(phone);
         boolean isMultiSim = SimSlotState.getCurrentState().numActiveSims > 1;
 
         TelephonyStatsLog.write(TelephonyStatsLog.DATA_STALL_RECOVERY_REPORTED, carrierId, rat,
-                signalStrength, recoveryAction, isOpportunistic, isMultiSim);
+                signalStrength, recoveryAction, isOpportunistic, isMultiSim, band);
     }
 
     private static @NetworkType int getRat(Phone phone) {
diff --git a/src/java/com/android/internal/telephony/metrics/MetricsCollector.java b/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
index 8b2796e..ce01b7e 100644
--- a/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
+++ b/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
@@ -517,8 +517,10 @@
                 .writeInt(dataCallSession.failureCause)
                 .writeInt(dataCallSession.suggestedRetryMillis)
                 .writeInt(dataCallSession.deactivateReason)
-                .writeLong(dataCallSession.durationMinutes)
+                .writeLong(round(
+                        dataCallSession.durationMinutes, DURATION_BUCKET_MILLIS / MINUTE_IN_MILLIS))
                 .writeBoolean(dataCallSession.ongoing)
+                .writeInt(dataCallSession.bandAtEnd)
                 .build();
     }
 
@@ -593,6 +595,6 @@
 
     /** Returns the value rounded to the bucket. */
     private static long round(long value, long bucket) {
-        return ((value + bucket / 2) / bucket) * bucket;
+        return bucket == 0 ? value : ((value + bucket / 2) / bucket) * bucket;
     }
 }
diff --git a/src/java/com/android/internal/telephony/metrics/ServiceStateStats.java b/src/java/com/android/internal/telephony/metrics/ServiceStateStats.java
index 9cbc406..058d81b 100644
--- a/src/java/com/android/internal/telephony/metrics/ServiceStateStats.java
+++ b/src/java/com/android/internal/telephony/metrics/ServiceStateStats.java
@@ -19,6 +19,7 @@
 import android.annotation.Nullable;
 import android.os.SystemClock;
 import android.telephony.AccessNetworkConstants;
+import android.telephony.AccessNetworkUtils;
 import android.telephony.Annotation.NetworkType;
 import android.telephony.NetworkRegistrationInfo;
 import android.telephony.ServiceState;
@@ -27,6 +28,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.ServiceStateTracker;
 import com.android.internal.telephony.nano.PersistAtomsProto.CellularDataServiceSwitch;
 import com.android.internal.telephony.nano.PersistAtomsProto.CellularServiceState;
 import com.android.telephony.Rlog;
@@ -122,6 +124,56 @@
         }
     }
 
+    /** Returns the service state for the given phone, or {@code null} if it cannot be obtained. */
+    @Nullable
+    private static ServiceState getServiceStateForPhone(Phone phone) {
+        ServiceStateTracker serviceStateTracker = phone.getServiceStateTracker();
+        return serviceStateTracker != null ? serviceStateTracker.getServiceState() : null;
+    }
+
+    /**
+     * Returns the band used from the given phone and RAT, or {@code 0} if it is invalid or cannot
+     * be determined.
+     */
+    static int getBand(Phone phone, @NetworkType int rat) {
+        ServiceState serviceState = getServiceStateForPhone(phone);
+        return getBand(serviceState, rat);
+    }
+
+    /**
+     * Returns the band used from the given service state and RAT, or {@code 0} if it is invalid or
+     * cannot be determined.
+     */
+    static int getBand(@Nullable ServiceState serviceState, @NetworkType int rat) {
+        if (serviceState == null) {
+            return 0; // Band unknown
+        }
+        int chNumber = serviceState.getChannelNumber();
+        int band;
+        switch (rat) {
+            case TelephonyManager.NETWORK_TYPE_GSM:
+            case TelephonyManager.NETWORK_TYPE_GPRS:
+            case TelephonyManager.NETWORK_TYPE_EDGE:
+                band = AccessNetworkUtils.getOperatingBandForArfcn(chNumber);
+                break;
+            case TelephonyManager.NETWORK_TYPE_UMTS:
+            case TelephonyManager.NETWORK_TYPE_HSDPA:
+            case TelephonyManager.NETWORK_TYPE_HSUPA:
+            case TelephonyManager.NETWORK_TYPE_HSPA:
+            case TelephonyManager.NETWORK_TYPE_HSPAP:
+                band = AccessNetworkUtils.getOperatingBandForUarfcn(chNumber);
+                break;
+            case TelephonyManager.NETWORK_TYPE_LTE:
+            case TelephonyManager.NETWORK_TYPE_LTE_CA:
+                band = AccessNetworkUtils.getOperatingBandForEarfcn(chNumber);
+                break;
+            default:
+                band = 0;
+                break;
+        }
+        return band == AccessNetworkUtils.INVALID_BAND ? 0 : band;
+    }
+
     private static CellularServiceState copyOf(CellularServiceState state) {
         // MessageNano does not support clone, have to copy manually
         CellularServiceState copy = new CellularServiceState();
diff --git a/src/java/com/android/internal/telephony/metrics/VoiceCallSessionStats.java b/src/java/com/android/internal/telephony/metrics/VoiceCallSessionStats.java
index 6b6da10..7113d13 100644
--- a/src/java/com/android/internal/telephony/metrics/VoiceCallSessionStats.java
+++ b/src/java/com/android/internal/telephony/metrics/VoiceCallSessionStats.java
@@ -46,7 +46,6 @@
 import android.os.SystemClock;
 import android.telecom.VideoProfile;
 import android.telecom.VideoProfile.VideoState;
-import android.telephony.AccessNetworkUtils;
 import android.telephony.Annotation.NetworkType;
 import android.telephony.DisconnectCause;
 import android.telephony.ServiceState;
@@ -515,7 +514,7 @@
 
     private void updateRatTracker(ServiceState state) {
         @NetworkType int rat = getRat(state);
-        int band = getBand(rat, state.getChannelNumber());
+        int band = ServiceStateStats.getBand(state, rat);
 
         mRatUsage.add(mPhone.getCarrierId(), rat, getTimeMillis(), getConnectionIds());
         for (int i = 0; i < mCallProtos.size(); i++) {
@@ -574,33 +573,6 @@
         return isWifiCall ? TelephonyManager.NETWORK_TYPE_IWLAN : state.getVoiceNetworkType();
     }
 
-    /** Returns the band associated with a given rat and channel number. */
-    private int getBand(@NetworkType int rat, int chNumber) {
-        int band;
-        switch (rat) {
-            case TelephonyManager.NETWORK_TYPE_GSM:
-            case TelephonyManager.NETWORK_TYPE_GPRS:
-            case TelephonyManager.NETWORK_TYPE_EDGE:
-                band = AccessNetworkUtils.getOperatingBandForArfcn(chNumber);
-                break;
-            case TelephonyManager.NETWORK_TYPE_UMTS:
-            case TelephonyManager.NETWORK_TYPE_HSDPA:
-            case TelephonyManager.NETWORK_TYPE_HSUPA:
-            case TelephonyManager.NETWORK_TYPE_HSPA:
-            case TelephonyManager.NETWORK_TYPE_HSPAP:
-                band = AccessNetworkUtils.getOperatingBandForUarfcn(chNumber);
-                break;
-            case TelephonyManager.NETWORK_TYPE_LTE:
-            case TelephonyManager.NETWORK_TYPE_LTE_CA:
-                band = AccessNetworkUtils.getOperatingBandForEarfcn(chNumber);
-                break;
-            default:
-                band = 0;
-                break;
-        }
-        return band == AccessNetworkUtils.INVALID_BAND ? 0 : band;
-    }
-
     /** Returns the signal strength. */
     private int getSignalStrength(@NetworkType int rat) {
         if (rat == TelephonyManager.NETWORK_TYPE_IWLAN) {
diff --git a/src/java/com/android/internal/telephony/sip/SipCommandInterface.java b/src/java/com/android/internal/telephony/sip/SipCommandInterface.java
index d1d2d8a..8149285 100644
--- a/src/java/com/android/internal/telephony/sip/SipCommandInterface.java
+++ b/src/java/com/android/internal/telephony/sip/SipCommandInterface.java
@@ -26,6 +26,7 @@
 import android.telephony.SignalThresholdInfo;
 import android.telephony.TelephonyManager;
 import android.telephony.data.DataProfile;
+import android.telephony.data.SliceInfo;
 import android.telephony.emergency.EmergencyNumber;
 
 import com.android.internal.telephony.BaseCommands;
@@ -285,7 +286,7 @@
     @Override
     public void setupDataCall(int accessNetworkType, DataProfile dataProfile, boolean isRoaming,
                               boolean allowRoaming, int reason, LinkProperties linkProperties,
-                              int pduSessionId, Message result) {
+                              int pduSessionId, SliceInfo sliceInfo, Message result) {
     }
 
     @Override
diff --git a/src/java/com/android/internal/telephony/vendor/VendorSubscriptionInfoUpdater.java b/src/java/com/android/internal/telephony/vendor/VendorSubscriptionInfoUpdater.java
index 9a2f566..b6c6243 100644
--- a/src/java/com/android/internal/telephony/vendor/VendorSubscriptionInfoUpdater.java
+++ b/src/java/com/android/internal/telephony/vendor/VendorSubscriptionInfoUpdater.java
@@ -78,41 +78,6 @@
     }
 
     @Override
-    protected void handleSimReady(int phoneId) {
-        List<Integer> cardIds = new ArrayList<>();
-        Rlog.d(LOG_TAG, "handleSimReady: phoneId: " + phoneId);
-
-        if (sIccId[phoneId] != null && sIccId[phoneId].equals(ICCID_STRING_FOR_NO_SIM)) {
-            Rlog.d(LOG_TAG, " SIM" + (phoneId + 1) + " hot plug in");
-            sIccId[phoneId] = null;
-        }
-        UiccSlot uiccSlot = UiccController.getInstance().getUiccSlotForPhone(phoneId);
-        if (uiccSlot == null) {
-            Rlog.d(LOG_TAG, "handleSimReady: uiccSlot null");
-            return;
-        }
-
-        String iccId = uiccSlot.getIccId();
-        if (IccUtils.stripTrailingFs(iccId) == null) {
-            Rlog.d(LOG_TAG, "handleSimReady: IccID null");
-            return;
-        }
-        sIccId[phoneId] = IccUtils.stripTrailingFs(iccId);
-
-        updateSubscriptionInfoByIccId(phoneId, true /* updateEmbeddedSubs */);
-
-        cardIds.add(getCardIdFromPhoneId(phoneId));
-        updateEmbeddedSubscriptions(cardIds, (hasChanges) -> {
-            if (hasChanges) {
-                mSubscriptionController.notifySubscriptionInfoChanged();
-            }
-        });
-        broadcastSimStateChanged(phoneId, IccCardConstants.INTENT_VALUE_ICC_READY, null);
-        broadcastSimCardStateChanged(phoneId, TelephonyManager.SIM_STATE_PRESENT);
-        broadcastSimApplicationStateChanged(phoneId, TelephonyManager.SIM_STATE_NOT_READY);
-    }
-
-    @Override
     protected void handleSimLoaded(int phoneId) {
         // mIsRecordUpdateRequired set to false if sIccId has a valid Iccid to skip
         // adding subId once again from here.
diff --git a/tests/telephonytests/src/com/android/internal/telephony/RILTest.java b/tests/telephonytests/src/com/android/internal/telephony/RILTest.java
index 11ab18f..6c264ae 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/RILTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/RILTest.java
@@ -157,8 +157,6 @@
 import android.telephony.data.DataCallResponse;
 import android.telephony.data.DataProfile;
 import android.telephony.data.EpsQos;
-import android.telephony.data.NrQos;
-import android.telephony.data.Qos;
 import android.telephony.data.QosFilter;
 import android.telephony.data.QosSession;
 import android.testing.AndroidTestingRunner;
@@ -2617,7 +2615,7 @@
 
         mRILUnderTest.setupDataCall(AccessNetworkConstants.AccessNetworkType.EUTRAN, dp, false,
                 false, 0, null,
-                DataCallResponse.PDU_SESSION_ID_NOT_SET, obtainMessage());
+                DataCallResponse.PDU_SESSION_ID_NOT_SET, null, obtainMessage());
         ArgumentCaptor<DataProfileInfo> dpiCaptor = ArgumentCaptor.forClass(DataProfileInfo.class);
         verify(mRadioProxy).setupDataCall(
                 mSerialNumberCaptor.capture(), eq(AccessNetworkConstants.AccessNetworkType.EUTRAN),
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SimulatedCommands.java b/tests/telephonytests/src/com/android/internal/telephony/SimulatedCommands.java
index 53c2160..a7e9336 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SimulatedCommands.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SimulatedCommands.java
@@ -50,6 +50,7 @@
 import android.telephony.data.ApnSetting;
 import android.telephony.data.DataCallResponse;
 import android.telephony.data.DataProfile;
+import android.telephony.data.SliceInfo;
 import android.telephony.emergency.EmergencyNumber;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -1178,10 +1179,10 @@
     @Override
     public void setupDataCall(int accessNetworkType, DataProfile dataProfile, boolean isRoaming,
                               boolean allowRoaming, int reason, LinkProperties linkProperties,
-                              int pduSessionId, Message result) {
+                              int pduSessionId, SliceInfo sliceInfo, Message result) {
 
         SimulatedCommandsVerifier.getInstance().setupDataCall(accessNetworkType, dataProfile,
-                isRoaming, allowRoaming, reason, linkProperties, pduSessionId, result);
+                isRoaming, allowRoaming, reason, linkProperties, pduSessionId, sliceInfo, result);
 
         if (mSetupDataCallResult == null) {
             try {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SimulatedCommandsVerifier.java b/tests/telephonytests/src/com/android/internal/telephony/SimulatedCommandsVerifier.java
index f1cf40c..e15613a 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SimulatedCommandsVerifier.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SimulatedCommandsVerifier.java
@@ -26,6 +26,7 @@
 import android.telephony.SignalThresholdInfo;
 import android.telephony.TelephonyManager;
 import android.telephony.data.DataProfile;
+import android.telephony.data.SliceInfo;
 import android.telephony.emergency.EmergencyNumber;
 
 import com.android.internal.telephony.CommandsInterface;
@@ -1202,7 +1203,7 @@
     @Override
     public void setupDataCall(int accessNetworkType, DataProfile dataProfile, boolean isRoaming,
                               boolean allowRoaming, int reason, LinkProperties linkProperties,
-                              int pduSessionId, Message result) {
+                              int pduSessionId, SliceInfo sliceInfo, Message result) {
     }
 
     @Override
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SubscriptionControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/SubscriptionControllerTest.java
index 4d10b0a..6566d3d 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SubscriptionControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SubscriptionControllerTest.java
@@ -24,6 +24,7 @@
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.any;
@@ -1914,4 +1915,21 @@
         assertFalse(mSubscriptionControllerUT.getActiveSubscriptionInfo(
                 1, mContext.getOpPackageName(), null).areUiccApplicationsEnabled());
     }
+
+    @Test
+    @SmallTest
+    public void testInsertEmptySubInfoRecord_returnsNull_ifRecordExists() {
+        final String mockedIccid = "123456789";
+        final int mockedSlotIndex = 1;
+
+        assertNotNull(mSubscriptionControllerUT.insertEmptySubInfoRecord(
+                mockedIccid, mockedSlotIndex));
+        // Insert second time with the same iccid should result in no-op and return null.
+        assertNull(mSubscriptionControllerUT.insertEmptySubInfoRecord(
+                mockedIccid, mockedSlotIndex));
+        assertEquals(
+                1,
+                mSubscriptionControllerUT
+                        .getAllSubInfoList(mCallingPackage, mCallingFeature).size());
+    }
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoUpdaterTest.java b/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoUpdaterTest.java
index ac0c636..f9199f7 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoUpdaterTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoUpdaterTest.java
@@ -902,4 +902,44 @@
         verify(mSubscriptionController, times(1)).refreshCachedActiveSubscriptionInfoList();
         verify(mSubscriptionController, times(1)).notifySubscriptionInfoChanged();
     }
+
+    @Test
+    @SmallTest
+    public void testSimReady() throws Exception {
+        replaceInstance(SubscriptionInfoUpdater.class, "sIccId", null,new String[]{""});
+
+        doReturn(FAKE_ICCID_1).when(mUiccSlot).getIccId();
+
+        mUpdater.updateInternalIccState(
+            IccCardConstants.INTENT_VALUE_ICC_READY, "TESTING", FAKE_SUB_ID_1);
+        processAllMessages();
+
+        verify(mSubscriptionController).clearSubInfoRecord(eq(FAKE_SUB_ID_1));
+        verify(mSubscriptionManager, times(1)).addSubscriptionInfoRecord(
+                eq(FAKE_ICCID_1), eq(FAKE_SUB_ID_1));
+        assertTrue(mUpdater.isSubInfoInitialized());
+        verify(mSubscriptionController, times(1)).notifySubscriptionInfoChanged();
+    }
+
+    @Test
+    @SmallTest
+    public void testSimReadyAndLoaded() throws Exception {
+        replaceInstance(SubscriptionInfoUpdater.class, "sIccId", null,new String[]{""});
+
+        doReturn(null).when(mUiccSlot).getIccId();
+
+        mUpdater.updateInternalIccState(
+            IccCardConstants.INTENT_VALUE_ICC_READY, "TESTING", FAKE_SUB_ID_1);
+        processAllMessages();
+
+        verify(mSubscriptionManager, times(0)).addSubscriptionInfoRecord(
+                eq(FAKE_ICCID_1), eq(FAKE_SUB_ID_1));
+
+        loadSim();
+
+        SubscriptionManager mSubscriptionManager = SubscriptionManager.from(mContext);
+        verify(mSubscriptionManager, times(1)).addSubscriptionInfoRecord(
+                eq(FAKE_ICCID_1), eq(FAKE_SUB_ID_1));
+        verify(mSubscriptionController, times(1)).notifySubscriptionInfoChanged();
+    }
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataConnectionTest.java b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataConnectionTest.java
index 2298f1b..9cc9da2 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataConnectionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataConnectionTest.java
@@ -390,7 +390,7 @@
         verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
                 eq(AccessNetworkType.UTRAN), dpCaptor.capture(), eq(false),
                 eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
-                anyInt(), any(Message.class));
+                anyInt(), any(), any(Message.class));
 
         assertEquals("spmode.ne.jp", dpCaptor.getValue().getApn());
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java
index 365be1a..80b2553 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java
@@ -691,7 +691,7 @@
         verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
                 eq(AccessNetworkType.EUTRAN), any(DataProfile.class),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
-                anyInt(), any(Message.class));
+                anyInt(), any(), any(Message.class));
     }
 
     // Test the normal data call setup scenario.
@@ -720,7 +720,7 @@
         verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
                 eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
-                anyInt(), any(Message.class));
+                anyInt(), any(), any(Message.class));
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, NETWORK_TYPE_LTE_BITMASK);
 
         verifyDataConnected(FAKE_APN1);
@@ -762,7 +762,7 @@
         verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
                 eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
-                anyInt(), any(Message.class));
+                anyInt(), any(), any(Message.class));
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, NETWORK_TYPE_LTE_BITMASK);
 
         // This time we'll let RIL command succeed.
@@ -781,7 +781,7 @@
         verify(mSimulatedCommandsVerifier, times(2)).setupDataCall(
                 eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
-                anyInt(), any(Message.class));
+                anyInt(), any(), any(Message.class));
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN2, 0, 21, 1, NETWORK_TYPE_LTE_BITMASK);
 
         // Verify connected with APN2 setting.
@@ -806,7 +806,7 @@
         verify(mSimulatedCommandsVerifier, times(2)).setupDataCall(
                 eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
-                anyInt(), any(Message.class));
+                anyInt(), any(), any(Message.class));
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 5, 1, NETWORK_TYPE_LTE_BITMASK);
 
         logd("Sending DATA_DISABLED_CMD");
@@ -842,7 +842,7 @@
         verify(mSimulatedCommandsVerifier, times(2)).setupDataCall(
                 eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
-                anyInt(), any(Message.class));
+                anyInt(), any(), any(Message.class));
 
 
         List<DataProfile> dataProfiles = dpCaptor.getAllValues();
@@ -888,7 +888,7 @@
         verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
                 eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
-                anyInt(), any(Message.class));
+                anyInt(), any(), any(Message.class));
         assertEquals(DctConstants.State.IDLE, mDct.getState(PhoneConstants.APN_TYPE_DEFAULT));
         assertEquals(DctConstants.State.CONNECTED, mDct.getState(PhoneConstants.APN_TYPE_MMS));
     }
@@ -918,7 +918,7 @@
         verify(mSimulatedCommandsVerifier, times(2)).setupDataCall(
                 eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
-                anyInt(), any(Message.class));
+                anyInt(), any(), any(Message.class));
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, NETWORK_TYPE_LTE_BITMASK);
 
         //user is in roaming
@@ -969,7 +969,7 @@
         verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
                 eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
-                anyInt(), any(Message.class));
+                anyInt(), any(), any(Message.class));
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN3, 2, 64, 0, 0);
 
         assertTrue(mDct.isAnyDataConnected());
@@ -1018,7 +1018,7 @@
         verify(mSimulatedCommandsVerifier, times(2)).setupDataCall(
                 eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
-                anyInt(), any(Message.class));
+                anyInt(), any(), any(Message.class));
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 5, 1, NETWORK_TYPE_LTE_BITMASK);
         assertTrue(mDct.isAnyDataConnected());
 
@@ -1066,7 +1066,7 @@
 
         verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
                 eq(AccessNetworkType.EUTRAN), any(DataProfile.class), eq(false), eq(false),
-                eq(DataService.REQUEST_REASON_NORMAL), any(), anyInt(), any(Message.class));
+                eq(DataService.REQUEST_REASON_NORMAL), any(), anyInt(), any(), any(Message.class));
     }
 
     // Test the XCAP APN setup.
@@ -1080,7 +1080,7 @@
 
         verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
                 eq(AccessNetworkType.EUTRAN), any(DataProfile.class), eq(false), eq(false),
-                eq(DataService.REQUEST_REASON_NORMAL), any(), anyInt(), any(Message.class));
+                eq(DataService.REQUEST_REASON_NORMAL), any(), anyInt(), any(), any(Message.class));
     }
 
     @Test
@@ -1119,7 +1119,7 @@
         verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
                 eq(AccessNetworkType.EUTRAN), any(DataProfile.class),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
-                anyInt(), any(Message.class));
+                anyInt(), any(), any(Message.class));
     }
 
     // Test the unmetered default APN setup when data is disabled. Default APN should always honor
@@ -1141,7 +1141,7 @@
         verify(mSimulatedCommandsVerifier, never()).setupDataCall(
                 eq(AccessNetworkType.EUTRAN), any(DataProfile.class),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
-                anyInt(), any(Message.class));
+                anyInt(), any(), any(Message.class));
     }
 
 
@@ -1162,7 +1162,7 @@
 
         verify(mSimulatedCommandsVerifier, times(0)).setupDataCall(anyInt(), any(DataProfile.class),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
-                anyInt(), any(Message.class));
+                anyInt(), any(), any(Message.class));
     }
 
     // Test the restricted data request when data is disabled.
@@ -1189,7 +1189,7 @@
         waitForMs(200);
         verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(anyInt(), any(DataProfile.class),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
-                anyInt(), any(Message.class));
+                anyInt(), any(), any(Message.class));
     }
 
     // Test the restricted data request when roaming is disabled.
@@ -1217,7 +1217,7 @@
         waitForMs(200);
         verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(anyInt(), any(DataProfile.class),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
-                anyInt(), any(Message.class));
+                anyInt(), any(), any(Message.class));
     }
 
     // Test the default data when data is not connectable.
@@ -1234,7 +1234,7 @@
 
         verify(mSimulatedCommandsVerifier, times(0)).setupDataCall(anyInt(), any(DataProfile.class),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
-                anyInt(), any(Message.class));
+                anyInt(), any(), any(Message.class));
     }
 
     // Test the default data on IWLAN.
@@ -1257,7 +1257,7 @@
 
         verify(mSimulatedCommandsVerifier, times(0)).setupDataCall(anyInt(), any(DataProfile.class),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
-                anyInt(), any(Message.class));
+                anyInt(), any(), any(Message.class));
     }
 
     // Test the default data when the phone is in ECBM.
@@ -1274,7 +1274,7 @@
 
         verify(mSimulatedCommandsVerifier, times(0)).setupDataCall(anyInt(), any(DataProfile.class),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
-                anyInt(), any(Message.class));
+                anyInt(), any(), any(Message.class));
     }
 
     // Test update waiting apn list when on data rat change
@@ -1301,7 +1301,7 @@
         verify(mSimulatedCommandsVerifier).setupDataCall(
                 eq(AccessNetworkType.CDMA2000), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
-                anyInt(), any(Message.class));
+                anyInt(), any(), any(Message.class));
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN4, 0, 21, 2, NETWORK_TYPE_EHRPD_BITMASK);
         assertTrue(mDct.isAnyDataConnected());
 
@@ -1338,7 +1338,7 @@
         verify(mSimulatedCommandsVerifier).setupDataCall(
                 eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
-                anyInt(), any(Message.class));
+                anyInt(), any(), any(Message.class));
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, NETWORK_TYPE_LTE_BITMASK);
         assertTrue(mDct.isAnyDataConnected());
     }
@@ -1516,7 +1516,7 @@
         verify(mSimulatedCommandsVerifier).setupDataCall(
                 eq(AccessNetworkType.CDMA2000), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
-                anyInt(), any(Message.class));
+                anyInt(), any(), any(Message.class));
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN4, 0, 21, 2, NETWORK_TYPE_EHRPD_BITMASK);
         assertTrue(mDct.isAnyDataConnected());
 
@@ -1642,7 +1642,7 @@
         verify(mSimulatedCommandsVerifier, times(2)).setupDataCall(
                 eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
-                anyInt(), any(Message.class));
+                anyInt(), any(), any(Message.class));
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, NETWORK_TYPE_LTE_BITMASK);
 
         logd("Sending EVENT_NETWORK_STATUS_CHANGED");
@@ -1681,7 +1681,7 @@
         verify(mSimulatedCommandsVerifier, timeout(TEST_TIMEOUT).times(2)).setupDataCall(
                 eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
-                anyInt(), any(Message.class));
+                anyInt(), any(), any(Message.class));
         waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, NETWORK_TYPE_LTE_BITMASK);
 
@@ -1722,7 +1722,7 @@
         verify(mSimulatedCommandsVerifier, timeout(TEST_TIMEOUT).times(2)).setupDataCall(
                 eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
-                anyInt(), any(Message.class));
+                anyInt(), any(), any(Message.class));
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, NETWORK_TYPE_LTE_BITMASK);
 
         logd("Sending EVENT_NETWORK_STATUS_CHANGED false");
@@ -1760,7 +1760,7 @@
         verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
                 eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
-                anyInt(), any(Message.class));
+                anyInt(), any(), any(Message.class));
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, NETWORK_TYPE_LTE_BITMASK);
 
         logd("Sending EVENT_NETWORK_STATUS_CHANGED false");
@@ -1793,7 +1793,7 @@
         verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
                 eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
-                anyInt(), any(Message.class));
+                anyInt(), any(), any(Message.class));
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, NETWORK_TYPE_LTE_BITMASK);
 
         logd("Sending EVENT_NETWORK_STATUS_CHANGED false");
@@ -2146,7 +2146,7 @@
         verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
                 eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
                 eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
-                anyInt(), any(Message.class));
+                anyInt(), any(), any(Message.class));
         verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, NETWORK_TYPE_LTE_BITMASK);
 
         verifyDataConnected(FAKE_APN1);