Add intent-filter priority for CONFIGURE_VOICEMAIL intent. am: 5cd723c11b am: f8fb0e7220 am: 13ab2b0d51 am: 188a9a9e4f am: cabe5e73ff am: b783476a08 am: 058c2033e1

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/services/Telephony/+/14882717

Change-Id: I193ee67363c4fc80c6c3eafd7c5f11bd4e40a4f7
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/OWNERS b/OWNERS
index 1ea2d9e..b4ef543 100644
--- a/OWNERS
+++ b/OWNERS
@@ -6,12 +6,12 @@
 tgunn@google.com
 jminjie@google.com
 shuoq@google.com
-nazaninb@google.com
 sarahchin@google.com
 xiaotonj@google.com
 huiwang@google.com
 jayachandranc@google.com
 chinmayd@google.com
 amruthr@google.com
+sasindran@google.com
 
 per-file *SimPhonebookProvider* = file:platform/packages/apps/Contacts:/OWNERS
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index ba797a3..03b0be9 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -341,6 +341,10 @@
     private static final int CMD_GET_SLICING_CONFIG = 110;
     private static final int EVENT_GET_SLICING_CONFIG_DONE = 111;
     private static final int CMD_ERASE_DATA_SHARED_PREFERENCES = 112;
+    private static final int CMD_ENABLE_VONR = 113;
+    private static final int EVENT_ENABLE_VONR_DONE = 114;
+    private static final int CMD_IS_VONR_ENABLED = 115;
+    private static final int EVENT_IS_VONR_ENABLED_DONE = 116;
 
     // Parameters of select command.
     private static final int SELECT_COMMAND = 0xA4;
@@ -834,7 +838,7 @@
                     } else {
                         // request.result must be set to something non-null
                         // for the calling thread to unblock
-                        if (request.result != null) {
+                        if (ar.result != null) {
                             request.result = ar.result;
                         } else {
                             request.result = false;
@@ -851,6 +855,46 @@
                     notifyRequester(request);
                     break;
 
+                case CMD_IS_VONR_ENABLED: {
+                    request = (MainThreadRequest) msg.obj;
+                    onCompleted = obtainMessage(EVENT_IS_VONR_ENABLED_DONE,
+                            request);
+                    Phone phone = getPhoneFromRequest(request);
+                    if (phone != null) {
+                        phone.isVoNrEnabled(onCompleted, request.workSource);
+                    } else {
+                        loge("isVoNrEnabled: No phone object");
+                        request.result = false;
+                        notifyRequester(request);
+                    }
+                    break;
+                }
+
+                case EVENT_IS_VONR_ENABLED_DONE:
+                    ar = (AsyncResult) msg.obj;
+                    request = (MainThreadRequest) ar.userObj;
+                    if (ar.exception == null && ar.result != null) {
+                        request.result = ar.result;
+                    } else {
+                        // request.result must be set to something non-null
+                        // for the calling thread to unblock
+                        if (ar.result != null) {
+                            request.result = ar.result;
+                        } else {
+                            request.result = false;
+                        }
+                        if (ar.result == null) {
+                            loge("isVoNrEnabled: Empty response");
+                        } else if (ar.exception instanceof CommandException) {
+                            loge("isVoNrEnabled: CommandException: "
+                                    + ar.exception);
+                        } else {
+                            loge("isVoNrEnabled: Unknown exception");
+                        }
+                    }
+                    notifyRequester(request);
+                    break;
+
                 case CMD_ENABLE_NR_DUAL_CONNECTIVITY: {
                     request = (MainThreadRequest) msg.obj;
                     onCompleted = obtainMessage(EVENT_ENABLE_NR_DUAL_CONNECTIVITY_DONE, request);
@@ -899,6 +943,49 @@
                     break;
                 }
 
+                case CMD_ENABLE_VONR: {
+                    request = (MainThreadRequest) msg.obj;
+                    onCompleted = obtainMessage(EVENT_ENABLE_VONR_DONE, request);
+                    Phone phone = getPhoneFromRequest(request);
+                    if (phone != null) {
+                        phone.setVoNrEnabled((boolean) request.argument, onCompleted,
+                                request.workSource);
+                    } else {
+                        loge("setVoNrEnabled: No phone object");
+                        request.result =
+                                TelephonyManager.ENABLE_VONR_RADIO_NOT_AVAILABLE;
+                        notifyRequester(request);
+                    }
+                    break;
+                }
+
+                case EVENT_ENABLE_VONR_DONE: {
+                    ar = (AsyncResult) msg.obj;
+                    request = (MainThreadRequest) ar.userObj;
+                    if (ar.exception == null) {
+                        request.result = TelephonyManager.ENABLE_VONR_SUCCESS;
+                    } else {
+                        request.result = TelephonyManager.ENABLE_VONR_RADIO_ERROR;
+                        if (ar.exception instanceof CommandException) {
+                            CommandException.Error error =
+                                    ((CommandException) (ar.exception)).getCommandError();
+                            if (error == CommandException.Error.RADIO_NOT_AVAILABLE) {
+                                request.result = TelephonyManager.ENABLE_VONR_RADIO_NOT_AVAILABLE;
+                            } else if (error == CommandException.Error.REQUEST_NOT_SUPPORTED) {
+                                request.result = TelephonyManager.ENABLE_VONR_REQUEST_NOT_SUPPORTED;
+                            } else {
+                                request.result = TelephonyManager.ENABLE_VONR_RADIO_ERROR;
+                            }
+                            loge("setVoNrEnabled" + ": CommandException: "
+                                    + ar.exception);
+                        } else {
+                            loge("setVoNrEnabled" + ": Unknown exception");
+                        }
+                    }
+                    notifyRequester(request);
+                    break;
+                }
+
                 case CMD_GET_ALLOWED_NETWORK_TYPES_BITMASK:
                     request = (MainThreadRequest) msg.obj;
                     onCompleted = obtainMessage(EVENT_GET_ALLOWED_NETWORK_TYPES_BITMASK_DONE,
@@ -1056,7 +1143,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(),
@@ -2947,6 +3034,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(
@@ -8205,6 +8300,53 @@
     }
 
     /**
+     * Enable or disable Voice over NR (VoNR)
+     * @param subId the subscription ID that this action applies to.
+     * @param enabled enable or disable VoNR.
+     * @return operation result.
+     */
+    @Override
+    public int setVoNrEnabled(int subId, boolean enabled) {
+        enforceModifyPermission();
+        final Phone phone = getPhone(subId);
+
+        final long identity = Binder.clearCallingIdentity();
+        if (phone == null) {
+            loge("setVoNrEnabled fails with no phone object for subId: " + subId);
+            return TelephonyManager.ENABLE_VONR_RADIO_NOT_AVAILABLE;
+        }
+
+        WorkSource workSource = getWorkSource(Binder.getCallingUid());
+        try {
+            int result = (int) sendRequest(CMD_ENABLE_VONR, enabled, subId,
+                    workSource);
+            if (DBG) log("setVoNrEnabled result: " + result);
+            return result;
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
+     * Is voice over NR enabled
+     * @return true if VoNR is enabled else false
+     */
+    @Override
+    public boolean isVoNrEnabled(int subId) {
+        enforceReadPrivilegedPermission("isVoNrEnabled");
+        WorkSource workSource = getWorkSource(Binder.getCallingUid());
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            boolean isEnabled = (boolean) sendRequest(CMD_IS_VONR_ENABLED,
+                    null, subId, workSource);
+            if (DBG) log("isVoNrEnabled: " + isEnabled);
+            return isEnabled;
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
      * Action set from carrier signalling broadcast receivers to start/stop reporting the default
      * network status based on which carrier apps could apply actions accordingly,
      * enable/disable default url handler for example.
diff --git a/src/com/android/phone/RcsProvisioningMonitor.java b/src/com/android/phone/RcsProvisioningMonitor.java
index 23c4c5a..6d2bd6f 100644
--- a/src/com/android/phone/RcsProvisioningMonitor.java
+++ b/src/com/android/phone/RcsProvisioningMonitor.java
@@ -75,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
@@ -220,7 +224,19 @@
         }
 
         void setSingleRegistrationCapability(int singleRegistrationCapability) {
-            mSingleRegistrationCapability = singleRegistrationCapability;
+            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() {
@@ -675,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
@@ -715,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) {
@@ -735,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;
     }
@@ -746,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));
         });
     }
 
@@ -765,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);
             }
         }
 
@@ -783,6 +797,10 @@
         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);
     }
@@ -852,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/SimPhonebookProvider.java b/src/com/android/phone/SimPhonebookProvider.java
index b921398..04c4f48 100644
--- a/src/com/android/phone/SimPhonebookProvider.java
+++ b/src/com/android/phone/SimPhonebookProvider.java
@@ -16,8 +16,8 @@
 
 package com.android.phone;
 
-import static com.android.internal.telephony.IccProvider.STR_NEW_TAG;
 import static com.android.internal.telephony.IccProvider.STR_NEW_NUMBER;
+import static com.android.internal.telephony.IccProvider.STR_NEW_TAG;
 
 import android.Manifest;
 import android.annotation.TestApi;
@@ -97,6 +97,8 @@
     private static final String TAG = "SimPhonebookProvider";
     private static final Set<String> ELEMENTARY_FILES_COLUMNS_SET =
             ImmutableSet.copyOf(ELEMENTARY_FILES_ALL_COLUMNS);
+    private static final Set<String> SIM_RECORDS_COLUMNS_SET =
+            ImmutableSet.copyOf(SIM_RECORDS_ALL_COLUMNS);
     private static final Set<String> SIM_RECORDS_WRITABLE_COLUMNS = ImmutableSet.of(
             SimRecords.NAME, SimRecords.PHONE_NUMBER
     );
@@ -305,8 +307,10 @@
 
         MatrixCursor result = new MatrixCursor(projection);
         try {
-            addEfToCursor(
-                    result, getActiveSubscriptionInfo(args.subscriptionId), args.efType);
+            SubscriptionInfo info = getActiveSubscriptionInfo(args.subscriptionId);
+            if (info != null) {
+                addEfToCursor(result, info, args.efType);
+            }
         } catch (RemoteException e) {
             // Return an empty cursor. If service to access it is throwing remote
             // exceptions then it's basically the same as not having a SIM.
@@ -353,6 +357,7 @@
     }
 
     private Cursor querySimRecords(PhonebookArgs args, String[] projection) {
+        validateProjection(SIM_RECORDS_COLUMNS_SET, projection);
         validateSubscriptionAndEf(args);
         if (projection == null) {
             projection = SIM_RECORDS_ALL_COLUMNS;
@@ -407,6 +412,7 @@
     }
 
     private Cursor querySimRecordsItem(PhonebookArgs args, String[] projection) {
+        validateProjection(SIM_RECORDS_COLUMNS_SET, projection);
         if (projection == null) {
             projection = SIM_RECORDS_ALL_COLUMNS;
         }
@@ -734,6 +740,7 @@
         }
     }
 
+    @Nullable
     private SubscriptionInfo getActiveSubscriptionInfo(int subId) {
         // Getting the SubscriptionInfo requires READ_PHONE_STATE.
         CallingIdentity identity = clearCallingIdentity();
diff --git a/src/com/android/phone/settings/RadioInfo.java b/src/com/android/phone/settings/RadioInfo.java
index b1ab413..d4c926e 100644
--- a/src/com/android/phone/settings/RadioInfo.java
+++ b/src/com/android/phone/settings/RadioInfo.java
@@ -673,6 +673,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);
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/ImsConference.java b/src/com/android/services/telephony/ImsConference.java
index 0be927a..7f088f7 100644
--- a/src/com/android/services/telephony/ImsConference.java
+++ b/src/com/android/services/telephony/ImsConference.java
@@ -257,7 +257,7 @@
 
                 @Override
                 public void onConnectionPropertiesChanged(Connection c, int connectionProperties) {
-                    Log.d(this, "onConnectionPropertiesChanged: Connection: %s,"
+                    Log.i(ImsConference.this, "onConnectionPropertiesChanged: Connection: %s,"
                             + " connectionProperties: %s", c, connectionProperties);
                     updateConnectionProperties(connectionProperties);
                 }
@@ -383,6 +383,11 @@
     private boolean mIsUsingSimCallManager = false;
 
     /**
+     * See {@link #isRemotelyHosted()} for details.
+     */
+    private boolean mWasRemotelyHosted = false;
+
+    /**
      * Where {@link #isMultiparty()} is {@code false}, contains the
      * {@link ConferenceParticipantConnection#getUserEntity()} and
      * {@link ConferenceParticipantConnection#getEndpoint()} of the single participant which this
@@ -522,11 +527,12 @@
                 (properties & Connection.PROPERTY_IS_EXTERNAL_CALL) != 0);
 
         conferenceProperties = changeBitmask(conferenceProperties,
-                Connection.PROPERTY_REMOTELY_HOSTED, !isConferenceHost());
+                Connection.PROPERTY_REMOTELY_HOSTED, isRemotelyHosted());
 
         conferenceProperties = changeBitmask(conferenceProperties,
                 Connection.PROPERTY_IS_ADHOC_CONFERENCE,
                 (properties & Connection.PROPERTY_IS_ADHOC_CONFERENCE) != 0);
+        Log.i(this, "applyHostProperties: confProp=%s", conferenceProperties);
 
         return conferenceProperties;
     }
@@ -774,6 +780,26 @@
     }
 
     /**
+     * Returns whether the conference is remotely hosted or not.
+     * This method will cache the current remotely hosted state when the conference host or
+     * original connection becomes null.  This is important for scenarios where the conference host
+     * or original connection changes midway through a conference such as in an SRVCC scenario.
+     * @return {@code true} if the conference was remotely hosted based on the conference host and
+     * its original connection, or based on the last known remotely hosted state.  {@code false}
+     * otherwise.
+     */
+    public boolean isRemotelyHosted() {
+        if (mConferenceHost == null || mConferenceHost.getOriginalConnection() == null) {
+            return mWasRemotelyHosted;
+        }
+        com.android.internal.telephony.Connection originalConnection =
+                mConferenceHost.getOriginalConnection();
+        mWasRemotelyHosted = originalConnection.isMultiparty()
+                && !originalConnection.isConferenceHost();
+        return mWasRemotelyHosted;
+    }
+
+    /**
      * Determines if this conference is hosted on the current device or the peer device.
      *
      * @return {@code true} if this conference is hosted on the current device, {@code false} if it
@@ -1209,6 +1235,7 @@
         ConferenceParticipantConnection connection = new ConferenceParticipantConnection(
                 parent.getOriginalConnection(), participant,
                 !isConferenceHost() /* isRemotelyHosted */);
+
         if (participant.getConnectTime() == 0) {
             connection.setConnectTimeMillis(parent.getConnectTimeMillis());
             connection.setConnectionStartElapsedRealtimeMillis(
diff --git a/src/com/android/services/telephony/TelephonyConferenceController.java b/src/com/android/services/telephony/TelephonyConferenceController.java
index 228541a..9aa3dbe 100644
--- a/src/com/android/services/telephony/TelephonyConferenceController.java
+++ b/src/com/android/services/telephony/TelephonyConferenceController.java
@@ -40,6 +40,7 @@
  */
 final class TelephonyConferenceController {
     private static final int TELEPHONY_CONFERENCE_MAX_SIZE = 5;
+    private static final String RIL_REPORTED_CONFERENCE_CALL_STRING = "Conference Call";
 
     private final TelephonyConnection.TelephonyConnectionListener mTelephonyConnectionListener =
             new TelephonyConnection.TelephonyConnectionListener() {
@@ -179,7 +180,6 @@
     private void recalculateConference() {
         Set<TelephonyConnection> conferencedConnections = new HashSet<>();
         int numGsmConnections = 0;
-
         for (TelephonyConnection connection : mTelephonyConnections) {
             com.android.internal.telephony.Connection radioConnection =
                 connection.getOriginalConnection();
@@ -271,11 +271,19 @@
                             // Remove all instances of PROPERTY_IS_DOWNGRADED_CONFERENCE. This
                             // property should only be set on the parent call (i.e. the newly
                             // created TelephonyConference.
-                            Log.d(this, "Removing PROPERTY_IS_DOWNGRADED_CONFERENCE from connection"
-                                    + " %s", connection);
-                            int newProperties = connection.getConnectionProperties()
-                                    & ~Connection.PROPERTY_IS_DOWNGRADED_CONFERENCE;
-                            connection.setTelephonyConnectionProperties(newProperties);
+                            // This doesn't apply to a connection whose address is "Conference
+                            // Call", which may be updated by some modem to create a connection
+                            // to represent a merged conference connection in SRVCC.
+                            if (connection.getAddress() == null
+                                    || !connection.getAddress().getSchemeSpecificPart()
+                                            .equalsIgnoreCase(
+                                                    RIL_REPORTED_CONFERENCE_CALL_STRING)) {
+                                Log.d(this, "Removing PROPERTY_IS_DOWNGRADED_CONFERENCE"
+                                        + " from connection %s", connection);
+                                int newProperties = connection.getConnectionProperties()
+                                        & ~Connection.PROPERTY_IS_DOWNGRADED_CONFERENCE;
+                                connection.setTelephonyConnectionProperties(newProperties);
+                            }
                             isDowngradedConference = true;
                         }
                         mTelephonyConference.addTelephonyConnection(connection);
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index 53e923e..ce3cf01 100755
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -3810,4 +3810,13 @@
             mCommunicator.sendMessages(set);
         }
     }
+
+    /**
+     * Returns the current telephony connection listeners for test purposes.
+     * @return list of telephony connection listeners.
+     */
+    @VisibleForTesting
+    public List<TelephonyConnectionListener> getTelephonyConnectionListeners() {
+        return new ArrayList<>(mTelephonyListeners);
+    }
 }
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 7a0d8c2..4f6acc8 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -1199,9 +1199,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();
@@ -2084,8 +2084,7 @@
             if (phone.getEmergencyNumberTracker() != null) {
                 if (phone.getEmergencyNumberTracker().isEmergencyNumber(
                         emergencyNumberAddress, true)) {
-                    if (phone.getHalVersion().greaterOrEqual(RIL.RADIO_HAL_VERSION_1_4)
-                            || isAvailableForEmergencyCalls(phone)) {
+                    if (isAvailableForEmergencyCalls(phone)) {
                         // a)
                         if (phone.getPhoneId() == defaultVoicePhoneId) {
                             Log.i(this, "getPhoneForEmergencyCall, Phone Id that supports"
@@ -2208,12 +2207,6 @@
                 // Only sort if there are enough elements to do so.
                 if (phoneSlotStatus.size() > 1) {
                     Collections.sort(phoneSlotStatus, (o1, o2) -> {
-                        if (!o1.hasDialedEmergencyNumber && o2.hasDialedEmergencyNumber) {
-                            return -1;
-                        }
-                        if (o1.hasDialedEmergencyNumber && !o2.hasDialedEmergencyNumber) {
-                            return 1;
-                        }
                         // Sort by non-absent SIM.
                         if (o1.simState == TelephonyManager.SIM_STATE_ABSENT
                                 && o2.simState != TelephonyManager.SIM_STATE_ABSENT) {
@@ -2232,6 +2225,13 @@
                         if (o2.isLocked && !o1.isLocked) {
                             return 1;
                         }
+                        // Prefer slots where the number is considered emergency.
+                        if (!o1.hasDialedEmergencyNumber && o2.hasDialedEmergencyNumber) {
+                            return -1;
+                        }
+                        if (o1.hasDialedEmergencyNumber && !o2.hasDialedEmergencyNumber) {
+                            return 1;
+                        }
                         // sort by number of RadioAccessFamily Capabilities.
                         int compare = RadioAccessFamily.compare(o1.capabilities, o2.capabilities);
                         if (compare == 0) {
diff --git a/tests/src/com/android/phone/RcsProvisioningMonitorTest.java b/tests/src/com/android/phone/RcsProvisioningMonitorTest.java
index 4fba922..8e5e073 100644
--- a/tests/src/com/android/phone/RcsProvisioningMonitorTest.java
+++ b/tests/src/com/android/phone/RcsProvisioningMonitorTest.java
@@ -305,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++) {
@@ -313,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());
     }
 
@@ -324,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());
     }
@@ -340,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);
@@ -401,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);
@@ -421,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);
@@ -435,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);
@@ -479,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);
@@ -580,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
@@ -611,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);
@@ -694,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);
diff --git a/tests/src/com/android/phone/SimPhonebookProviderTest.java b/tests/src/com/android/phone/SimPhonebookProviderTest.java
index f897fac..29a653d 100644
--- a/tests/src/com/android/phone/SimPhonebookProviderTest.java
+++ b/tests/src/com/android/phone/SimPhonebookProviderTest.java
@@ -56,6 +56,7 @@
 import com.android.internal.telephony.uicc.IccConstants;
 
 import com.google.common.collect.ImmutableList;
+import com.google.common.io.Closeables;
 import com.google.common.truth.Correspondence;
 
 import org.junit.Before;
@@ -234,6 +235,19 @@
     }
 
     @Test
+    public void query_elementaryFilesItem_nonExistentSubscriptionId_returnsEmptyCursor() {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.makeAllEfsSupported(1);
+
+        // Subscription ID 2 does not exist
+        Uri nonExistentElementaryFileItemUri = ElementaryFiles.getItemUri(2, EF_ADN);
+
+        try (Cursor cursor = mResolver.query(nonExistentElementaryFileItemUri, null, null, null)) {
+            assertThat(Objects.requireNonNull(cursor)).hasCount(0);
+        }
+    }
+
+    @Test
     public void query_adnRecords_returnsCursorWithMatchingProjection() {
         setupSimsWithSubscriptionIds(1);
         mIccPhoneBook.makeAllEfsSupported(1);
@@ -275,6 +289,33 @@
     }
 
     @Test
+    public void query_adnRecords_invalidColumnProjection_throwsIllegalArgumentException() {
+        setupSimsWithSubscriptionIds(1);
+        mIccPhoneBook.makeAllEfsSupported(1);
+        Uri contentAdn = SimRecords.getContentUri(1, EF_ADN);
+
+        assertThrows(IllegalArgumentException.class, () -> Closeables.close(
+                mResolver.query(contentAdn, new String[] {
+                        "an_unsupported_column",
+                }, null, null), false)
+        );
+
+        assertThrows(IllegalArgumentException.class, () -> Closeables.close(
+                mResolver.query(contentAdn, new String[] {
+                        SimRecords.RECORD_NUMBER,
+                        "an_unsupported_column"
+                }, null, null), false)
+        );
+
+        assertThrows(IllegalArgumentException.class, () -> Closeables.close(
+                mResolver.query(contentAdn, new String[] {
+                        "an_unsupported_column",
+                        SimRecords.RECORD_NUMBER
+                }, null, null), false)
+        );
+    }
+
+    @Test
     public void query_adnRecords_noRecords_returnsEmptyCursor() {
         setupSimsWithSubscriptionIds(1);
         mIccPhoneBook.makeAllEfsSupported(1);
diff --git a/tests/src/com/android/services/telephony/ImsConferenceTest.java b/tests/src/com/android/services/telephony/ImsConferenceTest.java
index 3bc5ee8..9d2f5ac 100644
--- a/tests/src/com/android/services/telephony/ImsConferenceTest.java
+++ b/tests/src/com/android/services/telephony/ImsConferenceTest.java
@@ -622,6 +622,46 @@
     }
 
     /**
+     * Tests a scenario where a handover connection arrives via
+     * {@link TelephonyConnection#onOriginalConnectionRedialed(
+     * com.android.internal.telephony.Connection)}.  During this process, the conference properties
+     * get updated.  Since the original connection is null at this point, we need to verify that
+     * the remotely hosted property is retained from before the original connection was nulled.
+     */
+    @Test
+    public void testIsConferenceRemotelyHostedCachingOnSRVCC() {
+        mConferenceHost.setIsImsConnection(true);
+        when(mConferenceHost.getMockImsPhoneConnection().isMultiparty()).thenReturn(true);
+        when(mConferenceHost.getMockImsPhoneConnection().isConferenceHost()).thenReturn(true);
+
+        // Start out with a valid conference host.
+        ImsConference imsConference = new ImsConference(mMockTelecomAccountRegistry,
+                mMockTelephonyConnectionServiceProxy, mConferenceHost,
+                null /* phoneAccountHandle */, () -> false /* featureFlagProxy */,
+                new ImsConference.CarrierConfiguration.Builder().build());
+
+        // By default it is not remotely hosted.
+        assertFalse(imsConference.isRemotelyHosted());
+        assertEquals(0,
+                imsConference.getConnectionProperties() & Connection.PROPERTY_REMOTELY_HOSTED);
+
+        // Simulate a change to the original connection due to srvcc
+        com.android.internal.telephony.Connection previousOriginalConnection =
+                mConferenceHost.getMockImsPhoneConnection();
+        mConferenceHost.setMockImsPhoneConnection(null);
+
+        // Trigger the property update which takes place when the original connection changes.
+        mConferenceHost.getTelephonyConnectionListeners().forEach(
+                l -> l.onConnectionPropertiesChanged(mConferenceHost,
+                        mConferenceHost.getConnectionProperties()));
+
+        // Should still NOT be remotely hosted based on cached value.
+        assertFalse(imsConference.isRemotelyHosted());
+        assertEquals(0,
+                imsConference.getConnectionProperties() & Connection.PROPERTY_REMOTELY_HOSTED);
+    }
+
+    /**
      * Verifies that an ImsConference can handle SIP and TEL URIs for both the P-Associated-Uri and
      * conference event package identities.
      */
diff --git a/tests/src/com/android/services/telephony/TelephonyConferenceControllerTest.java b/tests/src/com/android/services/telephony/TelephonyConferenceControllerTest.java
index cfdc2fd..b7fe988 100644
--- a/tests/src/com/android/services/telephony/TelephonyConferenceControllerTest.java
+++ b/tests/src/com/android/services/telephony/TelephonyConferenceControllerTest.java
@@ -23,9 +23,11 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.net.Uri;
 import android.os.Looper;
 import android.telecom.Conference;
 import android.telecom.Connection;
+import android.telecom.PhoneAccount;
 import android.test.suitebuilder.annotation.SmallTest;
 
 import org.junit.Before;
@@ -35,7 +37,9 @@
 import org.mockito.MockitoAnnotations;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
+import java.util.List;
 
 /**
  * Tests the functionality in TelephonyConferenceController.java
@@ -111,6 +115,46 @@
     }
 
     /**
+     * Verify the connection with "Conference Call" with PROPERTY_IS_DOWNGRADED_CONFERENCE
+     * during SRVCC
+     */
+    @Test
+    @SmallTest
+    public void testSrvccConferenceConnection() {
+        when(mTestTelephonyConnectionA.mMockRadioConnection.getCall()
+                .isMultiparty()).thenReturn(true);
+        when(mTestTelephonyConnectionB.mMockRadioConnection.getCall()
+                .isMultiparty()).thenReturn(true);
+
+        List<Connection> listConnections = Arrays.asList(
+                mTestTelephonyConnectionA, mTestTelephonyConnectionB);
+        when(mMockTelephonyConnectionServiceProxy.getAllConnections()).thenReturn(listConnections);
+
+        mTestTelephonyConnectionA.setAddress(
+                Uri.fromParts(PhoneAccount.SCHEME_TEL, "Conference Call", null), 0);
+        mTestTelephonyConnectionA.setTelephonyConnectionProperties(
+                Connection.PROPERTY_IS_DOWNGRADED_CONFERENCE);
+        mTestTelephonyConnectionB.setAddress(
+                Uri.fromParts(PhoneAccount.SCHEME_TEL, "5551213", null), 0);
+        mTestTelephonyConnectionB.setTelephonyConnectionProperties(
+                Connection.PROPERTY_IS_DOWNGRADED_CONFERENCE);
+
+        // add telephony connection B
+        mControllerTest.add(mTestTelephonyConnectionB);
+
+        // add telephony connection A
+        mControllerTest.add(mTestTelephonyConnectionA);
+
+        // verify the connection with "Conference Call" has PROPERTY_IS_DOWNGRADED_CONFERENCE
+        assertTrue((mTestTelephonyConnectionA.getConnectionProperties()
+                & Connection.PROPERTY_IS_DOWNGRADED_CONFERENCE) != 0);
+
+        // verify the connection with "5551213" hasn't PROPERTY_IS_DOWNGRADED_CONFERENCE
+        assertFalse((mTestTelephonyConnectionB.getConnectionProperties()
+                & Connection.PROPERTY_IS_DOWNGRADED_CONFERENCE) != 0);
+    }
+
+    /**
      * Behavior: add telephony connection B and A to conference controller,
      *           set status for connections and merged calls, remove one call
      * Assumption: after performing the behaviours, the status of Connection A is STATE_ACTIVE;
diff --git a/tests/src/com/android/services/telephony/TestTelephonyConnection.java b/tests/src/com/android/services/telephony/TestTelephonyConnection.java
index 817e9a7..e149d3b 100644
--- a/tests/src/com/android/services/telephony/TestTelephonyConnection.java
+++ b/tests/src/com/android/services/telephony/TestTelephonyConnection.java
@@ -305,4 +305,12 @@
     public PersistableBundle getCarrierConfigBundle() {
         return mCarrierConfig;
     }
+
+    public ImsPhoneConnection getMockImsPhoneConnection() {
+        return mImsPhoneConnection;
+    }
+
+    public void setMockImsPhoneConnection(ImsPhoneConnection connection) {
+        mImsPhoneConnection = connection;
+    }
 }