Merge "Added API on PhoneInterfaceManager for updating fplmn"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 49c1571..0bba1f8 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -138,6 +138,7 @@
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
     <uses-permission android:name="android.permission.WRITE_APN_SETTINGS" />
     <uses-permission android:name="android.permission.BROADCAST_SMS"/>
     <uses-permission android:name="android.permission.BROADCAST_WAP_PUSH"/>
@@ -169,6 +170,7 @@
     <uses-permission android:name="android.permission.BIND_CARRIER_MESSAGING_SERVICE" />
     <uses-permission android:name="android.permission.BIND_EUICC_SERVICE" />
     <uses-permission android:name="com.android.permission.BIND_TELEPHONY_NETWORK_SERVICE" />
+    <uses-permission android:name="android.permission.BIND_CELL_BROADCAST_SERVICE" />
     <uses-permission android:name="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS" />
     <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
     <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
@@ -199,6 +201,10 @@
     <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
     <uses-permission android:name="android.permission.READ_PRECISE_PHONE_STATE" />
     <uses-permission android:name="android.permission.MANAGE_ROLE_HOLDERS" />
+    <!-- Allows us to whitelist receivers of the
+         ACTION_SIM_SLOT_STATUS_CHANGED broadcast to start activities
+         from the background.  -->
+    <uses-permission android:name="android.permission.START_ACTIVITIES_FROM_BACKGROUND" />
 
     <application android:name="PhoneApp"
             android:persistent="true"
diff --git a/OWNERS b/OWNERS
index 1ef8344..5be6fe5 100644
--- a/OWNERS
+++ b/OWNERS
@@ -11,3 +11,4 @@
 shuoq@google.com
 paulye@google.com
 nazaninb@google.com
+sarahchin@google.com
\ No newline at end of file
diff --git a/ecc/conversion_toolset_v1/gen_eccdata.sh b/ecc/conversion_toolset_v1/gen_eccdata.sh
index 1efac37..9fc0efc 100644
--- a/ecc/conversion_toolset_v1/gen_eccdata.sh
+++ b/ecc/conversion_toolset_v1/gen_eccdata.sh
@@ -19,8 +19,7 @@
 source "${LOCAL_TOOLSET_DIR}/env.sh"
 
 echo "Converting eccdata..."
-${ANDROID_BUILD_TOP}/prebuilts/tools/linux-x86_64/protoc/bin/protoc \
-  --encode=ecc.AllInfo proto/protobuf_ecc_data.proto \
+aprotoc --encode=ecc.AllInfo proto/protobuf_ecc_data.proto \
   < "${INPUT_DATA}" > "${RAW_DATA}"
 
 echo "Compressing eccdata..."
diff --git a/ecc/gen_eccdata.sh b/ecc/gen_eccdata.sh
index e4dd745..2888585 100755
--- a/ecc/gen_eccdata.sh
+++ b/ecc/gen_eccdata.sh
@@ -20,24 +20,8 @@
   exit 1
 fi
 
-case $(uname -s) in
-  Darwin)
-    KERNEL=darwin
-    ;;
-  Linux)
-    KERNEL=linux
-    ;;
-  *)
-    echo "Unknown kernel \"`uname -s`\"" 1>&2
-    exit 1
-    ;;
-esac
-
-read -d "" PROTOC_COMMAND << END || :
-${ANDROID_BUILD_TOP}/prebuilts/tools/${KERNEL}-x86_64/protoc/bin/protoc
-END
-if ! [ -x "${PROTOC_COMMAND}" ] ; then
-  echo "Missing ${PROTOC_COMMAND}." 1>&2
+if ! [ -x "$(which aprotoc)" ] ; then
+  echo "Missing aprotoc, build it with 'm aprotoc'." 1>&2
   exit 1
 fi
 
diff --git a/res/values/strings.xml b/res/values/strings.xml
index c68deb2..dd8abe7 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1547,6 +1547,15 @@
          message is shown when an in-progress call is ended due to the battery being low. -->
     <string name="callFailed_low_battery">Video call ended due to low battery.</string>
 
+    <!-- In-call screen: error message shown when the user attempts to place an emergency call
+         over wifi calling (WFC), but emergency services are not available in the current
+         location. -->
+    <string name="callFailed_emergency_call_over_wfc_not_available">Emergency calls over Wi-Fi calling not available in this location.</string>
+
+    <!-- In-call screen: error message shown when the user attempts to place a call over wifi
+         calling (WFC), but wifi calling is not available in the current location. -->
+    <string name="callFailed_wfc_service_not_available_in_this_location">Wi-Fi calling is not available in this location.</string>
+
     <!-- The title for the change voicemail PIN activity -->
     <string name="change_pin_title">Change Voicemail PIN</string>
     <!-- The label for the continue button in change voicemail PIN activity -->
diff --git a/sip/src/com/android/services/telephony/sip/SipProfileDb.java b/sip/src/com/android/services/telephony/sip/SipProfileDb.java
index bb1c7ec..812ebb4 100644
--- a/sip/src/com/android/services/telephony/sip/SipProfileDb.java
+++ b/sip/src/com/android/services/telephony/sip/SipProfileDb.java
@@ -16,11 +16,10 @@
 
 package com.android.services.telephony.sip;
 
-import com.android.internal.os.AtomicFile;
-
 import android.content.Context;
 import android.net.sip.SipProfile;
 import android.text.TextUtils;
+import android.util.AtomicFile;
 import android.util.EventLog;
 import android.util.Log;
 
diff --git a/src/com/android/phone/CarrierConfigLoader.java b/src/com/android/phone/CarrierConfigLoader.java
index 48047ca..d1eb3dc 100644
--- a/src/com/android/phone/CarrierConfigLoader.java
+++ b/src/com/android/phone/CarrierConfigLoader.java
@@ -194,7 +194,7 @@
 
                 case EVENT_SYSTEM_UNLOCKED:
                 {
-                    for (int i = 0; i < TelephonyManager.from(mContext).getPhoneCount(); ++i) {
+                    for (int i = 0; i < TelephonyManager.from(mContext).getMaxPhoneCount(); ++i) {
                         // When user unlock device, we should only try to send broadcast again if we
                         // have sent it before unlock. This will avoid we try to load carrier config
                         // when SIM is still loading when unlock happens.
@@ -211,7 +211,7 @@
                     // Only update if there are cached config removed to avoid updating config for
                     // unrelated packages.
                     if (clearCachedConfigForPackage(carrierPackageName)) {
-                        int numPhones = TelephonyManager.from(mContext).getPhoneCount();
+                        int numPhones = TelephonyManager.from(mContext).getMaxPhoneCount();
                         for (int i = 0; i < numPhones; ++i) {
                             updateConfigForPhoneId(i);
                         }
@@ -523,7 +523,7 @@
         pkgFilter.addDataScheme("package");
         context.registerReceiver(mPackageReceiver, pkgFilter);
 
-        int numPhones = TelephonyManager.from(context).getPhoneCount();
+        int numPhones = TelephonyManager.from(context).getMaxPhoneCount();
         mConfigFromDefaultApp = new PersistableBundle[numPhones];
         mConfigFromCarrierApp = new PersistableBundle[numPhones];
         mOverrideConfigs = new PersistableBundle[numPhones];
diff --git a/src/com/android/phone/EmergencyActionGroup.java b/src/com/android/phone/EmergencyActionGroup.java
index b8bf7a8..c090af7 100644
--- a/src/com/android/phone/EmergencyActionGroup.java
+++ b/src/com/android/phone/EmergencyActionGroup.java
@@ -161,7 +161,10 @@
             case R.id.action1:
             case R.id.action2:
             case R.id.action3:
-                if (AccessibilityManager.getInstance(mContext).isTouchExplorationEnabled()) {
+                AccessibilityManager accessibilityMgr =
+                        (AccessibilityManager) mContext.getSystemService(
+                                Context.ACCESSIBILITY_SERVICE);
+                if (accessibilityMgr.isTouchExplorationEnabled()) {
                     getContext().startActivity(intent);
                 } else {
                     revealTheButton(v);
diff --git a/src/com/android/phone/EmergencyAssistanceHelper.java b/src/com/android/phone/EmergencyAssistanceHelper.java
index 33788d3..79ee515 100644
--- a/src/com/android/phone/EmergencyAssistanceHelper.java
+++ b/src/com/android/phone/EmergencyAssistanceHelper.java
@@ -31,8 +31,6 @@
 import android.text.TextUtils;
 import android.util.Log;
 
-import com.android.internal.util.CollectionUtils;
-
 import java.util.List;
 
 /**
@@ -120,8 +118,9 @@
     private static String getDefaultEmergencyPackage(Context context) {
         long identity = Binder.clearCallingIdentity();
         try {
-            return CollectionUtils.firstOrNull(context.getSystemService(RoleManager.class)
-                    .getRoleHolders(RoleManager.ROLE_EMERGENCY));
+            List<String> roleHolders = context.getSystemService(RoleManager.class)
+                    .getRoleHolders(RoleManager.ROLE_EMERGENCY);
+            return roleHolders.isEmpty() ? null : roleHolders.get(0);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
diff --git a/src/com/android/phone/EmergencyDialer.java b/src/com/android/phone/EmergencyDialer.java
index 3cf74c8..42209c7 100644
--- a/src/com/android/phone/EmergencyDialer.java
+++ b/src/com/android/phone/EmergencyDialer.java
@@ -23,6 +23,7 @@
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.Dialog;
+import android.app.WallpaperColors;
 import android.app.WallpaperManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -31,6 +32,7 @@
 import android.database.DataSetObserver;
 import android.graphics.Color;
 import android.graphics.Point;
+import android.graphics.drawable.ColorDrawable;
 import android.media.AudioManager;
 import android.media.ToneGenerator;
 import android.net.Uri;
@@ -68,9 +70,6 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.TextView;
 
-import com.android.internal.colorextraction.ColorExtractor;
-import com.android.internal.colorextraction.ColorExtractor.GradientColors;
-import com.android.internal.colorextraction.drawable.ScrimDrawable;
 import com.android.phone.EmergencyDialerMetricsLogger.DialedFrom;
 import com.android.phone.EmergencyDialerMetricsLogger.PhoneNumberType;
 import com.android.phone.EmergencyDialerMetricsLogger.UiModeErrorCode;
@@ -100,7 +99,8 @@
  */
 public class EmergencyDialer extends Activity implements View.OnClickListener,
         View.OnLongClickListener, View.OnKeyListener, TextWatcher,
-        DialpadKeyButton.OnPressedListener, ColorExtractor.OnColorsChangedListener,
+        DialpadKeyButton.OnPressedListener,
+        WallpaperManager.OnColorsChangedListener,
         EmergencyShortcutButton.OnConfirmClickListener,
         EmergencyInfoGroup.OnConfirmClickListener {
 
@@ -212,8 +212,7 @@
     private String mLastNumber; // last number we tried to dial. Used to restore error dialog.
 
     // Background gradient
-    private ColorExtractor mColorExtractor;
-    private ScrimDrawable mBackgroundDrawable;
+    private ColorDrawable mBackgroundDrawable;
     private boolean mSupportsDarkText;
 
     private boolean mIsWfcEmergencyCallingWarningEnabled;
@@ -276,15 +275,13 @@
         Log.d(LOG_TAG, "Enable emergency dialer shortcut: "
                 + mShortcutViewConfig.isEnabled());
 
-        mColorExtractor = new ColorExtractor(this);
-
         if (mShortcutViewConfig.isEnabled()) {
             // Shortcut view doesn't support dark text theme.
             updateTheme(false);
         } else {
-            GradientColors lockScreenColors = mColorExtractor.getColors(WallpaperManager.FLAG_LOCK,
-                    ColorExtractor.TYPE_EXTRA_DARK);
-            updateTheme(lockScreenColors.supportsDarkText());
+            WallpaperColors wallpaperColors =
+                    getWallpaperManager().getWallpaperColors(WallpaperManager.FLAG_LOCK);
+            updateTheme(supportsDarkText(wallpaperColors));
         }
 
         setContentView(R.layout.emergency_dialer);
@@ -298,7 +295,7 @@
         mDefaultDigitsTextSize = mDigits.getScaledTextSize();
         maybeAddNumberFormatting();
 
-        mBackgroundDrawable = new ScrimDrawable();
+        mBackgroundDrawable = new ColorDrawable();
         Point displaySize = new Point();
         ((WindowManager) getSystemService(Context.WINDOW_SERVICE))
                 .getDefaultDisplay().getSize(displaySize);
@@ -647,15 +644,18 @@
 
         if (mShortcutViewConfig.isEnabled()) {
             // Shortcut view doesn't support dark text theme.
-            mBackgroundDrawable.setColor(Color.BLACK, false);
+            mBackgroundDrawable.setColor(Color.BLACK);
             updateTheme(false);
         } else {
-            mColorExtractor.addOnColorsChangedListener(this);
-            GradientColors lockScreenColors = mColorExtractor.getColors(WallpaperManager.FLAG_LOCK,
-                    ColorExtractor.TYPE_EXTRA_DARK);
-            // Do not animate when view isn't visible yet, just set an initial state.
-            mBackgroundDrawable.setColor(lockScreenColors.getMainColor(), false);
-            updateTheme(lockScreenColors.supportsDarkText());
+            WallpaperManager wallpaperManager = getWallpaperManager();
+            if (wallpaperManager.isWallpaperSupported()) {
+                wallpaperManager.addOnColorsChangedListener(this, null);
+            }
+
+            WallpaperColors wallpaperColors =
+                    wallpaperManager.getWallpaperColors(WallpaperManager.FLAG_LOCK);
+            mBackgroundDrawable.setColor(getPrimaryColor(wallpaperColors));
+            updateTheme(supportsDarkText(wallpaperColors));
         }
 
         if (mShortcutViewConfig.isEnabled()) {
@@ -696,7 +696,11 @@
     @Override
     protected void onStop() {
         super.onStop();
-        mColorExtractor.removeOnColorsChangedListener(this);
+
+        WallpaperManager wallpaperManager = getWallpaperManager();
+        if (wallpaperManager.isWallpaperSupported()) {
+            wallpaperManager.removeOnColorsChangedListener(this);
+        }
     }
 
     /**
@@ -937,12 +941,10 @@
     }
 
     @Override
-    public void onColorsChanged(ColorExtractor extractor, int which) {
+    public void onColorsChanged(WallpaperColors colors, int which) {
         if ((which & WallpaperManager.FLAG_LOCK) != 0) {
-            GradientColors colors = extractor.getColors(WallpaperManager.FLAG_LOCK,
-                    ColorExtractor.TYPE_EXTRA_DARK);
-            mBackgroundDrawable.setColor(colors.getMainColor(), true /* animated */);
-            updateTheme(colors.supportsDarkText());
+            mBackgroundDrawable.setColor(getPrimaryColor(colors));
+            updateTheme(supportsDarkText(colors));
         }
     }
 
@@ -1236,4 +1238,28 @@
                 return "Unknown-" + callSource;
         }
     }
+
+    private WallpaperManager getWallpaperManager() {
+        return getSystemService(WallpaperManager.class);
+    }
+
+    private static boolean supportsDarkText(WallpaperColors colors) {
+        if (colors != null) {
+            return (colors.getColorHints() & WallpaperColors.HINT_SUPPORTS_DARK_TEXT) != 0;
+        }
+        // It's possible that wallpaper colors are null (e.g. when colors are being
+        // processed or a live wallpaper is used). In this case, fallback to same
+        // behavior as when shortcut view is enabled.
+        return false;
+    }
+
+    private static int getPrimaryColor(WallpaperColors colors) {
+        if (colors != null) {
+            return colors.getPrimaryColor().toArgb();
+        }
+        // It's possible that wallpaper colors are null (e.g. when colors are being
+        // processed or a live wallpaper is used). In this case, fallback to same
+        // behavior as when shortcut view is enabled.
+        return Color.BLACK;
+    }
 }
diff --git a/src/com/android/phone/EmergencyInfoGroup.java b/src/com/android/phone/EmergencyInfoGroup.java
index 14c24d8..5120bc8 100644
--- a/src/com/android/phone/EmergencyInfoGroup.java
+++ b/src/com/android/phone/EmergencyInfoGroup.java
@@ -210,7 +210,10 @@
     public void onClick(View view) {
         switch (view.getId()) {
             case R.id.emergency_info_view:
-                if (AccessibilityManager.getInstance(mContext).isTouchExplorationEnabled()) {
+                AccessibilityManager accessibilityMgr =
+                        (AccessibilityManager) mContext.getSystemService(
+                                Context.ACCESSIBILITY_SERVICE);
+                if (accessibilityMgr.isTouchExplorationEnabled()) {
                     if (mOnConfirmClickListener != null) {
                         mOnConfirmClickListener.onConfirmClick(this);
                     }
diff --git a/src/com/android/phone/EmergencyShortcutButton.java b/src/com/android/phone/EmergencyShortcutButton.java
index 59b3794..f77595b 100644
--- a/src/com/android/phone/EmergencyShortcutButton.java
+++ b/src/com/android/phone/EmergencyShortcutButton.java
@@ -195,7 +195,10 @@
     public void onClick(View view) {
         switch (view.getId()) {
             case R.id.emergency_call_number_info_view:
-                if (AccessibilityManager.getInstance(mContext).isTouchExplorationEnabled()) {
+                AccessibilityManager accessibilityMgr =
+                        (AccessibilityManager) mContext.getSystemService(
+                                Context.ACCESSIBILITY_SERVICE);
+                if (accessibilityMgr.isTouchExplorationEnabled()) {
                     // TalkBack itself includes a prompt to confirm click action implicitly,
                     // so we don't need an additional confirmation with second tap on button.
                     if (mOnConfirmClickListener != null) {
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index f216d08..a2cbaf8 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -18,6 +18,7 @@
 
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 
+import static com.android.internal.telephony.PhoneConstants.PHONE_TYPE_IMS;
 import static com.android.internal.telephony.PhoneConstants.SUBSCRIPTION_KEY;
 
 import android.Manifest.permission;
@@ -150,7 +151,10 @@
 import com.android.internal.telephony.emergency.EmergencyNumberTracker;
 import com.android.internal.telephony.euicc.EuiccConnector;
 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.TelephonyMetrics;
+import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
 import com.android.internal.telephony.uicc.IccIoResult;
 import com.android.internal.telephony.uicc.IccUtils;
 import com.android.internal.telephony.uicc.SIMRecords;
@@ -159,7 +163,6 @@
 import com.android.internal.telephony.uicc.UiccController;
 import com.android.internal.telephony.uicc.UiccProfile;
 import com.android.internal.telephony.uicc.UiccSlot;
-import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
 import com.android.internal.telephony.util.VoicemailNotificationSettingsUtil;
 import com.android.internal.util.HexDump;
 import com.android.phone.settings.PickSmsSubscriptionActivity;
@@ -2765,7 +2768,7 @@
             if (phone != null) {
                 phone.setDataActivationState(activationState);
             } else {
-                loge("setVoiceActivationState fails with invalid subId: " + subId);
+                loge("setDataActivationState fails with invalid subId: " + subId);
             }
         } finally {
             Binder.restoreCallingIdentity(identity);
@@ -4897,13 +4900,13 @@
     public int getCarrierPrivilegeStatusForUid(int subId, int uid) {
         final Phone phone = getPhone(subId);
         if (phone == null) {
-            loge("getCarrierPrivilegeStatus: Invalid subId");
+            loge("getCarrierPrivilegeStatusForUid: Invalid subId");
             return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
         }
         UiccProfile profile =
                 UiccController.getInstance().getUiccProfileForPhone(phone.getPhoneId());
         if (profile == null) {
-            loge("getCarrierPrivilegeStatus: No UICC");
+            loge("getCarrierPrivilegeStatusForUid: No UICC");
             return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
         }
         return profile.getCarrierPrivilegeStatusForUid(phone.getContext().getPackageManager(), uid);
@@ -4954,7 +4957,7 @@
         }
         UiccCard card = UiccController.getInstance().getUiccCard(phoneId);
         if (card == null) {
-            loge("getCarrierPackageNamesForIntent: No UICC");
+            loge("getCarrierPackageNamesForIntentAndPhone: No UICC");
             return null ;
         }
         return card.getCarrierPackageNamesForIntent(mApp.getPackageManager(), intent);
@@ -6544,7 +6547,10 @@
                 if (card != null) {
                     cardId = card.getCardId();
                 } else {
-                    cardId = slot.getIccId();
+                    cardId = slot.getEid();
+                    if (TextUtils.isEmpty(cardId)) {
+                        cardId = slot.getIccId();
+                    }
                 }
 
                 if (cardId != null) {
@@ -7304,4 +7310,32 @@
             Binder.restoreCallingIdentity(identity);
         }
     }
+
+    /**
+     * Updates whether conference event pacakge handling is enabled.
+     * @param isCepEnabled {@code true} if CEP handling is enabled (default), or {@code false}
+     *                                 otherwise.
+     */
+    @Override
+    public void setCepEnabled(boolean isCepEnabled) {
+        TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "setCepEnabled");
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            Rlog.i(LOG_TAG, "setCepEnabled isCepEnabled=" + isCepEnabled);
+            for (Phone phone : PhoneFactory.getPhones()) {
+                Phone defaultPhone = phone.getImsPhone();
+                if (defaultPhone != null && defaultPhone.getPhoneType() == PHONE_TYPE_IMS) {
+                    ImsPhone imsPhone = (ImsPhone) defaultPhone;
+                    ImsPhoneCallTracker imsPhoneCallTracker =
+                            (ImsPhoneCallTracker) imsPhone.getCallTracker();
+                    imsPhoneCallTracker.setConferenceEventPackageEnabled(isCepEnabled);
+                    Rlog.i(LOG_TAG, "setCepEnabled isCepEnabled=" + isCepEnabled + ", for imsPhone "
+                            + imsPhone.getMsisdn());
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
 }
diff --git a/src/com/android/phone/TelephonyShellCommand.java b/src/com/android/phone/TelephonyShellCommand.java
index a59c9c4..a34abc0 100644
--- a/src/com/android/phone/TelephonyShellCommand.java
+++ b/src/com/android/phone/TelephonyShellCommand.java
@@ -53,6 +53,10 @@
     private static final String IMS_GET_CARRIER_SERVICE = "get-ims-service";
     private static final String IMS_ENABLE = "enable";
     private static final String IMS_DISABLE = "disable";
+    // Used to disable or enable processing of conference event package data from the network.
+    // This is handy for testing scenarios where CEP data does not exist on a network which does
+    // support CEP data.
+    private static final String IMS_CEP = "conference-event-package";
 
     private static final String SMS_GET_APPS = "get-apps";
     private static final String SMS_GET_DEFAULT_APP = "get-default-app";
@@ -131,6 +135,8 @@
         pw.println("  ims disable [-s SLOT_ID]");
         pw.println("    disables IMS for the SIM slot specified, or for the default voice SIM");
         pw.println("    slot if none is specified.");
+        pw.println("  ims conference-event-package [enable/disable]");
+        pw.println("    enables or disables handling or network conference event package data.");
     }
 
     private void onHelpSms() {
@@ -190,6 +196,9 @@
             case IMS_DISABLE: {
                 return handleDisableIms();
             }
+            case IMS_CEP: {
+                return handleCepChange();
+            }
         }
 
         return -1;
@@ -466,6 +475,22 @@
         return 0;
     }
 
+    private int handleCepChange() {
+        Log.i(LOG_TAG, "handleCepChange");
+        String opt = getNextArg();
+        if (opt == null) {
+            return -1;
+        }
+        boolean isCepEnabled = opt.equals("enable");
+
+        try {
+            mInterface.setCepEnabled(isCepEnabled);
+        } catch (RemoteException e) {
+            return -1;
+        }
+        return 0;
+    }
+
     private int getDefaultSlot() {
         int slotId = SubscriptionManager.getDefaultVoicePhoneId();
         if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
diff --git a/src/com/android/phone/euicc/EuiccResolutionUiDispatcherActivity.java b/src/com/android/phone/euicc/EuiccResolutionUiDispatcherActivity.java
index 0f083c9..fd741a0 100644
--- a/src/com/android/phone/euicc/EuiccResolutionUiDispatcherActivity.java
+++ b/src/com/android/phone/euicc/EuiccResolutionUiDispatcherActivity.java
@@ -20,6 +20,7 @@
 import android.content.Intent;
 import android.service.euicc.EuiccService;
 import android.telephony.euicc.EuiccManager;
+import android.util.ArraySet;
 import android.util.Log;
 
 /**
@@ -33,6 +34,14 @@
 public class EuiccResolutionUiDispatcherActivity extends EuiccUiDispatcherActivity {
     private static final String TAG = "EuiccResUiDispatcher";
 
+    /** List of all valid resolution actions for validation purposes. */
+    private static final ArraySet<String> RESOLUTION_ACTIONS = new ArraySet<>();
+    static {
+        RESOLUTION_ACTIONS.add(EuiccService.ACTION_RESOLVE_DEACTIVATE_SIM);
+        RESOLUTION_ACTIONS.add(EuiccService.ACTION_RESOLVE_NO_PRIVILEGES);
+        RESOLUTION_ACTIONS.add(EuiccService.ACTION_RESOLVE_RESOLVABLE_ERRORS);
+    }
+
     @Override
     @Nullable
     protected Intent getEuiccUiIntent() {
@@ -45,7 +54,7 @@
         String euiccUiAction =
                 getIntent().getStringExtra(
                         EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_ACTION);
-        if (!EuiccService.RESOLUTION_ACTIONS.contains(euiccUiAction)) {
+        if (!RESOLUTION_ACTIONS.contains(euiccUiAction)) {
             Log.w(TAG, "Unknown resolution action: " + euiccUiAction);
             return null;
         }
diff --git a/src/com/android/services/telephony/DisconnectCauseUtil.java b/src/com/android/services/telephony/DisconnectCauseUtil.java
index cf3f913..4a5fb4a 100644
--- a/src/com/android/services/telephony/DisconnectCauseUtil.java
+++ b/src/com/android/services/telephony/DisconnectCauseUtil.java
@@ -18,10 +18,14 @@
 
 import android.content.Context;
 import android.media.ToneGenerator;
+import android.os.PersistableBundle;
 import android.telecom.DisconnectCause;
+import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionManager;
 
 import com.android.internal.telephony.CallFailCause;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneFactory;
 import com.android.phone.ImsUtil;
 import com.android.phone.PhoneGlobals;
 import com.android.phone.common.R;
@@ -102,7 +106,7 @@
                         telephonyPerciseDisconnectCause),
                 toTelecomDisconnectCauseDescription(context, telephonyDisconnectCause, phoneId),
                 toTelecomDisconnectReason(context,telephonyDisconnectCause, reason, phoneId),
-                toTelecomDisconnectCauseTone(telephonyDisconnectCause));
+                toTelecomDisconnectCauseTone(telephonyDisconnectCause, phoneId));
     }
 
     /**
@@ -166,6 +170,8 @@
             case android.telephony.DisconnectCause.POWER_OFF:
             case android.telephony.DisconnectCause.LOW_BATTERY:
             case android.telephony.DisconnectCause.DIAL_LOW_BATTERY:
+            case android.telephony.DisconnectCause.EMERGENCY_CALL_OVER_WFC_NOT_AVAILABLE:
+            case android.telephony.DisconnectCause.WFC_SERVICE_NOT_AVAILABLE_IN_THIS_LOCATION:
             case android.telephony.DisconnectCause.SERVER_ERROR:
             case android.telephony.DisconnectCause.SERVER_UNREACHABLE:
             case android.telephony.DisconnectCause.TIMED_OUT:
@@ -357,6 +363,12 @@
             case android.telephony.DisconnectCause.OTASP_PROVISIONING_IN_PROCESS:
                 resourceId = R.string.callFailed_otasp_provisioning_in_process;
                 break;
+            case android.telephony.DisconnectCause.EMERGENCY_CALL_OVER_WFC_NOT_AVAILABLE:
+                resourceId = R.string.callFailed_emergency_call_over_wfc_not_available;
+                break;
+            case android.telephony.DisconnectCause.WFC_SERVICE_NOT_AVAILABLE_IN_THIS_LOCATION:
+                resourceId = R.string.callFailed_wfc_service_not_available_in_this_location;
+                break;
             default:
                 break;
         }
@@ -744,6 +756,12 @@
             case android.telephony.DisconnectCause.OTASP_PROVISIONING_IN_PROCESS:
                 resourceId = R.string.callFailed_otasp_provisioning_in_process;
                 break;
+            case android.telephony.DisconnectCause.EMERGENCY_CALL_OVER_WFC_NOT_AVAILABLE:
+                resourceId = R.string.callFailed_emergency_call_over_wfc_not_available;
+                break;
+            case android.telephony.DisconnectCause.WFC_SERVICE_NOT_AVAILABLE_IN_THIS_LOCATION:
+                resourceId = R.string.callFailed_wfc_service_not_available_in_this_location;
+                break;
             default:
                 break;
         }
@@ -793,11 +811,22 @@
     /**
      * Returns the tone to play for the disconnect cause, or UNKNOWN if none should be played.
      */
-    private static int toTelecomDisconnectCauseTone(int telephonyDisconnectCause) {
-        switch (telephonyDisconnectCause) {
-            case android.telephony.DisconnectCause.BUSY:
+    private static int toTelecomDisconnectCauseTone(int telephonyDisconnectCause, int phoneId) {
+        Phone phone = PhoneFactory.getPhone(phoneId);
+        PersistableBundle config;
+        if (phone != null) {
+            config = PhoneGlobals.getInstance().getCarrierConfigForSubId(phone.getSubId());
+        } else {
+            config = PhoneGlobals.getInstance().getCarrierConfig();
+        }
+        int[] busyToneArray = config.getIntArray(
+                CarrierConfigManager.KEY_DISCONNECT_CAUSE_PLAY_BUSYTONE_INT_ARRAY);
+        for (int busyTone : busyToneArray) {
+            if (busyTone == telephonyDisconnectCause) {
                 return ToneGenerator.TONE_SUP_BUSY;
-
+            }
+        }
+        switch (telephonyDisconnectCause) {
             case android.telephony.DisconnectCause.CONGESTION:
                 return ToneGenerator.TONE_SUP_CONGESTION;
 
diff --git a/src/com/android/services/telephony/ImsConference.java b/src/com/android/services/telephony/ImsConference.java
index 4da92e2..5617334 100644
--- a/src/com/android/services/telephony/ImsConference.java
+++ b/src/com/android/services/telephony/ImsConference.java
@@ -110,6 +110,25 @@
                handleOriginalConnectionChange();
             }
         }
+
+        /**
+         * Handles changes to conference participant data as reported by the conference host
+         * connection.
+         *
+         * @param c The connection.
+         * @param participants The participant information.
+         */
+        @Override
+        public void onConferenceParticipantsChanged(android.telecom.Connection c,
+                List<ConferenceParticipant> participants) {
+
+            if (c == null || participants == null) {
+                return;
+            }
+            Log.v(this, "onConferenceParticipantsChanged: %d participants", participants.size());
+            TelephonyConnection telephonyConnection = (TelephonyConnection) c;
+            handleConferenceParticipantsUpdate(telephonyConnection, participants);
+        }
     };
 
     /**
@@ -140,25 +159,6 @@
             setDisconnected(disconnectCause);
         }
 
-        /**
-         * Handles changes to conference participant data as reported by the conference host
-         * connection.
-         *
-         * @param c The connection.
-         * @param participants The participant information.
-         */
-        @Override
-        public void onConferenceParticipantsChanged(android.telecom.Connection c,
-                List<ConferenceParticipant> participants) {
-
-            if (c == null || participants == null) {
-                return;
-            }
-            Log.v(this, "onConferenceParticipantsChanged: %d participants", participants.size());
-            TelephonyConnection telephonyConnection = (TelephonyConnection) c;
-            handleConferenceParticipantsUpdate(telephonyConnection, participants);
-        }
-
         @Override
         public void onVideoStateChanged(android.telecom.Connection c, int videoState) {
             Log.d(this, "onVideoStateChanged video state %d", videoState);
diff --git a/src/com/android/services/telephony/ImsConferenceController.java b/src/com/android/services/telephony/ImsConferenceController.java
index 9902700..b193c7f 100644
--- a/src/com/android/services/telephony/ImsConferenceController.java
+++ b/src/com/android/services/telephony/ImsConferenceController.java
@@ -53,6 +53,21 @@
         }
     };
 
+    private final TelephonyConnection.TelephonyConnectionListener mTelephonyConnectionListener =
+            new TelephonyConnection.TelephonyConnectionListener() {
+        @Override
+        public void onConferenceStarted() {
+            Log.v(this, "onConferenceStarted");
+            recalculate();
+        }
+
+        @Override
+        public void onConferenceSupportedChanged(Connection c, boolean isConferenceSupported) {
+            Log.v(this, "onConferenceSupportedChanged");
+            recalculate();
+        }
+    };
+
     /**
      * Ims conference controller connection listener.  Used to respond to changes in state of the
      * Telephony connections the controller is aware of.
@@ -74,18 +89,6 @@
         public void onDestroyed(Connection connection) {
             remove(connection);
         }
-
-        @Override
-        public void onConferenceStarted() {
-            Log.v(this, "onConferenceStarted");
-            recalculate();
-        }
-
-        @Override
-        public void onConferenceSupportedChanged(Connection c, boolean isConferenceSupported) {
-            Log.v(this, "onConferenceSupportedChanged");
-            recalculate();
-        }
     };
 
     /**
@@ -149,6 +152,7 @@
 
         mTelephonyConnections.add(connection);
         connection.addConnectionListener(mConnectionListener);
+        connection.addTelephonyConnectionListener(mTelephonyConnectionListener);
         recalculateConference();
     }
 
@@ -176,6 +180,10 @@
         }
 
         connection.removeConnectionListener(mConnectionListener);
+        if (connection instanceof TelephonyConnection) {
+            TelephonyConnection telephonyConnection = (TelephonyConnection) connection;
+            telephonyConnection.removeTelephonyConnectionListener(mTelephonyConnectionListener);
+        }
         mTelephonyConnections.remove(connection);
         recalculateConferenceable();
     }
@@ -388,6 +396,7 @@
         // Use the "Other" disconnect cause to ensure the call is logged to the call log but the
         // disconnect tone is not played.
         connection.removeConnectionListener(mConnectionListener);
+        connection.removeTelephonyConnectionListener(mTelephonyConnectionListener);
         connection.clearOriginalConnection();
         connection.setDisconnected(new DisconnectCause(DisconnectCause.OTHER,
                 android.telephony.DisconnectCause.toString(
diff --git a/src/com/android/services/telephony/PstnIncomingCallNotifier.java b/src/com/android/services/telephony/PstnIncomingCallNotifier.java
index 223616f..a2ced9e 100644
--- a/src/com/android/services/telephony/PstnIncomingCallNotifier.java
+++ b/src/com/android/services/telephony/PstnIncomingCallNotifier.java
@@ -54,6 +54,14 @@
     private static final int EVENT_CDMA_CALL_WAITING = 101;
     private static final int EVENT_UNKNOWN_CONNECTION = 102;
 
+    /**
+     * The max amount of time to wait before hanging up a call that was for number verification.
+     *
+     * The delay is so that the remote end has time to hang up the call after receiving the
+     * verification signal so that the call doesn't go to voicemail.
+     */
+    private static final int MAX_NUMBER_VERIFICATION_HANGUP_DELAY_MILLIS = 10000;
+
     /** The phone object to listen to. */
     private final Phone mPhone;
 
@@ -131,12 +139,16 @@
             if (connection.getAddress() != null) {
                 if (NumberVerificationManager.getInstance()
                         .checkIncomingCall(connection.getAddress())) {
-                    // Disconnect the call if it matches
-                    try {
-                        connection.hangup();
-                    } catch (CallStateException e) {
-                        Log.e(this, e, "Error hanging up potential number verification call");
-                    }
+                    // Disconnect the call if it matches, after a delay
+                    mHandler.postDelayed(() -> {
+                        try {
+                            connection.hangup();
+                        } catch (CallStateException e) {
+                            Log.i(this, "Remote end hung up call verification call");
+                        }
+                        // TODO: use an app-supplied delay (needs new API), not to exceed the
+                        // existing max.
+                    }, MAX_NUMBER_VERIFICATION_HANGUP_DELAY_MILLIS);
                     return;
                 }
             }
diff --git a/src/com/android/services/telephony/RadioOnHelper.java b/src/com/android/services/telephony/RadioOnHelper.java
index 288c72c..85f94ab 100644
--- a/src/com/android/services/telephony/RadioOnHelper.java
+++ b/src/com/android/services/telephony/RadioOnHelper.java
@@ -53,7 +53,7 @@
             return;
         }
         mListeners = new ArrayList<>(2);
-        for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
+        for (int i = 0; i < TelephonyManager.getDefault().getMaxPhoneCount(); i++) {
             mListeners.add(new RadioOnStateListener());
         }
     }
@@ -76,7 +76,7 @@
         mCallback = callback;
         mInProgressListeners.clear();
         mIsRadioOnCallingEnabled = false;
-        for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
+        for (int i = 0; i < TelephonyManager.getDefault().getMaxPhoneCount(); i++) {
             Phone phone = PhoneFactory.getPhone(i);
             if (phone == null) {
                 continue;
diff --git a/src/com/android/services/telephony/TelecomAccountRegistry.java b/src/com/android/services/telephony/TelecomAccountRegistry.java
index 6bbcdc4..1e681e8 100644
--- a/src/com/android/services/telephony/TelecomAccountRegistry.java
+++ b/src/com/android/services/telephony/TelecomAccountRegistry.java
@@ -820,6 +820,15 @@
         }
     };
 
+    private BroadcastReceiver mLocaleChangeReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            Log.i(this, "Locale change; re-registering phone accounts.");
+            tearDownAccounts();
+            setupAccounts();
+        }
+    };
+
     private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
         @Override
         public void onServiceStateChanged(ServiceState serviceState) {
@@ -1083,6 +1092,11 @@
         filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
         mContext.registerReceiver(mReceiver, filter);
 
+        //We also need to listen for locale changes
+        //(e.g. system language changed -> SIM card name changed)
+        mContext.registerReceiver(mLocaleChangeReceiver,
+                new IntentFilter(Intent.ACTION_LOCALE_CHANGED));
+
         // Listen to the RTT system setting so that we update it when the user flips it.
         ContentObserver rttUiSettingObserver = new ContentObserver(
                 new Handler(Looper.getMainLooper())) {
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index 414e4d2..1601f00 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -26,8 +26,10 @@
 import android.os.Message;
 import android.os.PersistableBundle;
 import android.telecom.CallAudioState;
+import android.telecom.Conference;
 import android.telecom.ConferenceParticipant;
 import android.telecom.Connection;
+import android.telecom.ConnectionService;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
 import android.telecom.StatusHints;
@@ -406,6 +408,10 @@
     public abstract static class TelephonyConnectionListener {
         public void onOriginalConnectionConfigured(TelephonyConnection c) {}
         public void onOriginalConnectionRetry(TelephonyConnection c, boolean isPermanentFailure) {}
+        public void onConferenceParticipantsChanged(Connection c,
+                List<ConferenceParticipant> participants) {}
+        public void onConferenceStarted() {}
+        public void onConferenceSupportedChanged(Connection c, boolean isConferenceSupported) {}
     }
 
     private final PostDialListener mPostDialListener = new PostDialListener() {
@@ -623,6 +629,7 @@
         }
     };
 
+    private TelephonyConnectionService mTelephonyConnectionService;
     protected com.android.internal.telephony.Connection mOriginalConnection;
     private Call.State mConnectionState = Call.State.IDLE;
     private Bundle mOriginalConnectionExtras = new Bundle();
@@ -1159,7 +1166,8 @@
                && isShowingOriginalDialString()) {
             Log.i(this, "new original dial string is null, convert to: "
                    +  mOriginalConnection.getOrigDialString());
-            originalConnection.setConverted(mOriginalConnection.getOrigDialString());
+            originalConnection.restoreDialedNumberAfterConversion(
+                    mOriginalConnection.getOrigDialString());
         }
 
         clearOriginalConnection();
@@ -1264,13 +1272,23 @@
      */
     private void setTechnologyTypeExtra() {
         if (getPhone() != null) {
-            putExtra(TelecomManager.EXTRA_CALL_TECHNOLOGY_TYPE, getPhone().getPhoneType());
+            Bundle newExtras = getExtras();
+            if (newExtras == null) {
+                newExtras = new Bundle();
+            }
+            newExtras.putInt(TelecomManager.EXTRA_CALL_TECHNOLOGY_TYPE, getPhone().getPhoneType());
+            putExtras(newExtras);
         }
     }
 
     private void refreshDisableAddCall() {
         if (shouldSetDisableAddCallExtra()) {
-            putExtra(Connection.EXTRA_DISABLE_ADD_CALL, true);
+            Bundle newExtras = getExtras();
+            if (newExtras == null) {
+                newExtras = new Bundle();
+            }
+            newExtras.putBoolean(Connection.EXTRA_DISABLE_ADD_CALL, true);
+            putExtras(newExtras);
         } else {
             removeExtras(Connection.EXTRA_DISABLE_ADD_CALL);
         }
@@ -1758,8 +1776,8 @@
         // To "optimize", we check here to see if there already exists any active calls.  If so,
         // we issue an update for those calls first to make sure we only have one top-level
         // active call.
-        if (getConnectionService() != null) {
-            for (Connection current : getConnectionService().getAllConnections()) {
+        if (getTelephonyConnectionService() != null) {
+            for (Connection current : getTelephonyConnectionService().getAllConnections()) {
                 if (current != this && current instanceof TelephonyConnection) {
                     TelephonyConnection other = (TelephonyConnection) current;
                     if (other.getState() == STATE_ACTIVE) {
@@ -1786,9 +1804,10 @@
      * @return {@code true} if the connection is video capable, {@code false} otherwise.
      */
     private boolean isVideoCapable() {
-        return can(mOriginalConnectionCapabilities, Capability.SUPPORTS_VT_LOCAL_BIDIRECTIONAL)
-                && can(mOriginalConnectionCapabilities,
-                Capability.SUPPORTS_VT_REMOTE_BIDIRECTIONAL);
+        return (mOriginalConnectionCapabilities & Capability.SUPPORTS_VT_LOCAL_BIDIRECTIONAL)
+                == Capability.SUPPORTS_VT_LOCAL_BIDIRECTIONAL
+                && (mOriginalConnectionCapabilities & Capability.SUPPORTS_VT_REMOTE_BIDIRECTIONAL)
+                == Capability.SUPPORTS_VT_REMOTE_BIDIRECTIONAL;
     }
 
     /**
@@ -1800,7 +1819,8 @@
      * @return {@code true} if the connection is external, {@code false} otherwise.
      */
     private boolean isExternalConnection() {
-        return can(mOriginalConnectionCapabilities, Capability.IS_EXTERNAL_CONNECTION);
+        return (mOriginalConnectionCapabilities
+                & Capability.IS_EXTERNAL_CONNECTION) == Capability.IS_EXTERNAL_CONNECTION;
     }
 
     /**
@@ -1822,8 +1842,10 @@
      * @return {@code true} if the connection is pullable, {@code false} otherwise.
      */
     private boolean isPullable() {
-        return can(mOriginalConnectionCapabilities, Capability.IS_EXTERNAL_CONNECTION)
-                && can(mOriginalConnectionCapabilities, Capability.IS_PULLABLE);
+        return (mOriginalConnectionCapabilities & Capability.IS_EXTERNAL_CONNECTION)
+                == Capability.IS_EXTERNAL_CONNECTION
+                && (mOriginalConnectionCapabilities & Capability.IS_PULLABLE)
+                == Capability.IS_PULLABLE;
     }
 
     /**
@@ -1881,17 +1903,20 @@
     public int applyOriginalConnectionCapabilities(int capabilities) {
         // We only support downgrading to audio if both the remote and local side support
         // downgrading to audio.
-        boolean supportsDowngradeToAudio = can(mOriginalConnectionCapabilities,
-                Capability.SUPPORTS_DOWNGRADE_TO_VOICE_LOCAL |
-                        Capability.SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE);
+        int supportsDowngrade = Capability.SUPPORTS_DOWNGRADE_TO_VOICE_LOCAL
+                | Capability.SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE;
+        boolean supportsDowngradeToAudio =
+                (mOriginalConnectionCapabilities & supportsDowngrade) == supportsDowngrade;
         capabilities = changeBitmask(capabilities,
                 CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO, !supportsDowngradeToAudio);
 
         capabilities = changeBitmask(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL,
-                can(mOriginalConnectionCapabilities, Capability.SUPPORTS_VT_REMOTE_BIDIRECTIONAL));
+                (mOriginalConnectionCapabilities & Capability.SUPPORTS_VT_REMOTE_BIDIRECTIONAL)
+                        == Capability.SUPPORTS_VT_REMOTE_BIDIRECTIONAL);
 
-        boolean isLocalVideoSupported = can(mOriginalConnectionCapabilities,
-                Capability.SUPPORTS_VT_LOCAL_BIDIRECTIONAL) && !mIsTtyEnabled;
+        boolean isLocalVideoSupported = (mOriginalConnectionCapabilities
+                & Capability.SUPPORTS_VT_LOCAL_BIDIRECTIONAL)
+                == Capability.SUPPORTS_VT_LOCAL_BIDIRECTIONAL && !mIsTtyEnabled;
         capabilities = changeBitmask(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL,
                 isLocalVideoSupported);
 
@@ -2342,4 +2367,47 @@
         sb.append("]");
         return sb.toString();
     }
+
+    public final void setTelephonyConnectionService(TelephonyConnectionService connectionService) {
+        mTelephonyConnectionService = connectionService;
+    }
+
+    public final TelephonyConnectionService getTelephonyConnectionService() {
+        return mTelephonyConnectionService;
+    }
+
+    /**
+     * Notifies listeners of a change to conference participant(s).
+     *
+     * @param conferenceParticipants The participants.
+     */
+    protected final void updateConferenceParticipants(
+            List<ConferenceParticipant> conferenceParticipants) {
+        for (TelephonyConnectionListener l : mTelephonyListeners) {
+            l.onConferenceParticipantsChanged(this, conferenceParticipants);
+        }
+    }
+
+    /**
+     * Called by a {@link ConnectionService} to notify Telecom that a {@link Conference#onMerge()}
+     * operation has started.
+     * <p>
+     */
+    protected void notifyConferenceStarted() {
+        for (TelephonyConnectionListener l : mTelephonyListeners) {
+            l.onConferenceStarted();
+        }
+    }
+
+    /**
+     * Notifies listeners when a change has occurred to the Connection which impacts its ability to
+     * be a part of a conference call.
+     * @param isConferenceSupported {@code true} if the connection supports being part of a
+     *      conference call, {@code false} otherwise.
+     */
+    protected void notifyConferenceSupportedChanged(boolean isConferenceSupported) {
+        for (TelephonyConnectionListener l : mTelephonyListeners) {
+            l.onConferenceSupportedChanged(this, isConferenceSupported);
+        }
+    }
 }
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 0e5a612..5e3a899 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -1344,6 +1344,7 @@
             returnConnection.setShowPreciseFailedCause(
                     TelecomAccountRegistry.getInstance(this).isShowPreciseFailedCause(
                             phoneAccountHandle));
+            returnConnection.setTelephonyConnectionService(this);
         }
         return returnConnection;
     }
diff --git a/tests/src/com/android/phone/CallFeaturesSettingTest.java b/tests/src/com/android/phone/CallFeaturesSettingTest.java
index 78d68e3..15d48ba 100644
--- a/tests/src/com/android/phone/CallFeaturesSettingTest.java
+++ b/tests/src/com/android/phone/CallFeaturesSettingTest.java
@@ -21,8 +21,12 @@
 import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
 import static androidx.test.espresso.matcher.ViewMatchers.withText;
 
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.when;
 
+import android.content.Context;
+
+import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.FlakyTest;
 import androidx.test.rule.ActivityTestRule;
 
@@ -52,6 +56,8 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mActivity = mRule.getActivity();
+        Context targetContext = InstrumentationRegistry.getTargetContext();
+        doReturn(targetContext).when(mMockPhone).getContext();
     }
 
     @FlakyTest
diff --git a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
index 1329a77..ab4c067 100644
--- a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
+++ b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
@@ -46,6 +46,7 @@
 import com.android.internal.telephony.CallStateException;
 import com.android.internal.telephony.Connection;
 import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.emergency.EmergencyNumberTracker;
 import com.android.internal.telephony.gsm.SuppServiceNotification;
 
 import org.junit.After;
@@ -72,6 +73,7 @@
     @Mock TelephonyConnectionService.TelephonyManagerProxy mTelephonyManagerProxy;
     @Mock TelephonyConnectionService.SubscriptionManagerProxy mSubscriptionManagerProxy;
     @Mock TelephonyConnectionService.PhoneFactoryProxy mPhoneFactoryProxy;
+    @Mock EmergencyNumberTracker mEmergencyNumberTracker;
 
     TelephonyConnectionService mTestConnectionService;
 
@@ -818,6 +820,8 @@
         when(phone.getServiceState()).thenReturn(testServiceState);
         when(phone.getPhoneId()).thenReturn(phoneId);
         when(phone.getDefaultPhone()).thenReturn(phone);
+        when(phone.getEmergencyNumberTracker()).thenReturn(mEmergencyNumberTracker);
+        when(mEmergencyNumberTracker.getEmergencyNumber(anyString())).thenReturn(null);
         return phone;
     }
 
diff --git a/tests/src/com/android/services/telephony/TestTelephonyConnection.java b/tests/src/com/android/services/telephony/TestTelephonyConnection.java
index b6e4bf3..f77fd30 100644
--- a/tests/src/com/android/services/telephony/TestTelephonyConnection.java
+++ b/tests/src/com/android/services/telephony/TestTelephonyConnection.java
@@ -23,6 +23,7 @@
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
@@ -31,6 +32,7 @@
 import com.android.internal.telephony.Connection;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.emergency.EmergencyNumberTracker;
 
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
@@ -56,6 +58,9 @@
     @Mock
     Resources mMockResources;
 
+    @Mock
+    EmergencyNumberTracker mEmergencyNumberTracker;
+
     private Phone mMockPhone;
     private int mNotifyPhoneAccountChangedCount = 0;
     private List<String> mLastConnectionEvents = new ArrayList<>();
@@ -80,6 +85,8 @@
         doNothing().when(mMockRadioConnection).addListener(any(Connection.Listener.class));
         doNothing().when(mMockRadioConnection).addPostDialListener(
                 any(Connection.PostDialListener.class));
+        when(mEmergencyNumberTracker.getEmergencyNumber(anyString())).thenReturn(null);
+        when(mMockPhone.getEmergencyNumberTracker()).thenReturn(mEmergencyNumberTracker);
         when(mMockPhone.getRingingCall()).thenReturn(mMockCall);
         when(mMockPhone.getContext()).thenReturn(mMockContext);
         when(mMockPhone.getCurrentSubscriberUris()).thenReturn(null);