Merge "Show phone numbers from all sources in hidden menu"
diff --git a/src/com/android/phone/CarrierConfigLoader.java b/src/com/android/phone/CarrierConfigLoader.java
index a463243..e276082 100644
--- a/src/com/android/phone/CarrierConfigLoader.java
+++ b/src/com/android/phone/CarrierConfigLoader.java
@@ -348,7 +348,7 @@
                     try {
                         ICarrierService carrierService =
                                 ICarrierService.Stub.asInterface(conn.service);
-                        carrierService.getCarrierConfig(carrierId, resultReceiver);
+                        carrierService.getCarrierConfig(phoneId, carrierId, resultReceiver);
                         logdWithLocalLog("Fetch config for default app: "
                                 + mPlatformCarrierConfigPackage
                                 + " carrierid: " + carrierId.toString());
@@ -488,7 +488,7 @@
                     try {
                         ICarrierService carrierService =
                                 ICarrierService.Stub.asInterface(conn.service);
-                        carrierService.getCarrierConfig(carrierId, resultReceiver);
+                        carrierService.getCarrierConfig(phoneId, carrierId, resultReceiver);
                         logdWithLocalLog("Fetch config for carrier app: "
                                 + getCarrierPackageForPhoneId(phoneId)
                                 + " carrierid: " + carrierId.toString());
@@ -656,7 +656,7 @@
                     try {
                         ICarrierService carrierService =
                                 ICarrierService.Stub.asInterface(conn.service);
-                        carrierService.getCarrierConfig(null, resultReceiver);
+                        carrierService.getCarrierConfig(phoneId, null, resultReceiver);
                         logdWithLocalLog("Fetch no sim config from default app: "
                                 + mPlatformCarrierConfigPackage);
                     } catch (RemoteException e) {
diff --git a/src/com/android/phone/ImsRcsController.java b/src/com/android/phone/ImsRcsController.java
index 3618d58..bf55764 100644
--- a/src/com/android/phone/ImsRcsController.java
+++ b/src/com/android/phone/ImsRcsController.java
@@ -17,9 +17,13 @@
 package com.android.phone;
 
 import android.Manifest;
+import android.app.compat.CompatChanges;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledAfter;
 import android.content.pm.PackageManager;
 import android.net.Uri;
 import android.os.Binder;
+import android.os.Build;
 import android.os.RemoteException;
 import android.os.ServiceSpecificException;
 import android.os.UserHandle;
@@ -73,6 +77,15 @@
     private Boolean mSingleRegistrationOverride;
 
     /**
+     * For apps targeting Android T and above, support the publishing state on APIs, such as
+     * {@code RcsUceAdapter#PUBLISH_STATE_PUBLISHING}
+     * @hide
+     */
+    @ChangeId
+    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S)
+    public static final long SUPPORT_PUBLISHING_STATE = 202894742;
+
+    /**
      * Initialize the singleton ImsRcsController instance.
      * This is only done once, at startup, from PhoneApp.onCreate().
      */
@@ -316,7 +329,9 @@
     @Override
     public @PublishState int getUcePublishState(int subId) {
         enforceReadPrivilegedPermission("getUcePublishState");
+        final int uid = Binder.getCallingUid();
         final long token = Binder.clearCallingIdentity();
+        boolean isSupportPublishingState = false;
         try {
             UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
                     UceControllerManager.class);
@@ -324,7 +339,10 @@
                 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
                         "This subscription does not support UCE.");
             }
-            return uceCtrlManager.getUcePublishState();
+            if (CompatChanges.isChangeEnabled(SUPPORT_PUBLISHING_STATE, uid)) {
+                isSupportPublishingState = true;
+            }
+            return uceCtrlManager.getUcePublishState(isSupportPublishingState);
         } catch (ImsException e) {
             throw new ServiceSpecificException(e.getCode(), e.getMessage());
         } finally {
@@ -466,7 +484,9 @@
     @Override
     public void registerUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
         enforceReadPrivilegedPermission("registerUcePublishStateCallback");
+        final int uid = Binder.getCallingUid();
         final long token = Binder.clearCallingIdentity();
+        boolean isSupportPublishingState = false;
         try {
             UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
                     UceControllerManager.class);
@@ -474,7 +494,11 @@
                 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
                         "This subscription does not support UCE.");
             }
-            uceCtrlManager.registerPublishStateCallback(c);
+
+            if (CompatChanges.isChangeEnabled(SUPPORT_PUBLISHING_STATE, uid)) {
+                isSupportPublishingState = true;
+            }
+            uceCtrlManager.registerPublishStateCallback(c, isSupportPublishingState);
         } catch (ImsException e) {
             throw new ServiceSpecificException(e.getCode(), e.getMessage());
         } finally {
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 50f1787..3b1cfbd 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -22,16 +22,18 @@
 import static com.android.internal.telephony.PhoneConstants.PHONE_TYPE_GSM;
 import static com.android.internal.telephony.PhoneConstants.PHONE_TYPE_IMS;
 import static com.android.internal.telephony.PhoneConstants.SUBSCRIPTION_KEY;
-import static com.android.internal.telephony.TelephonyStatsLog.RCS_CLIENT_PROVISIONING_STATS__EVENT__CLIENT_PARAMS_SENT;
 
 import android.Manifest;
 import android.Manifest.permission;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.app.AppOpsManager;
 import android.app.PendingIntent;
 import android.app.compat.CompatChanges;
 import android.app.role.RoleManager;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledSince;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -105,7 +107,9 @@
 import android.telephony.TelephonyScanManager;
 import android.telephony.ThermalMitigationRequest;
 import android.telephony.UiccCardInfo;
+import android.telephony.UiccPortInfo;
 import android.telephony.UiccSlotInfo;
+import android.telephony.UiccSlotMapping;
 import android.telephony.UssdResponse;
 import android.telephony.VisualVoicemailSmsFilterSettings;
 import android.telephony.data.ApnSetting;
@@ -182,7 +186,6 @@
 import com.android.internal.telephony.ims.ImsResolver;
 import com.android.internal.telephony.imsphone.ImsPhone;
 import com.android.internal.telephony.imsphone.ImsPhoneCallTracker;
-import com.android.internal.telephony.metrics.RcsStats;
 import com.android.internal.telephony.metrics.TelephonyMetrics;
 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
 import com.android.internal.telephony.uicc.IccIoResult;
@@ -218,6 +221,7 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -404,6 +408,16 @@
             "reset_network_erase_modem_config_enabled";
 
     private static final int SET_NETWORK_SELECTION_MODE_AUTOMATIC_TIMEOUT_MS = 2000; // 2 seconds
+    /**
+     * With support for MEP(multiple enabled profile) in Android T, a SIM card can have more than
+     * one ICCID active at the same time.
+     * Apps should use below API signatures if targeting SDK is T and beyond.
+     *
+     * @hide
+     */
+    @ChangeId
+    @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
+    public static final long GET_API_SIGNATURES_FROM_UICC_PORT_INFO = 202110963L;
 
     /**
      * A request object to use for transmitting data to an ICC.
@@ -1149,7 +1163,7 @@
                                     request.argument).first;
                     request.phone.setCallForwardingOption(
                             callForwardingInfoToSet.isEnabled()
-                                    ? CommandsInterface.CF_ACTION_ENABLE
+                                    ? CommandsInterface.CF_ACTION_REGISTRATION
                                     : CommandsInterface.CF_ACTION_DISABLE,
                             callForwardingInfoToSet.getReason(),
                             callForwardingInfoToSet.getNumber(),
@@ -3040,6 +3054,14 @@
     @SuppressWarnings("unchecked")
     public List<NeighboringCellInfo> getNeighboringCellInfo(String callingPackage,
             String callingFeatureId) {
+        try {
+            mApp.getSystemService(AppOpsManager.class)
+                    .checkPackage(Binder.getCallingUid(), callingPackage);
+        } catch (SecurityException e) {
+            EventLog.writeEvent(0x534e4554, "190619791", Binder.getCallingUid());
+            throw e;
+        }
+
         final int targetSdk = TelephonyPermissions.getTargetSdk(mApp, callingPackage);
         if (targetSdk >= android.os.Build.VERSION_CODES.Q) {
             throw new SecurityException(
@@ -3231,6 +3253,13 @@
 
     @Override
     public String getMeidForSlot(int slotIndex, String callingPackage, String callingFeatureId) {
+        try {
+            mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
+        } catch (SecurityException se) {
+            EventLog.writeEvent(0x534e4554, "186530496", Binder.getCallingUid());
+            throw new SecurityException("Package " + callingPackage + " does not belong to "
+                    + Binder.getCallingUid());
+        }
         Phone phone = PhoneFactory.getPhone(slotIndex);
         if (phone == null) {
             return null;
@@ -5001,6 +5030,13 @@
     @Override
     public int getNetworkTypeForSubscriber(int subId, String callingPackage,
             String callingFeatureId) {
+        try {
+            mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
+        } catch (SecurityException se) {
+            EventLog.writeEvent(0x534e4554, "186776740", Binder.getCallingUid());
+            throw new SecurityException("Package " + callingPackage + " does not belong to "
+                    + Binder.getCallingUid());
+        }
         final int targetSdk = TelephonyPermissions.getTargetSdk(mApp, callingPackage);
         if (targetSdk > android.os.Build.VERSION_CODES.Q) {
             return getDataNetworkTypeForSubscriber(subId, callingPackage, callingFeatureId);
@@ -6301,28 +6337,35 @@
      * Starts a new network scan and returns the id of this scan.
      *
      * @param subId id of the subscription
+     * @param renounceFineLocationAccess Set this to true if the caller would not like to receive
+     * location related information which will be sent if the caller already possess
+     * {@android.Manifest.permission.ACCESS_FINE_LOCATION} and do not renounce the permission
      * @param request contains the radio access networks with bands/channels to scan
      * @param messenger callback messenger for scan results or errors
      * @param binder for the purpose of auto clean when the user thread crashes
      * @return the id of the requested scan which can be used to stop the scan.
      */
     @Override
-    public int requestNetworkScan(int subId, NetworkScanRequest request, Messenger messenger,
+    public int requestNetworkScan(int subId, boolean renounceFineLocationAccess,
+            NetworkScanRequest request, Messenger messenger,
             IBinder binder, String callingPackage, String callingFeatureId) {
         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
                 mApp, subId, "requestNetworkScan");
         LocationAccessPolicy.LocationPermissionResult locationResult =
-                LocationAccessPolicy.checkLocationPermission(mApp,
-                        new LocationAccessPolicy.LocationPermissionQuery.Builder()
-                                .setCallingPackage(callingPackage)
-                                .setCallingFeatureId(callingFeatureId)
-                                .setCallingPid(Binder.getCallingPid())
-                                .setCallingUid(Binder.getCallingUid())
-                                .setMethod("requestNetworkScan")
-                                .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
-                                .setMinSdkVersionForCoarse(Build.VERSION_CODES.Q)
-                                .setMinSdkVersionForEnforcement(Build.VERSION_CODES.Q)
-                                .build());
+                LocationAccessPolicy.LocationPermissionResult.DENIED_HARD;
+        if (!renounceFineLocationAccess) {
+            locationResult = LocationAccessPolicy.checkLocationPermission(mApp,
+                            new LocationAccessPolicy.LocationPermissionQuery.Builder()
+                                    .setCallingPackage(callingPackage)
+                                    .setCallingFeatureId(callingFeatureId)
+                                    .setCallingPid(Binder.getCallingPid())
+                                    .setCallingUid(Binder.getCallingUid())
+                                    .setMethod("requestNetworkScan")
+                                    .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
+                                    .setMinSdkVersionForCoarse(Build.VERSION_CODES.Q)
+                                    .setMinSdkVersionForEnforcement(Build.VERSION_CODES.Q)
+                                    .build());
+        }
         if (locationResult != LocationAccessPolicy.LocationPermissionResult.ALLOWED) {
             SecurityException e = checkNetworkRequestForSanitizedLocationAccess(
                     request, subId, callingPackage);
@@ -6340,7 +6383,7 @@
         final long identity = Binder.clearCallingIdentity();
         try {
             return mNetworkScanRequestTracker.startNetworkScan(
-                    request, messenger, binder, getPhone(subId),
+                    renounceFineLocationAccess, request, messenger, binder, getPhone(subId),
                     callingUid, callingPid, callingPackage);
         } finally {
             Binder.restoreCallingIdentity(identity);
@@ -7560,6 +7603,13 @@
      */
     @Override
     public String getDeviceIdWithFeature(String callingPackage, String callingFeatureId) {
+        try {
+            mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
+        } catch (SecurityException se) {
+            EventLog.writeEvent(0x534e4554, "186530889", Binder.getCallingUid());
+            throw new SecurityException("Package " + callingPackage + " does not belong to "
+                    + Binder.getCallingUid());
+        }
         final Phone phone = PhoneFactory.getPhone(0);
         if (phone == null) {
             return null;
@@ -7864,49 +7914,54 @@
     }
 
     /**
-     * {@hide}
      * Returns the service state information on specified subscription.
      */
     @Override
-    public ServiceState getServiceStateForSubscriber(int subId, String callingPackage,
-            String callingFeatureId) {
+    public ServiceState getServiceStateForSubscriber(int subId,
+            boolean renounceFineLocationAccess, boolean renounceCoarseLocationAccess,
+            String callingPackage, String callingFeatureId) {
         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
                 mApp, subId, callingPackage, callingFeatureId, "getServiceStateForSubscriber")) {
             return null;
         }
 
-        LocationAccessPolicy.LocationPermissionResult fineLocationResult =
-                LocationAccessPolicy.checkLocationPermission(mApp,
-                        new LocationAccessPolicy.LocationPermissionQuery.Builder()
-                                .setCallingPackage(callingPackage)
-                                .setCallingFeatureId(callingFeatureId)
-                                .setCallingPid(Binder.getCallingPid())
-                                .setCallingUid(Binder.getCallingUid())
-                                .setMethod("getServiceStateForSubscriber")
-                                .setLogAsInfo(true)
-                                .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
-                                .setMinSdkVersionForCoarse(Build.VERSION_CODES.Q)
-                                .setMinSdkVersionForEnforcement(Build.VERSION_CODES.Q)
-                                .build());
+        boolean hasFinePermission = false;
+        boolean hasCoarsePermission = false;
+        if (!renounceFineLocationAccess) {
+            LocationAccessPolicy.LocationPermissionResult fineLocationResult =
+                    LocationAccessPolicy.checkLocationPermission(mApp,
+                            new LocationAccessPolicy.LocationPermissionQuery.Builder()
+                                    .setCallingPackage(callingPackage)
+                                    .setCallingFeatureId(callingFeatureId)
+                                    .setCallingPid(Binder.getCallingPid())
+                                    .setCallingUid(Binder.getCallingUid())
+                                    .setMethod("getServiceStateForSubscriber")
+                                    .setLogAsInfo(true)
+                                    .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
+                                    .setMinSdkVersionForCoarse(Build.VERSION_CODES.Q)
+                                    .setMinSdkVersionForEnforcement(Build.VERSION_CODES.Q)
+                                    .build());
+            hasFinePermission =
+                    fineLocationResult == LocationAccessPolicy.LocationPermissionResult.ALLOWED;
+        }
 
-        LocationAccessPolicy.LocationPermissionResult coarseLocationResult =
-                LocationAccessPolicy.checkLocationPermission(mApp,
-                        new LocationAccessPolicy.LocationPermissionQuery.Builder()
-                                .setCallingPackage(callingPackage)
-                                .setCallingFeatureId(callingFeatureId)
-                                .setCallingPid(Binder.getCallingPid())
-                                .setCallingUid(Binder.getCallingUid())
-                                .setMethod("getServiceStateForSubscriber")
-                                .setLogAsInfo(true)
-                                .setMinSdkVersionForCoarse(Build.VERSION_CODES.Q)
-                                .setMinSdkVersionForFine(Integer.MAX_VALUE)
-                                .setMinSdkVersionForEnforcement(Build.VERSION_CODES.Q)
-                                .build());
-        // We don't care about hard or soft here -- all we need to know is how much info to scrub.
-        boolean hasFinePermission =
-                fineLocationResult == LocationAccessPolicy.LocationPermissionResult.ALLOWED;
-        boolean hasCoarsePermission =
-                coarseLocationResult == LocationAccessPolicy.LocationPermissionResult.ALLOWED;
+        if (!renounceCoarseLocationAccess) {
+            LocationAccessPolicy.LocationPermissionResult coarseLocationResult =
+                    LocationAccessPolicy.checkLocationPermission(mApp,
+                            new LocationAccessPolicy.LocationPermissionQuery.Builder()
+                                    .setCallingPackage(callingPackage)
+                                    .setCallingFeatureId(callingFeatureId)
+                                    .setCallingPid(Binder.getCallingPid())
+                                    .setCallingUid(Binder.getCallingUid())
+                                    .setMethod("getServiceStateForSubscriber")
+                                    .setLogAsInfo(true)
+                                    .setMinSdkVersionForCoarse(Build.VERSION_CODES.Q)
+                                    .setMinSdkVersionForFine(Integer.MAX_VALUE)
+                                    .setMinSdkVersionForEnforcement(Build.VERSION_CODES.Q)
+                                    .build());
+            hasCoarsePermission =
+                    coarseLocationResult == LocationAccessPolicy.LocationPermissionResult.ALLOWED;
+        }
 
         final Phone phone = getPhone(subId);
         if (phone == null) {
@@ -8723,6 +8778,7 @@
                 .checkPackage(Binder.getCallingUid(), callingPackage);
 
         boolean hasReadPermission = false;
+        boolean isIccIdAccessRestricted = false;
         try {
             enforceReadPrivilegedPermission("getUiccCardsInfo");
             hasReadPermission = true;
@@ -8734,7 +8790,11 @@
                 throw new SecurityException("Caller does not have permission.");
             }
         }
-
+        // checking compatibility, if calling app's target SDK is T and beyond.
+        if (CompatChanges.isChangeEnabled(GET_API_SIGNATURES_FROM_UICC_PORT_INFO,
+                Binder.getCallingUid())) {
+            isIccIdAccessRestricted = true;
+        }
         final long identity = Binder.clearCallingIdentity();
         try {
             UiccController uiccController = UiccController.getInstance();
@@ -8746,21 +8806,23 @@
             // Remove private info if the caller doesn't have access
             ArrayList<UiccCardInfo> filteredInfos = new ArrayList<>();
             for (UiccCardInfo cardInfo : cardInfos) {
+                //setting the value after compatibility check
+                cardInfo.setIccIdAccessRestricted(isIccIdAccessRestricted);
                 // For an inactive eUICC, the UiccCard will be null even though the UiccCardInfo
                 // is available
-                UiccCard card = uiccController.getUiccCardForSlot(cardInfo.getSlotIndex());
+                UiccCard card = uiccController.getUiccCardForSlot(cardInfo.getPhysicalSlotIndex());
                 // TODO remove card.getUiccPortList().length once MEP API refactoring CL is merged
                 //  Get UiccPortInfo from CardInfo and process further based on each UiccPort
                 if (card == null || card.getUiccPortList().length == 0) {
                     // assume no access if the card or ports are unavailable
-                    filteredInfos.add(cardInfo.getUnprivileged());
+                    filteredInfos.add(getUiccCardInfoUnPrivileged(cardInfo));
                     continue;
                 }
 
                 if (haveCarrierPrivilegeAccess(card, callingPackage)) {
                     filteredInfos.add(cardInfo);
                 } else {
-                    filteredInfos.add(cardInfo.getUnprivileged());
+                    filteredInfos.add(getUiccCardInfoUnPrivileged(cardInfo));
                 }
             }
             return filteredInfos;
@@ -8769,10 +8831,70 @@
         }
     }
 
-    @Override
-    public UiccSlotInfo[] getUiccSlotsInfo() {
-        enforceReadPrivilegedPermission("getUiccSlotsInfo");
+    /**
+     * Returns a copy of the UiccCardinfo with the EID and ICCID set to null. These values are
+     * generally private and require carrier privileges to view.
+     *
+     * @hide
+     */
+    @NonNull
+    public UiccCardInfo getUiccCardInfoUnPrivileged(UiccCardInfo cardInfo) {
+        List<UiccPortInfo> portinfo = new  ArrayList<>();
+        for (UiccPortInfo portinfos : cardInfo.getPorts()) {
+            portinfo.add(getUiccPortInfoUnPrivileged(portinfos));
+        }
+        return new UiccCardInfo(
+                cardInfo.isEuicc(),
+                cardInfo.getCardId(),
+                null,
+                cardInfo.getPhysicalSlotIndex(),
+                cardInfo.isRemovable(),
+                cardInfo.isMultipleEnabledProfilesSupported(),
+                portinfo
+        );
+    }
 
+    /**
+     * @hide
+     * @return a copy of the UiccPortInfo with ICCID set to {@link UiccPortInfo#ICCID_REDACTED}.
+     * These values are generally private and require carrier privileges to view.
+     */
+    @NonNull
+    public UiccPortInfo getUiccPortInfoUnPrivileged(UiccPortInfo portInfo) {
+        return new UiccPortInfo(
+                UiccPortInfo.ICCID_REDACTED,
+                portInfo.getPortIndex(),
+                portInfo.getLogicalSlotIndex(),
+                portInfo.isActive()
+        );
+    }
+    @Override
+    public UiccSlotInfo[] getUiccSlotsInfo(String callingPackage) {
+        // Verify that tha callingPackage belongs to the calling UID
+        mApp.getSystemService(AppOpsManager.class)
+                .checkPackage(Binder.getCallingUid(), callingPackage);
+
+        boolean hasReadPermission = false;
+        boolean isLogicalSlotAccessRestricted = false;
+        String iccId;
+
+        try {
+            enforceReadPrivilegedPermission("getUiccSlotsInfo");
+            hasReadPermission = true;
+        } catch (SecurityException e) {
+            // even without READ_PRIVILEGED_PHONE_STATE, we allow the call to continue if the caller
+            // has carrier privileges on an active UICC
+            if (checkCarrierPrivilegesForPackageAnyPhone(callingPackage)
+                    == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
+                hasReadPermission = true;
+            }
+        }
+
+        // checking compatibility, if calling app's target SDK is T and beyond.
+        if (CompatChanges.isChangeEnabled(GET_API_SIGNATURES_FROM_UICC_PORT_INFO,
+                Binder.getCallingUid())) {
+            isLogicalSlotAccessRestricted  = true;
+        }
         final long identity = Binder.clearCallingIdentity();
         try {
             UiccSlot[] slots = UiccController.getInstance().getUiccSlots();
@@ -8780,7 +8902,6 @@
                 Rlog.i(LOG_TAG, "slots is null.");
                 return null;
             }
-
             UiccSlotInfo[] infos = new UiccSlotInfo[slots.length];
             for (int i = 0; i < slots.length; i++) {
                 UiccSlot slot = slots[i];
@@ -8790,12 +8911,24 @@
 
                 String cardId;
                 UiccCard card = slot.getUiccCard();
+                //if has read permission
+                if (hasReadPermission) {
+                    iccId = slot.getIccId();
+                } else {
+                    // if no read permission checking carrier
+                    if (haveCarrierPrivilegeAccess(card, callingPackage)) {
+                        iccId = slot.getIccId();
+                    } else {
+                        //if no carrier permission redact ICCID
+                        iccId = IccUtils.TEST_ICCID;
+                    }
+                }
                 if (card != null) {
                     cardId = card.getCardId();
                 } else {
                     cardId = slot.getEid();
                     if (TextUtils.isEmpty(cardId)) {
-                        cardId = slot.getIccId();
+                        cardId = iccId;
                     }
                 }
 
@@ -8823,15 +8956,19 @@
                         break;
 
                 }
-
                 infos[i] = new UiccSlotInfo(
-                        slot.isActive(),
                         slot.isEuicc(),
                         cardId,
                         cardState,
-                        slot.getPhoneId(),
                         slot.isExtendedApduSupported(),
-                        slot.isRemovable());
+                        slot.isRemovable(), Collections.singletonList(
+                        new UiccPortInfo(
+                                iccId,
+                                0 /* TODO: to use portList from UiccSlots */,
+                                slot.getPhoneId(),
+                                slot.isActive())));
+                //setting the value after compatibility check
+                infos[i].setLogicalSlotAccessRestricted(isLogicalSlotAccessRestricted);
             }
             return infos;
         } finally {
@@ -8840,6 +8977,8 @@
     }
 
     @Override
+    @Deprecated
+    //TODO : once integrating with HAL Changes we can clean up this Internal API.
     public boolean switchSlots(int[] physicalSlots) {
         enforceModifyPermission();
 
@@ -8852,6 +8991,24 @@
     }
 
     @Override
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public boolean setSimSlotMapping(@NonNull List<UiccSlotMapping> slotMapping) {
+        enforceModifyPermission();
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            //TODO: once integrating the HAL changes we can proceed with to work on the parsing side
+            int[] physicalSlots = new int[slotMapping.size()];
+            for (int i = 0; i < physicalSlots.length; i++) {
+                physicalSlots[i] = slotMapping.get(i).getPhysicalSlotIndex();
+            }
+            return (Boolean) sendRequest(CMD_SWITCH_SLOTS, physicalSlots);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
     public int getCardIdForDefaultEuicc(int subId, String callingPackage) {
         final long identity = Binder.clearCallingIdentity();
         try {
@@ -9434,7 +9591,7 @@
     }
 
     @Override
-    public int[] getSlotsMapping() {
+    public int[] getSlotsMapping(@NonNull String callingPackage) {
         enforceReadPrivilegedPermission("getSlotsMapping");
 
         final long identity = Binder.clearCallingIdentity();
@@ -9442,7 +9599,7 @@
             int phoneCount = TelephonyManager.getDefault().getPhoneCount();
             // All logical slots should have a mapping to a physical slot.
             int[] logicalSlotsMapping = new int[phoneCount];
-            UiccSlotInfo[] slotInfos = getUiccSlotsInfo();
+            UiccSlotInfo[] slotInfos = getUiccSlotsInfo(callingPackage);
             for (int i = 0; i < slotInfos.length; i++) {
                 if (SubscriptionManager.isValidPhoneId(slotInfos[i].getLogicalSlotIdx())) {
                     logicalSlotsMapping[slotInfos[i].getLogicalSlotIdx()] = i;
@@ -10397,9 +10554,6 @@
             } else {
                 configBinder.setRcsClientConfiguration(rcc);
             }
-
-            RcsStats.getInstance().onRcsClientProvisioningStats(subId,
-                    RCS_CLIENT_PROVISIONING_STATS__EVENT__CLIENT_PARAMS_SENT);
         } catch (RemoteException e) {
             Rlog.e(LOG_TAG, "fail to setRcsClientConfiguration " + e.getMessage());
             throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE,
@@ -11052,4 +11206,37 @@
             Binder.restoreCallingIdentity(identity);
         }
     }
+
+    /**
+     * Sets the modem service class Name that Telephony will bind to.
+     *
+     * @param serviceName The class name of the modem service.
+     * @return true if the operation is succeed, otherwise false.
+     */
+    public boolean setModemService(String serviceName) {
+        Log.d(LOG_TAG, "setModemService - " + serviceName);
+        TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "setModemService");
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp,
+                        SubscriptionManager.INVALID_SUBSCRIPTION_ID,
+                        "setModemService");
+        return mPhoneConfigurationManager.setModemService(serviceName);
+    }
+
+    /**
+     * Return the class name of the currently bounded modem service.
+     *
+     * @return the class name of the modem service.
+     */
+    public String getModemService() {
+        String result;
+        Log.d(LOG_TAG, "getModemService");
+        TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "getModemService");
+        TelephonyPermissions
+                        .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
+                        mApp, SubscriptionManager.INVALID_SUBSCRIPTION_ID,
+                        "getModemService");
+        result = mPhoneConfigurationManager.getModemService();
+        Log.d(LOG_TAG, "result = " + result);
+        return result;
+    }
 }
diff --git a/src/com/android/phone/RcsProvisioningMonitor.java b/src/com/android/phone/RcsProvisioningMonitor.java
index 9c1c3b5..6d2bd6f 100644
--- a/src/com/android/phone/RcsProvisioningMonitor.java
+++ b/src/com/android/phone/RcsProvisioningMonitor.java
@@ -16,10 +16,6 @@
 
 package com.android.phone;
 
-import static com.android.internal.telephony.TelephonyStatsLog.RCS_ACS_PROVISIONING_STATS__RESPONSE_TYPE__PROVISIONING_XML;
-import static com.android.internal.telephony.TelephonyStatsLog.RCS_CLIENT_PROVISIONING_STATS__EVENT__DMA_CHANGED;
-import static com.android.internal.telephony.TelephonyStatsLog.RCS_CLIENT_PROVISIONING_STATS__EVENT__TRIGGER_RCS_RECONFIGURATION;
-
 import android.Manifest;
 import android.app.role.OnRoleHoldersChangedListener;
 import android.app.role.RoleManager;
@@ -51,8 +47,6 @@
 import com.android.ims.FeatureUpdates;
 import com.android.ims.RcsFeatureManager;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.telephony.metrics.RcsStats;
-import com.android.internal.telephony.metrics.RcsStats.RcsProvisioningCallback;
 import com.android.internal.telephony.util.HandlerExecutor;
 import com.android.internal.util.CollectionUtils;
 import com.android.telephony.Rlog;
@@ -81,6 +75,10 @@
     private static final int EVENT_RESET = 8;
     private static final int EVENT_FEATURE_ENABLED_OVERRIDE = 9;
 
+    // indicate that the carrier single registration capable is initial value as
+    // carrier config is not ready yet.
+    private static final int MASK_CAP_CARRIER_INIT = 0xF000;
+
     private final PhoneGlobals mPhone;
     private final Handler mHandler;
     // Cache the RCS provsioning info and related sub id
@@ -102,8 +100,6 @@
     private final RoleManagerAdapter mRoleManager;
     private FeatureConnectorFactory<RcsFeatureManager> mFeatureFactory;
 
-    private RcsStats mRcsStats;
-
     private static RcsProvisioningMonitor sInstance;
 
     private final SubscriptionManager.OnSubscriptionsChangedListener mSubChangedListener =
@@ -228,10 +224,19 @@
         }
 
         void setSingleRegistrationCapability(int singleRegistrationCapability) {
-            mSingleRegistrationCapability = singleRegistrationCapability;
-            // update whether single registration supported.
-            mRcsStats.setEnableSingleRegistration(mSubId,
-                    mSingleRegistrationCapability == ProvisioningManager.STATUS_CAPABLE);
+            if (mSingleRegistrationCapability != singleRegistrationCapability) {
+                mSingleRegistrationCapability = singleRegistrationCapability;
+                notifyDma();
+            }
+        }
+
+        void notifyDma() {
+            // notify only if capable value has been updated when carrier config ready.
+            if ((mSingleRegistrationCapability & MASK_CAP_CARRIER_INIT) != MASK_CAP_CARRIER_INIT) {
+                logi("notify default messaging app for sub:" + mSubId + " with capability:"
+                        + mSingleRegistrationCapability);
+                notifyDmaForSub(mSubId, mSingleRegistrationCapability);
+            }
         }
 
         int getSingleRegistrationCapability() {
@@ -333,9 +338,6 @@
                     } else {
                         notifyRcsAutoConfigurationReceived();
                     }
-
-                    // check callback for metrics if not registered, register callback
-                    registerMetricsCallback();
                 } else {
                     // clear callbacks if rcs disconnected
                     clearCallbacks();
@@ -395,18 +397,6 @@
                 }
             }
         }
-
-        private void registerMetricsCallback() {
-            RcsProvisioningCallback rcsProvisioningCallback = mRcsStats.getRcsProvisioningCallback(
-                    mSubId, mSingleRegistrationCapability == ProvisioningManager.STATUS_CAPABLE);
-
-            // if not yet registered, register callback and set registered value
-            if (rcsProvisioningCallback != null && !rcsProvisioningCallback.getRegistered()) {
-                if (addRcsConfigCallback(rcsProvisioningCallback)) {
-                    rcsProvisioningCallback.setRegistered(true);
-                }
-            }
-        }
     }
 
     @VisibleForTesting
@@ -464,7 +454,7 @@
 
     @VisibleForTesting
     public RcsProvisioningMonitor(PhoneGlobals app, Looper looper, RoleManagerAdapter roleManager,
-            FeatureConnectorFactory<RcsFeatureManager> factory, RcsStats rcsStats) {
+            FeatureConnectorFactory<RcsFeatureManager> factory) {
         mPhone = app;
         mHandler = new MyHandler(looper);
         mCarrierConfigManager = mPhone.getSystemService(CarrierConfigManager.class);
@@ -475,7 +465,6 @@
         logv("DMA is " + mDmaPackageName);
         mDmaChangedListener = new DmaChangedListener();
         mFeatureFactory = factory;
-        mRcsStats = rcsStats;
         init();
     }
 
@@ -488,8 +477,7 @@
             HandlerThread handlerThread = new HandlerThread(TAG);
             handlerThread.start();
             sInstance = new RcsProvisioningMonitor(app, handlerThread.getLooper(),
-                    new RoleManagerAdapterImpl(app), RcsFeatureManager::getConnector,
-                    RcsStats.getInstance());
+                    new RoleManagerAdapterImpl(app), RcsFeatureManager::getConnector);
         }
         return sInstance;
     }
@@ -703,7 +691,7 @@
             logv("new default messaging application " + mDmaPackageName);
 
             mRcsProvisioningInfos.forEach((k, v) -> {
-                notifyDmaForSub(k, v.getSingleRegistrationCapability());
+                v.notifyDma();
 
                 byte[] cachedConfig = v.getConfig();
                 //clear old callbacks
@@ -716,10 +704,6 @@
                     logv("acs not used, set cached config and notify.");
                     v.setConfig(cachedConfig);
                 }
-
-                // store RCS metrics - DMA changed event
-                mRcsStats.onRcsClientProvisioningStats(k,
-                        RCS_CLIENT_PROVISIONING_STATS__EVENT__DMA_CHANGED);
             });
         }
     }
@@ -747,17 +731,20 @@
         return b.getBoolean(CarrierConfigManager.KEY_USE_ACS_FOR_RCS_BOOL);
     }
 
-    private boolean isSingleRegistrationRequiredByCarrier(int subId) {
+    private int getSingleRegistrationRequiredByCarrier(int subId) {
         Boolean enabledByOverride = mCarrierSingleRegistrationEnabledOverride.get(subId);
         if (enabledByOverride != null) {
-            return enabledByOverride;
+            return enabledByOverride ? ProvisioningManager.STATUS_CAPABLE
+                    : ProvisioningManager.STATUS_CARRIER_NOT_CAPABLE;
         }
 
         PersistableBundle b = mCarrierConfigManager.getConfigForSubId(subId);
-        if (b == null) {
-            return false;
+        if (!CarrierConfigManager.isConfigForIdentifiedCarrier(b)) {
+            return MASK_CAP_CARRIER_INIT;
         }
-        return b.getBoolean(CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL);
+        return b.getBoolean(CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL)
+                ? ProvisioningManager.STATUS_CAPABLE
+                : ProvisioningManager.STATUS_CARRIER_NOT_CAPABLE;
     }
 
     private int getSingleRegistrationCapableValue(int subId) {
@@ -767,10 +754,9 @@
                 : mPhone.getPackageManager().hasSystemFeature(
                         PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION);
 
-        int value = (isSingleRegistrationEnabledOnDevice ? 0
-                : ProvisioningManager.STATUS_DEVICE_NOT_CAPABLE) | (
-                isSingleRegistrationRequiredByCarrier(subId) ? 0
-                : ProvisioningManager.STATUS_CARRIER_NOT_CAPABLE);
+        int value = (isSingleRegistrationEnabledOnDevice ? ProvisioningManager.STATUS_CAPABLE
+                : ProvisioningManager.STATUS_DEVICE_NOT_CAPABLE)
+                | getSingleRegistrationRequiredByCarrier(subId);
         logv("SingleRegistrationCapableValue : " + value);
         return value;
     }
@@ -778,11 +764,8 @@
     private void onCarrierConfigChange() {
         logv("onCarrierConfigChange");
         mRcsProvisioningInfos.forEach((subId, info) -> {
-            int value = getSingleRegistrationCapableValue(subId);
-            if (value != info.getSingleRegistrationCapability()) {
-                info.setSingleRegistrationCapability(value);
-                notifyDmaForSub(subId, value);
-            }
+            info.setSingleRegistrationCapability(
+                    getSingleRegistrationCapableValue(subId));
         });
     }
 
@@ -797,9 +780,8 @@
                 byte[] data = loadConfigForSub(i);
                 int capability = getSingleRegistrationCapableValue(i);
                 logv("new info is created for sub : " + i + ", single registration capability :"
-                        + capability + ", rcs config : " + data);
+                        + capability + ", rcs config : " + Arrays.toString(data));
                 mRcsProvisioningInfos.put(i, new RcsProvisioningInfo(i, capability, data));
-                notifyDmaForSub(i, capability);
             }
         }
 
@@ -815,16 +797,12 @@
         logv("onConfigReceived, subId:" + subId + ", config:"
                 + config + ", isCompressed:" + isCompressed);
         RcsProvisioningInfo info = mRcsProvisioningInfos.get(subId);
+        if (info == null) {
+            logd("sub[" + subId + "] has been removed");
+            return;
+        }
         info.setConfig(isCompressed ? RcsConfig.decompressGzip(config) : config);
         updateConfigForSub(subId, config, isCompressed);
-
-        // Supporting ACS means config data comes from ACS
-        // store RCS metrics - received provisioning event
-        if (isAcsUsed(subId)) {
-            mRcsStats.onRcsAcsProvisioningStats(subId, 200,
-                    RCS_ACS_PROVISIONING_STATS__RESPONSE_TYPE__PROVISIONING_XML,
-                    isRcsVolteSingleRegistrationEnabled(subId));
-        }
     }
 
     private void onReconfigRequest(int subId) {
@@ -836,10 +814,6 @@
             updateConfigForSub(subId, null, true);
             info.triggerRcsReconfiguration();
         }
-
-        // store RCS metrics - reconfig event
-        mRcsStats.onRcsClientProvisioningStats(subId,
-                RCS_CLIENT_PROVISIONING_STATS__EVENT__TRIGGER_RCS_RECONFIGURATION);
     }
 
     private void notifyDmaForSub(int subId, int capability) {
@@ -896,6 +870,10 @@
         }
     }
 
+    private static void logi(String msg) {
+        Rlog.i(TAG, msg);
+    }
+
     private static void logd(String msg) {
         Rlog.d(TAG, msg);
     }
diff --git a/src/com/android/phone/TelephonyShellCommand.java b/src/com/android/phone/TelephonyShellCommand.java
index dbeb7ce..c6ee74e 100644
--- a/src/com/android/phone/TelephonyShellCommand.java
+++ b/src/com/android/phone/TelephonyShellCommand.java
@@ -151,6 +151,10 @@
     private static final String UCE_SET_CAPABILITY_REQUEST_TIMEOUT =
             "set-capabilities-request-timeout";
 
+    private static final String RADIO_SUBCOMMAND = "radio";
+    private static final String RADIO_SET_MODEM_SERVICE = "set-modem-service";
+    private static final String RADIO_GET_MODEM_SERVICE = "get-modem-service";
+
     // Check if a package has carrier privileges on any SIM, regardless of subId/phoneId.
     private static final String HAS_CARRIER_PRIVILEGES_COMMAND = "has-carrier-privileges";
 
@@ -319,6 +323,8 @@
             case GET_ALLOWED_NETWORK_TYPES_FOR_USER:
             case SET_ALLOWED_NETWORK_TYPES_FOR_USER:
                 return handleAllowedNetworkTypesCommand(cmd);
+            case RADIO_SUBCOMMAND:
+                return handleRadioCommand();
             default: {
                 return handleDefaultCommands(cmd);
             }
@@ -357,6 +363,8 @@
         pw.println("    Get the Allowed Network Types.");
         pw.println("  set-allowed-network-types-for-users");
         pw.println("    Set the Allowed Network Types.");
+        pw.println("  radio");
+        pw.println("    Radio Commands.");
         onHelpIms();
         onHelpUce();
         onHelpEmergencyNumber();
@@ -368,6 +376,7 @@
         onHelpD2D();
         onHelpDisableOrEnablePhysicalSubscription();
         onHelpAllowedNetworkTypes();
+        onHelpRadio();
     }
 
     private void onHelpD2D() {
@@ -656,6 +665,21 @@
         pw.println("        LTE only                   : 01000001000000000000");
     }
 
+    private void onHelpRadio() {
+        PrintWriter pw = getOutPrintWriter();
+        pw.println("Radio Commands:");
+        pw.println("  radio set-modem-service [-s SERVICE_NAME]");
+        pw.println("    Sets the class name of modem service defined in SERVICE_NAME");
+        pw.println("    to be the bound. Options are:");
+        pw.println("      -s: the service name that the modem service should be bound for.");
+        pw.println("          If no option is specified, it will bind to the default.");
+        pw.println("  radio get-modem-service");
+        pw.println("    Gets the service name of the currently defined modem service.");
+        pw.println("    If it is binding to default, 'default' returns.");
+        pw.println("    If it doesn't bind to any modem service for some reasons,");
+        pw.println("    the result would be 'unknown'.");
+    }
+
     private int handleImsCommand() {
         String arg = getNextArg();
         if (arg == null) {
@@ -2725,4 +2749,69 @@
             return -1;
         }
     }
+
+    private int handleRadioSetModemServiceCommand() {
+        PrintWriter errPw = getErrPrintWriter();
+        String serviceName = null;
+
+        String opt;
+        while ((opt = getNextOption()) != null) {
+            switch (opt) {
+                case "-s": {
+                    serviceName = getNextArgRequired();
+                    break;
+                }
+            }
+        }
+
+        try {
+            boolean result = mInterface.setModemService(serviceName);
+            if (VDBG) {
+                Log.v(LOG_TAG,
+                        "RadioSetModemService " + serviceName + ", result = " + result);
+            }
+            getOutPrintWriter().println(result);
+        } catch (RemoteException e) {
+            Log.w(LOG_TAG,
+                    "RadioSetModemService: " + serviceName + ", error = " + e.getMessage());
+            errPw.println("Exception: " + e.getMessage());
+            return -1;
+        }
+        return 0;
+    }
+
+    private int handleRadioGetModemServiceCommand() {
+        PrintWriter errPw = getErrPrintWriter();
+        String result;
+
+        try {
+            result = mInterface.getModemService();
+            getOutPrintWriter().println(result);
+        } catch (RemoteException e) {
+            errPw.println("Exception: " + e.getMessage());
+            return -1;
+        }
+        if (VDBG) {
+            Log.v(LOG_TAG, "RadioGetModemService, result = " + result);
+        }
+        return 0;
+    }
+
+    private int handleRadioCommand() {
+        String arg = getNextArg();
+        if (arg == null) {
+            onHelpRadio();
+            return 0;
+        }
+
+        switch (arg) {
+            case RADIO_SET_MODEM_SERVICE:
+                return handleRadioSetModemServiceCommand();
+
+            case RADIO_GET_MODEM_SERVICE:
+                return handleRadioGetModemServiceCommand();
+        }
+
+        return -1;
+    }
 }
diff --git a/src/com/android/phone/settings/RadioInfo.java b/src/com/android/phone/settings/RadioInfo.java
index 0487833..6728138 100644
--- a/src/com/android/phone/settings/RadioInfo.java
+++ b/src/com/android/phone/settings/RadioInfo.java
@@ -674,6 +674,12 @@
         mPreferredNetworkType.setSelection(mPreferredNetworkTypeResult, true);
         mPreferredNetworkType.setOnItemSelectedListener(mPreferredNetworkHandler);
 
+        new Thread(() -> {
+            int networkType = (int) mTelephonyManager.getPreferredNetworkTypeBitmask();
+            updatePreferredNetworkType(
+                    RadioAccessFamily.getNetworkTypeFromRaf(networkType));
+        }).start();
+
         // set phone index
         mSelectPhoneIndex.setSelection(mSelectedPhoneIndex, true);
         mSelectPhoneIndex.setOnItemSelectedListener(mSelectPhoneIndexHandler);
@@ -1119,24 +1125,28 @@
                 & TelephonyManager.NETWORK_TYPE_BITMASK_NR) == 0) {
             return;
         }
-
         ServiceState ss = serviceState;
         if (ss == null && mPhone != null) {
             ss = mPhone.getServiceState();
         }
         if (ss != null) {
+            boolean isNrSa = ss.getDataNetworkType() == TelephonyManager.NETWORK_TYPE_NR;
             NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo(
                     NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
             if (nri != null) {
                 DataSpecificRegistrationInfo dsri = nri.getDataSpecificInfo();
                 if (dsri != null) {
-                    mEndcAvailable.setText(dsri.isEnDcAvailable ? "True" : "False");
-                    mDcnrRestricted.setText(dsri.isDcNrRestricted ? "True" : "False");
-                    mNrAvailable.setText(dsri.isNrAvailable ? "True" : "False");
+                    mEndcAvailable.setText(isNrSa ? "N/A"
+                            : dsri.isEnDcAvailable ? "True" : "False");
+                    mDcnrRestricted.setText(isNrSa ? "N/A"
+                            : dsri.isDcNrRestricted ? "True" : "False");
+                    mNrAvailable.setText(isNrSa ? "N/A" : dsri.isNrAvailable ? "True" : "False");
                 }
             }
-            mNrState.setText(NetworkRegistrationInfo.nrStateToString(ss.getNrState()));
-            mNrFrequency.setText(ServiceState.frequencyRangeToString(ss.getNrFrequencyRange()));
+            mNrState.setText(isNrSa ? "N/A"
+                    : NetworkRegistrationInfo.nrStateToString(ss.getNrState()));
+            mNrFrequency.setText(isNrSa ? "N/A"
+                    : ServiceState.frequencyRangeToString(ss.getNrFrequencyRange()));
         }
 
         Executor simpleExecutor = (r) -> r.run();
diff --git a/src/com/android/services/telephony/DisconnectCauseUtil.java b/src/com/android/services/telephony/DisconnectCauseUtil.java
index 9c89e9e..9321e1e 100644
--- a/src/com/android/services/telephony/DisconnectCauseUtil.java
+++ b/src/com/android/services/telephony/DisconnectCauseUtil.java
@@ -787,12 +787,12 @@
             default:
                 break;
         }
-        return resourceId == null ? "" : context.getResources().getText(resourceId);
+        return resourceId == null ? "" : context.getResources().getString(resourceId);
     }
 
     private static boolean isRadioOffForThermalMitigation(int phoneId) {
         Phone phone = PhoneFactory.getPhone(phoneId);
-        return phone.isRadioOffForThermalMitigation();
+        return phone == null ? false : phone.isRadioOffForThermalMitigation();
     }
 
     /**
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 0d2b71b..e637791 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -1200,9 +1200,9 @@
             return connection;
         }
 
-        com.android.internal.telephony.Connection originalConnection =
-                call.getState() == Call.State.WAITING ?
-                    call.getLatestConnection() : call.getEarliestConnection();
+        // If there are multiple Connections tracked in a call, grab the latest, since it is most
+        // likely to be the incoming call.
+        com.android.internal.telephony.Connection originalConnection = call.getLatestConnection();
         if (isOriginalConnectionKnown(originalConnection)) {
             Log.i(this, "onCreateIncomingConnection, original connection already registered");
             return Connection.createCanceledConnection();
diff --git a/src/com/android/services/telephony/rcs/TelephonyRcsService.java b/src/com/android/services/telephony/rcs/TelephonyRcsService.java
index dfcea74..e72b0ab 100644
--- a/src/com/android/services/telephony/rcs/TelephonyRcsService.java
+++ b/src/com/android/services/telephony/rcs/TelephonyRcsService.java
@@ -32,7 +32,6 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.PhoneConfigurationManager;
-import com.android.internal.telephony.metrics.RcsStats;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.phone.ImsStateCallbackController;
 import com.android.phone.R;
@@ -165,7 +164,6 @@
         mFeatureControllers = new SparseArray<>(numSlots);
         mSlotToAssociatedSubIds = new SparseArray<>(numSlots);
         mRcsUceEnabled = sResourceProxy.getDeviceUceEnabled(mContext);
-        RcsStats.getInstance().registerUceCallback();
     }
 
     @VisibleForTesting
@@ -176,7 +174,6 @@
         mSlotToAssociatedSubIds = new SparseArray<>(numSlots);
         sResourceProxy = resourceProxy;
         mRcsUceEnabled = sResourceProxy.getDeviceUceEnabled(mContext);
-        RcsStats.getInstance().registerUceCallback();
     }
 
     /**
diff --git a/src/com/android/services/telephony/rcs/UceControllerManager.java b/src/com/android/services/telephony/rcs/UceControllerManager.java
index 995d685..02ae048 100644
--- a/src/com/android/services/telephony/rcs/UceControllerManager.java
+++ b/src/com/android/services/telephony/rcs/UceControllerManager.java
@@ -206,10 +206,11 @@
      *
      * @throws ImsException if the ImsService connected to this controller is currently down.
      */
-    public @PublishState int getUcePublishState() throws ImsException {
+    public @PublishState int getUcePublishState(boolean isSupportPublishingState)
+            throws ImsException {
         Future<Integer> future = mExecutorService.submit(() -> {
             checkUceControllerState();
-            return mUceController.getUcePublishState();
+            return mUceController.getUcePublishState(isSupportPublishingState);
         });
 
         try {
@@ -390,10 +391,11 @@
      *
      * @throws ImsException if the ImsService connected to this controller is currently down.
      */
-    public void registerPublishStateCallback(IRcsUcePublishStateCallback c) throws ImsException {
+    public void registerPublishStateCallback(IRcsUcePublishStateCallback c,
+            boolean supportPublishingState) throws ImsException {
         Future future = mExecutorService.submit(() -> {
             checkUceControllerState();
-            mUceController.registerPublishStateCallback(c);
+            mUceController.registerPublishStateCallback(c, supportPublishingState);
             return true;
         });
 
diff --git a/tests/src/com/android/phone/RcsProvisioningMonitorTest.java b/tests/src/com/android/phone/RcsProvisioningMonitorTest.java
index cf76ef0..8e5e073 100644
--- a/tests/src/com/android/phone/RcsProvisioningMonitorTest.java
+++ b/tests/src/com/android/phone/RcsProvisioningMonitorTest.java
@@ -16,10 +16,6 @@
 
 package com.android.phone;
 
-import static com.android.internal.telephony.TelephonyStatsLog.RCS_ACS_PROVISIONING_STATS__RESPONSE_TYPE__PROVISIONING_XML;
-import static com.android.internal.telephony.TelephonyStatsLog.RCS_CLIENT_PROVISIONING_STATS__EVENT__DMA_CHANGED;
-import static com.android.internal.telephony.TelephonyStatsLog.RCS_CLIENT_PROVISIONING_STATS__EVENT__TRIGGER_RCS_RECONFIGURATION;
-
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertNull;
@@ -68,7 +64,6 @@
 import com.android.ims.FeatureConnector;
 import com.android.ims.RcsFeatureManager;
 import com.android.internal.telephony.ITelephony;
-import com.android.internal.telephony.metrics.RcsStats;
 
 import org.junit.After;
 import org.junit.Before;
@@ -184,10 +179,6 @@
     private IRcsConfigCallback mCallback;
     @Mock
     private PackageManager mPackageManager;
-    @Mock
-    private RcsStats mRcsStats;
-    @Mock
-    private RcsStats.RcsProvisioningCallback mRcsProvisioningCallback;
 
     private Executor mExecutor = new Executor() {
         @Override
@@ -314,7 +305,6 @@
     @Test
     @SmallTest
     public void testInitWithSavedConfig() throws Exception {
-        ArgumentCaptor<Intent> captorIntent = ArgumentCaptor.forClass(Intent.class);
         createMonitor(3);
 
         for (int i = 0; i < 3; i++) {
@@ -322,10 +312,6 @@
                     mRcsProvisioningMonitor.getConfig(FAKE_SUB_ID_BASE + i)));
         }
 
-        verify(mPhone, times(3)).sendBroadcast(captorIntent.capture(), any());
-        Intent capturedIntent = captorIntent.getAllValues().get(1);
-        assertEquals(ProvisioningManager.ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE,
-                capturedIntent.getAction());
         verify(mIImsConfig, times(3)).notifyRcsAutoConfigurationReceived(any(), anyBoolean());
     }
 
@@ -333,14 +319,8 @@
     @SmallTest
     public void testInitWithoutSavedConfig() throws Exception {
         when(mCursor.getBlob(anyInt())).thenReturn(null);
-        ArgumentCaptor<Intent> captorIntent = ArgumentCaptor.forClass(Intent.class);
         createMonitor(3);
 
-        verify(mPhone, times(3)).sendBroadcast(captorIntent.capture(), any());
-        Intent capturedIntent = captorIntent.getAllValues().get(1);
-
-        assertEquals(ProvisioningManager.ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE,
-                capturedIntent.getAction());
         //Should not notify null config
         verify(mIImsConfig, never()).notifyRcsAutoConfigurationReceived(any(), anyBoolean());
     }
@@ -349,16 +329,12 @@
     @SmallTest
     public void testSubInfoChanged() throws Exception {
         createMonitor(3);
-        ArgumentCaptor<Intent> captorIntent = ArgumentCaptor.forClass(Intent.class);
 
         for (int i = 0; i < 3; i++) {
             assertTrue(Arrays.equals(CONFIG_DEFAULT.getBytes(),
                     mRcsProvisioningMonitor.getConfig(FAKE_SUB_ID_BASE + i)));
         }
-        verify(mPhone, times(3)).sendBroadcast(captorIntent.capture(), any());
-        Intent capturedIntent = captorIntent.getAllValues().get(1);
-        assertEquals(ProvisioningManager.ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE,
-                capturedIntent.getAction());
+
         verify(mIImsConfig, times(3)).notifyRcsAutoConfigurationReceived(any(), anyBoolean());
 
         makeFakeActiveSubIds(1);
@@ -410,14 +386,20 @@
     @SmallTest
     public void testCarrierConfigChanged() throws Exception {
         createMonitor(1);
+        // should not broadcast message if carrier config is not ready
+        verify(mPhone, never()).sendBroadcast(any(), any());
+
         when(mPackageManager.hasSystemFeature(
                 eq(PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION))).thenReturn(true);
         ArgumentCaptor<Intent> captorIntent = ArgumentCaptor.forClass(Intent.class);
+        mBundle.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
         mBundle.putBoolean(
                 CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, true);
+
         broadcastCarrierConfigChange(FAKE_SUB_ID_BASE);
         processAllMessages();
-        verify(mPhone, atLeastOnce()).sendBroadcast(captorIntent.capture(), any());
+
+        verify(mPhone, times(1)).sendBroadcast(captorIntent.capture(), any());
         Intent capturedIntent = captorIntent.getValue();
         assertEquals(capturedIntent.getAction(),
                 ProvisioningManager.ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE);
@@ -430,7 +412,8 @@
                 CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, false);
         broadcastCarrierConfigChange(FAKE_SUB_ID_BASE);
         processAllMessages();
-        verify(mPhone, atLeastOnce()).sendBroadcast(captorIntent.capture(), any());
+
+        verify(mPhone, times(2)).sendBroadcast(captorIntent.capture(), any());
         capturedIntent = captorIntent.getValue();
         assertEquals(capturedIntent.getAction(),
                 ProvisioningManager.ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE);
@@ -444,7 +427,8 @@
                 eq(PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION))).thenReturn(false);
         broadcastCarrierConfigChange(FAKE_SUB_ID_BASE);
         processAllMessages();
-        verify(mPhone, atLeastOnce()).sendBroadcast(captorIntent.capture(), any());
+
+        verify(mPhone, times(3)).sendBroadcast(captorIntent.capture(), any());
         capturedIntent = captorIntent.getValue();
         assertEquals(capturedIntent.getAction(),
                 ProvisioningManager.ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE);
@@ -488,6 +472,7 @@
 
         when(mPackageManager.hasSystemFeature(
                 eq(PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION))).thenReturn(false);
+        mBundle.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
         mBundle.putBoolean(
                 CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, false);
         broadcastCarrierConfigChange(FAKE_SUB_ID_BASE);
@@ -589,13 +574,39 @@
     @Test
     @SmallTest
     public void testSendBroadcastWhenDmaChanged() throws Exception {
-        createMonitor(3);
-        verify(mPhone, times(3)).sendBroadcast(any(), any());
-
+        when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(null);
+        mBundle.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
+        createMonitor(1);
         updateDefaultMessageApplication(DEFAULT_MESSAGING_APP2);
         processAllMessages();
 
-        verify(mPhone, times(6)).sendBroadcast(any(), any());
+        // should not broadcast message as no carrier config change happens
+        verify(mPhone, never()).sendBroadcast(any(), any());
+
+        when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(mBundle);
+        when(mPackageManager.hasSystemFeature(
+                eq(PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION))).thenReturn(true);
+        ArgumentCaptor<Intent> captorIntent = ArgumentCaptor.forClass(Intent.class);
+        mBundle.putBoolean(
+                CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, true);
+
+        broadcastCarrierConfigChange(FAKE_SUB_ID_BASE);
+        processAllMessages();
+
+        verify(mPhone, times(1)).sendBroadcast(captorIntent.capture(), any());
+        Intent capturedIntent = captorIntent.getValue();
+        assertEquals(capturedIntent.getAction(),
+                ProvisioningManager.ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE);
+
+        updateDefaultMessageApplication(DEFAULT_MESSAGING_APP1);
+        processAllMessages();
+
+        // should broadcast message when default messaging application changed if carrier config
+        // has been loaded
+        verify(mPhone, times(2)).sendBroadcast(captorIntent.capture(), any());
+        capturedIntent = captorIntent.getValue();
+        assertEquals(capturedIntent.getAction(),
+                ProvisioningManager.ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE);
     }
 
     @Test
@@ -620,6 +631,7 @@
 
         when(mPackageManager.hasSystemFeature(
                 eq(PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION))).thenReturn(true);
+        mBundle.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
         mBundle.putBoolean(
                 CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, true);
         broadcastCarrierConfigChange(FAKE_SUB_ID_BASE);
@@ -703,6 +715,7 @@
 
         when(mPackageManager.hasSystemFeature(
                 eq(PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION))).thenReturn(true);
+        mBundle.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
         mBundle.putBoolean(
                 CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, true);
         broadcastCarrierConfigChange(FAKE_SUB_ID_BASE);
@@ -755,66 +768,6 @@
         assertNull(mRcsProvisioningMonitor.getImsFeatureValidationOverride(FAKE_SUB_ID_BASE));
     }
 
-    @Test
-    @SmallTest
-    public void testMetricsAcsNotUsed() throws Exception {
-        createMonitor(1);
-
-        // Not used ACS
-        mBundle.putBoolean(CarrierConfigManager.KEY_USE_ACS_FOR_RCS_BOOL, false);
-        broadcastCarrierConfigChange(FAKE_SUB_ID_BASE);
-        processAllMessages();
-        mRcsProvisioningMonitor.updateConfig(FAKE_SUB_ID_BASE, CONFIG_DEFAULT.getBytes(), false);
-        processAllMessages();
-        verify(mRcsStats, never()).onRcsAcsProvisioningStats(anyInt(), anyInt(),
-                anyInt(), anyBoolean());
-    }
-
-    @Test
-    @SmallTest
-    public void testMetricsAcsUsed() throws Exception {
-        when(mRcsStats.getRcsProvisioningCallback(anyInt(), anyBoolean()))
-                .thenReturn(mRcsProvisioningCallback);
-        createMonitor(1);
-
-        verify(mIImsConfig, times(1))
-                .notifyRcsAutoConfigurationReceived(any(), anyBoolean());
-        // verify RcsStats.getRcsProvisioningCallback() is called
-        verify(mRcsStats, times(1)).getRcsProvisioningCallback(
-                eq(FAKE_SUB_ID_BASE), anyBoolean());
-        // verify registered callback obj which comes from RcsStats.getRcsProvisioningCallback()
-        verify(mIImsConfig, times(1))
-                .addRcsConfigCallback(eq(mRcsProvisioningCallback));
-
-        // Config data received and ACS used
-        int errorCode = 200;
-        mBundle.putBoolean(CarrierConfigManager.KEY_USE_ACS_FOR_RCS_BOOL, true);
-        broadcastCarrierConfigChange(FAKE_SUB_ID_BASE);
-        processAllMessages();
-        mRcsProvisioningMonitor.updateConfig(FAKE_SUB_ID_BASE, CONFIG_DEFAULT.getBytes(), false);
-        processAllMessages();
-        verify(mRcsStats, times(1)).onRcsAcsProvisioningStats(eq(FAKE_SUB_ID_BASE), eq(errorCode),
-                eq(RCS_ACS_PROVISIONING_STATS__RESPONSE_TYPE__PROVISIONING_XML), anyBoolean());
-    }
-
-    @Test
-    @SmallTest
-    public void testMetricsClientProvisioningStats() throws Exception {
-        createMonitor(1);
-
-        // reconfig trigger
-        mRcsProvisioningMonitor.requestReconfig(FAKE_SUB_ID_BASE);
-        processAllMessages();
-        verify(mRcsStats, times(1)).onRcsClientProvisioningStats(eq(FAKE_SUB_ID_BASE),
-                eq(RCS_CLIENT_PROVISIONING_STATS__EVENT__TRIGGER_RCS_RECONFIGURATION));
-
-        // DMA changed
-        updateDefaultMessageApplication(DEFAULT_MESSAGING_APP2);
-        processAllMessages();
-        verify(mRcsStats, times(1)).onRcsClientProvisioningStats(eq(FAKE_SUB_ID_BASE),
-                eq(RCS_CLIENT_PROVISIONING_STATS__EVENT__DMA_CHANGED));
-    }
-
     private void createMonitor(int subCount) throws Exception {
         if (Looper.myLooper() == null) {
             Looper.prepare();
@@ -824,7 +777,7 @@
                 .thenReturn(mFeatureConnector);
         when(mFeatureManager.getConfig()).thenReturn(mIImsConfig);
         mRcsProvisioningMonitor = new RcsProvisioningMonitor(mPhone, mHandlerThread.getLooper(),
-                mRoleManager, mFeatureFactory, mRcsStats);
+                mRoleManager, mFeatureFactory);
         mHandler = mRcsProvisioningMonitor.getHandler();
         try {
             mLooper = new TestableLooper(mHandler.getLooper());
diff --git a/tests/src/com/android/services/telephony/rcs/UceControllerManagerTest.java b/tests/src/com/android/services/telephony/rcs/UceControllerManagerTest.java
index 8d719fd..17decb9 100644
--- a/tests/src/com/android/services/telephony/rcs/UceControllerManagerTest.java
+++ b/tests/src/com/android/services/telephony/rcs/UceControllerManagerTest.java
@@ -19,6 +19,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
@@ -199,9 +200,9 @@
         doReturn(false).when(mUceController).isUnavailable();
         uceCtrlManager.onRcsConnected(mRcsFeatureManager);
 
-        uceCtrlManager.getUcePublishState();
+        uceCtrlManager.getUcePublishState(true);
 
-        verify(mUceController).getUcePublishState();
+        verify(mUceController).getUcePublishState(eq(true));
     }
 
     @Test
@@ -211,7 +212,7 @@
         uceCtrlManager.onRcsDisconnected();
 
         try {
-            uceCtrlManager.getUcePublishState();
+            uceCtrlManager.getUcePublishState(true);
             fail();
         } catch (ImsException e) {
             assertEquals(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE, e.getCode());
@@ -225,9 +226,9 @@
         UceControllerManager uceCtrlManager = getUceControllerManager();
         IRcsUcePublishStateCallback callback = Mockito.mock(IRcsUcePublishStateCallback.class);
 
-        uceCtrlManager.registerPublishStateCallback(callback);
+        uceCtrlManager.registerPublishStateCallback(callback, true);
 
-        verify(mUceController).registerPublishStateCallback(callback);
+        verify(mUceController).registerPublishStateCallback(callback, true);
     }
 
     @Test
@@ -238,7 +239,7 @@
 
         try {
             IRcsUcePublishStateCallback callback = Mockito.mock(IRcsUcePublishStateCallback.class);
-            uceCtrlManager.registerPublishStateCallback(callback);
+            uceCtrlManager.registerPublishStateCallback(callback, true);
             fail();
         } catch (ImsException e) {
             assertEquals(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE, e.getCode());