Merge "IMS conference merge improvements." into oc-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 9e39d30..c2b9800 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -76,6 +76,7 @@
     <protected-broadcast android:name= "com.android.ims.REGISTRATION_ERROR" />
     <protected-broadcast android:name= "com.android.phone.vvm.omtp.sms.REQUEST_SENT" />
     <protected-broadcast android:name= "com.android.phone.vvm.ACTION_VISUAL_VOICEMAIL_SERVICE_EVENT" />
+    <protected-broadcast android:name= "com.android.internal.telephony.CARRIER_VVM_PACKAGE_INSTALLED" />
 
     <uses-permission android:name="android.permission.BROADCAST_STICKY" />
     <uses-permission android:name="android.permission.CALL_PHONE" />
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index 6a0299f..cbd7a05 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu/strings.xml
@@ -154,7 +154,7 @@
     <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Itxaron, mesedez."</string>
     <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Laburregia da PIN kode berria."</string>
     <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Luzeegia da PIN kode berria."</string>
-    <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Ahulegia da PIN kode berria. Pasahitza segurua izan dadin, ez du izan behar zenbaki-segidarik edo errepikatutako zenbakirik."</string>
+    <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Ez da batere segurua PIN kode berria. Pasahitza segurua izan dadin, ez du izan behar zenbaki-segidarik edo errepikatutako zenbakirik."</string>
     <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"PIN kode zaharra ez dator bat."</string>
     <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Balio ez duten karaktereak ditu PIN kode berriak."</string>
     <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Ezin da aldatu PIN kodea"</string>
diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml
index ab913b4..363be54 100644
--- a/res/values-km/strings.xml
+++ b/res/values-km/strings.xml
@@ -527,7 +527,7 @@
     <string name="phone_entered_ecm_text" msgid="6266424252578731203">"បាន​បញ្ចូល​របៀប​ការ​ហៅ​ទៅ​វិញ​ពេល​មាន​អាសន្ន"</string>
     <string name="phone_in_ecm_notification_title" msgid="3226896828951687085">"របៀប​ហៅ​ទៅ​វិញ​ពេល​មាន​អាសន្ន"</string>
     <string name="phone_in_ecm_call_notification_text" msgid="4611608947314729773">"បាន​បិទ​ការ​តភ្ជាប់​ទិន្នន័យ"</string>
-    <string name="phone_in_ecm_notification_complete_time" msgid="7730376844178948351">"មិន​មាន​ការតភ្ជាប់​ទិន្នន័យ រហូតដល់ <xliff:g id="COMPLETETIME">%s</xliff:g>"</string>
+    <string name="phone_in_ecm_notification_complete_time" msgid="7730376844178948351">"មិន​មាន​ការតភ្ជាប់​ទិន្នន័យ រហូតដល់ម៉ោង <xliff:g id="COMPLETETIME">%s</xliff:g>"</string>
     <plurals name="alert_dialog_exit_ecm" formatted="false" msgid="7179911675595441201">
       <item quantity="other">ទូរស័ព្ទនេះនឹងស្ថិតក្នុងរបៀប ហៅត្រលប់ពេលអាសន្ន រយៈពេល <xliff:g id="COUNT_1">%s</xliff:g> នាទី។ ខណៈពេលស្ថិតក្នុងរបៀបនេះ មិនមានកម្មវិធីដែលប្រើការភ្ជាប់ទិន្នន័យណា អាចប្រើបានបានឡើយ។ តើអ្នកចង់ចាកចេញឥឡូវនេះទេ?</item>
       <item quantity="one">ទូរស័ព្ទនេះនឹងស្ថិតក្នុងរបៀប ហៅត្រលប់ពេលអាសន្ន រយៈពេល <xliff:g id="COUNT_0">%s</xliff:g> នាទី។ ខណៈពេលស្ថិតក្នុងរបៀបនេះ មិនមានកម្មវិធីដែលប្រើការភ្ជាប់ទិន្នន័យណា អាចប្រើបានបានឡើយ។ តើអ្នកចង់ចាកចេញឥឡូវនេះទេ?</item>
diff --git a/res/values-mcc262-mnc01/strings.xml b/res/values-mcc262-mnc01/strings.xml
index 85c4333..0765a73 100644
--- a/res/values-mcc262-mnc01/strings.xml
+++ b/res/values-mcc262-mnc01/strings.xml
@@ -17,7 +17,7 @@
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <!-- Status hint label for an incoming call over a wifi network which has not been accepted yet.
          DO NOT TRANSLATE. -->
-    <string name="status_hint_label_incoming_wifi_call">WLAN call from</string>
+    <string name="status_hint_label_incoming_wifi_call">WLAN Call from</string>
     <!-- Status hint label for a call being made over a wifi network. DO NOT TRANSLATE. -->
-    <string name="status_hint_label_wifi_call">WLAN call</string>
+    <string name="status_hint_label_wifi_call">WLAN Call</string>
 </resources>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 76c81b1..d42144e 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -529,12 +529,12 @@
     <string name="phone_in_ecm_call_notification_text" msgid="4611608947314729773">"Ligação de dados desativada"</string>
     <string name="phone_in_ecm_notification_complete_time" msgid="7730376844178948351">"Sem ligação de dados até à(s) <xliff:g id="COMPLETETIME">%s</xliff:g>"</string>
     <plurals name="alert_dialog_exit_ecm" formatted="false" msgid="7179911675595441201">
+      <item quantity="one">The phone will be in Emergency Callback mode for <xliff:g id="COUNT_1">%s</xliff:g> minutes. While in this mode no applications using a data connection can be used. Do you want to exit now?</item>
       <item quantity="other">O telemóvel fica no modo de Chamada de emergência durante <xliff:g id="COUNT_1">%s</xliff:g> minutos. Neste modo, não é possível utilizar aplicações com uma ligação de dados. Pretende sair agora?</item>
-      <item quantity="one">O telemóvel fica no modo de Chamada de emergência durante <xliff:g id="COUNT_0">%s</xliff:g> minuto. Neste modo, não é possível utilizar aplicações com uma ligação de dados. Pretende sair agora?</item>
     </plurals>
     <plurals name="alert_dialog_not_avaialble_in_ecm" formatted="false" msgid="8042973425225093895">
+      <item quantity="one">The selected action isn\'t available while in the Emergency Callback mode. The phone will be in this mode for <xliff:g id="COUNT_1">%s</xliff:g> minutes. Do you want to exit now?</item>
       <item quantity="other">A ação selecionada não está disponível no modo de Chamada de emergência. O telemóvel fica neste modo durante <xliff:g id="COUNT_1">%s</xliff:g> minutos. Pretende sair agora?</item>
-      <item quantity="one">A ação selecionada não está disponível no modo de Chamada de emergência. O telemóvel fica neste modo durante <xliff:g id="COUNT_0">%s</xliff:g> minuto. Pretende sair agora?</item>
     </plurals>
     <string name="alert_dialog_in_ecm_call" msgid="1886723687211887104">"A ação selecionada não está disponível durante uma chamada de emergência."</string>
     <string name="progress_dialog_exiting_ecm" msgid="4835734101617817074">"A sair do modo de chamada de retorno de emergência"</string>
diff --git a/src/com/android/phone/MMIDialogActivity.java b/src/com/android/phone/MMIDialogActivity.java
index 1e6fa41..165118b 100644
--- a/src/com/android/phone/MMIDialogActivity.java
+++ b/src/com/android/phone/MMIDialogActivity.java
@@ -68,6 +68,7 @@
                     }
                 }
         };
+        Log.d(TAG, "onCreate; registering for mmi complete.");
         mCM.registerForMmiComplete(mHandler, PhoneGlobals.MMI_COMPLETE, null);
         showMMIDialog();
     }
@@ -91,8 +92,10 @@
         if (codes.size() > 0) {
             final MmiCode mmiCode = codes.get(0);
             final Message message = Message.obtain(mHandler, PhoneGlobals.MMI_CANCEL);
+            Log.d(TAG, "showMMIDialog: mmiCode = " + mmiCode);
             mMMIDialog = PhoneUtils.displayMMIInitiate(this, mmiCode, message, mMMIDialog);
         } else {
+            Log.d(TAG, "showMMIDialog: no pending MMIs; finishing");
             finish();
         }
     }
@@ -104,6 +107,7 @@
         // Check the code to see if the request is ready to
         // finish, this includes any MMI state that is not
         // PENDING.
+        Log.d(TAG, "onMMIComplete: mmi=" + mmiCode);
 
         // if phone is a CDMA phone display feature code completed message
         int phoneType = mPhone.getPhoneType();
@@ -111,8 +115,10 @@
             PhoneUtils.displayMMIComplete(mPhone, this, mmiCode, null, null);
         } else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
             if (mmiCode.getState() != MmiCode.State.PENDING) {
-                Log.d(TAG, "Got MMI_COMPLETE, finishing dialog activity...");
+                Log.d(TAG, "onMMIComplete: Got MMI_COMPLETE, finishing dialog activity...");
                 dismissDialogsAndFinish();
+            } else {
+                Log.d(TAG, "onMMIComplete: still pending.");
             }
         }
     }
@@ -137,7 +143,7 @@
         // the in-call screen, since we'll be visible in a
         // partially-constructed state as soon as the "MMI Started" dialog
         // gets dismissed. So let's forcibly bail out right now.
-        Log.d(TAG, "onMMICancel: finishing InCallScreen...");
+        Log.d(TAG, "onMMICancel: finishing MMI dialog...");
         dismissDialogsAndFinish();
     }
 
@@ -150,6 +156,7 @@
             mCM.unregisterForMmiComplete(mHandler);
             mHandler = null;
         }
+        Log.v(TAG, "dismissDialogsAndFinish");
         finish();
     }
 }
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index 39937eb..2ed5139 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -57,6 +57,7 @@
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.phone.common.CallLogAsync;
 import com.android.phone.settings.SettingsConstants;
+import com.android.phone.vvm.CarrierVvmPackageInstalledReceiver;
 import com.android.services.telephony.sip.SipUtil;
 
 /**
@@ -145,6 +146,8 @@
     private Activity mPUKEntryActivity;
     private ProgressDialog mPUKEntryProgressDialog;
 
+    private boolean mDataDisconnectedDueToRoaming = false;
+
     private WakeState mWakeState = WakeState.SLEEP;
 
     private PowerManager mPowerManager;
@@ -157,6 +160,9 @@
     // Broadcast receiver for various intent broadcasts (see onCreate())
     private final BroadcastReceiver mReceiver = new PhoneAppBroadcastReceiver();
 
+    private final CarrierVvmPackageInstalledReceiver mCarrierVvmPackageInstalledReceiver =
+            new CarrierVvmPackageInstalledReceiver();
+
     Handler mHandler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
@@ -333,6 +339,8 @@
             intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
             registerReceiver(mReceiver, intentFilter);
 
+            mCarrierVvmPackageInstalledReceiver.register(this);
+
             //set the default values for the preferences in the phone.
             PreferenceManager.setDefaultValues(this, R.xml.network_setting_fragment, false);
 
@@ -671,16 +679,21 @@
                 // The "data disconnected due to roaming" notification is shown
                 // if (a) you have the "data roaming" feature turned off, and
                 // (b) you just lost data connectivity because you're roaming.
-                if (PhoneConstants.DataState.DISCONNECTED.name().equals(state)
+                // (c) if we haven't shown the notification for this disconnection earlier.
+                if (!mDataDisconnectedDueToRoaming
+                        && PhoneConstants.DataState.DISCONNECTED.name().equals(state)
                         && Phone.REASON_ROAMING_ON.equals(reason)
                         && !phone.getDataRoamingEnabled()) {
                     // Notify the user that data call is disconnected due to roaming. Note that
                     // calling this multiple times will not cause multiple notifications.
                     mHandler.sendEmptyMessage(EVENT_DATA_ROAMING_DISCONNECTED);
-                } else if (PhoneConstants.DataState.CONNECTED.name().equals(state)) {
+                    mDataDisconnectedDueToRoaming = true;
+                } else if (mDataDisconnectedDueToRoaming
+                        && PhoneConstants.DataState.CONNECTED.name().equals(state)) {
                     // Cancel the notification when data is available. Note it is okay to call this
                     // even if the notification doesn't exist.
                     mHandler.sendEmptyMessage(EVENT_DATA_ROAMING_OK);
+                    mDataDisconnectedDueToRoaming = false;
                 }
             } else if ((action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) &&
                     (mPUKEntryActivity != null)) {
diff --git a/src/com/android/phone/PhoneUtils.java b/src/com/android/phone/PhoneUtils.java
index d92d349..40025c1 100644
--- a/src/com/android/phone/PhoneUtils.java
+++ b/src/com/android/phone/PhoneUtils.java
@@ -787,7 +787,7 @@
                                           MmiCode mmiCode,
                                           Message buttonCallbackMessage,
                                           Dialog previousAlert) {
-        if (DBG) log("displayMMIInitiate: " + mmiCode);
+        log("displayMMIInitiate: " + android.telecom.Log.pii(mmiCode.toString()));
         if (previousAlert != null) {
             previousAlert.dismiss();
         }
@@ -824,13 +824,13 @@
         boolean isCancelable = (mmiCode != null) && mmiCode.isCancelable();
 
         if (!isCancelable) {
-            if (DBG) log("not a USSD code, displaying status toast.");
+            log("displayMMIInitiate: not a USSD code, displaying status toast.");
             CharSequence text = context.getText(R.string.mmiStarted);
             Toast.makeText(context, text, Toast.LENGTH_SHORT)
                 .show();
             return null;
         } else {
-            if (DBG) log("running USSD code, displaying indeterminate progress.");
+            log("displayMMIInitiate: running USSD code, displaying intermediate progress.");
 
             // create the indeterminate progress dialog and display it.
             ProgressDialog pd = new ProgressDialog(context, THEME);
@@ -862,13 +862,13 @@
         int title = 0;  // title for the progress dialog, if needed.
         MmiCode.State state = mmiCode.getState();
 
-        if (DBG) log("displayMMIComplete: state=" + state);
+        log("displayMMIComplete: state=" + state);
 
         switch (state) {
             case PENDING:
                 // USSD code asking for feedback from user.
                 text = mmiCode.getMessage();
-                if (DBG) log("- using text from PENDING MMI message: '" + text + "'");
+                log("displayMMIComplete: using text from PENDING MMI message: '" + text + "'");
                 break;
             case CANCELLED:
                 text = null;
@@ -887,7 +887,7 @@
 
             case FAILED:
                 text = mmiCode.getMessage();
-                if (DBG) log("- using text from MMI message: '" + text + "'");
+                log("displayMMIComplete (failed): using text from MMI message: '" + text + "'");
                 break;
             default:
                 throw new IllegalStateException("Unexpected MmiCode state: " + state);
@@ -929,9 +929,9 @@
             // A USSD in a pending state means that it is still
             // interacting with the user.
             if (state != MmiCode.State.PENDING) {
-                if (DBG) log("MMI code has finished running.");
+                log("displayMMIComplete: MMI code has finished running.");
 
-                if (DBG) log("Extended NW displayMMIInitiate (" + text + ")");
+                log("displayMMIComplete: Extended NW displayMMIInitiate (" + text + ")");
                 if (text == null || text.length() == 0)
                     return;
 
@@ -966,7 +966,8 @@
                 sUssdDialog.setMessage(sUssdMsg.toString());
                 sUssdDialog.show();
             } else {
-                if (DBG) log("USSD code has requested user input. Constructing input dialog.");
+                log("displayMMIComplete: USSD code has requested user input. Constructing input "
+                        + "dialog.");
 
                 // USSD MMI code that is interacting with the user.  The
                 // basic set of steps is this:
diff --git a/src/com/android/phone/vvm/CarrierVvmPackageInstalledReceiver.java b/src/com/android/phone/vvm/CarrierVvmPackageInstalledReceiver.java
new file mode 100644
index 0000000..ec0d3f6
--- /dev/null
+++ b/src/com/android/phone/vvm/CarrierVvmPackageInstalledReceiver.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.phone.vvm;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.PersistableBundle;
+import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomManager;
+import android.telephony.CarrierConfigManager;
+import android.telephony.TelephonyManager;
+import android.telephony.VisualVoicemailService;
+import android.text.TextUtils;
+import android.util.ArraySet;
+
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * Receives {@link Intent#ACTION_PACKAGE_ADDED} for the system dialer to inform it a carrier visual
+ * voicemail app has been installed. ACTION_PACKAGE_ADDED requires the receiver process to be
+ * running so the system dialer cannot receive it itself.
+ *
+ * Carrier VVM apps are usually regular apps, not a
+ * {@link VisualVoicemailService} nor {@link android.service.carrier.CarrierMessagingService} so it
+ * will not take precedence over the system dialer. The system dialer should disable VVM it self
+ * to let the carrier app take over since the installation is an explicit user interaction. Carrier
+ * customer support might also ask the user to switch to their app if they believe there's any
+ * issue in the system dialer so this transition should not require more user interaction.
+ *
+ * @see CarrierConfigManager#KEY_CARRIER_VVM_PACKAGE_NAME_STRING_ARRAY
+ */
+public class CarrierVvmPackageInstalledReceiver extends BroadcastReceiver {
+
+    private static final String TAG = "VvmPkgInstalledRcvr";
+
+    /**
+     * Hidden broadcast to the system dialer
+     */
+    private static final String ACTION_CARRIER_VVM_PACKAGE_INSTALLED =
+            "com.android.internal.telephony.CARRIER_VVM_PACKAGE_INSTALLED";
+
+    public void register(Context context) {
+        IntentFilter intentFilter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
+        intentFilter.addDataScheme("package");
+        context.registerReceiver(this, intentFilter);
+    }
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        if (intent.getData() == null) {
+            return;
+        }
+        String packageName = intent.getData().getSchemeSpecificPart();
+        if (packageName == null) {
+            return;
+        }
+
+        TelecomManager telecomManager = context.getSystemService(TelecomManager.class);
+        String systemDialer = telecomManager.getSystemDialerPackage();
+        TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class);
+        for (PhoneAccountHandle phoneAccountHandle : telecomManager.getCallCapablePhoneAccounts()) {
+            TelephonyManager pinnedTelephonyManager = telephonyManager
+                    .createForPhoneAccountHandle(phoneAccountHandle);
+
+            if (pinnedTelephonyManager == null) {
+                VvmLog.e(TAG, "cannot create TelephonyManager from " + phoneAccountHandle);
+                continue;
+            }
+
+            if (!getCarrierVvmPackages(telephonyManager).contains(packageName)) {
+                continue;
+            }
+
+            VvmLog.i(TAG, "Carrier VVM app " + packageName + " installed");
+
+            String vvmPackage = pinnedTelephonyManager.getVisualVoicemailPackageName();
+            if (!TextUtils.equals(vvmPackage, systemDialer)) {
+                // Non system dialer do not need to prioritize carrier vvm app.
+                VvmLog.i(TAG, "non system dialer " + vvmPackage + " ignored");
+                continue;
+            }
+
+            VvmLog.i(TAG, "sending broadcast to " + vvmPackage);
+            Intent broadcast = new Intent(ACTION_CARRIER_VVM_PACKAGE_INSTALLED);
+            broadcast.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
+            broadcast.setPackage(vvmPackage);
+            context.sendBroadcast(broadcast);
+        }
+    }
+
+    private static Set<String> getCarrierVvmPackages(TelephonyManager pinnedTelephonyManager) {
+        Set<String> carrierPackages = new ArraySet<>();
+
+        PersistableBundle config = pinnedTelephonyManager.getCarrierConfig();
+        String singlePackage = config
+                .getString(CarrierConfigManager.KEY_CARRIER_VVM_PACKAGE_NAME_STRING);
+        if (!TextUtils.isEmpty(singlePackage)) {
+            carrierPackages.add(singlePackage);
+        }
+        String[] arrayPackages = config
+                .getStringArray(CarrierConfigManager.KEY_CARRIER_VVM_PACKAGE_NAME_STRING_ARRAY);
+        if (arrayPackages != null) {
+            Collections.addAll(carrierPackages, arrayPackages);
+        }
+
+        return carrierPackages;
+    }
+}
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index ccc5f1e..d25cebe 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -659,6 +659,21 @@
         }
     }
 
+    /**
+     * Called by the {@link ConnectionService} when a newly created {@link Connection} has been
+     * added to the {@link ConnectionService} and sent to Telecom.  Here it is safe to send
+     * connection events.
+     *
+     * @param connection the {@link Connection}.
+     */
+    @Override
+    public void onCreateConnectionComplete(Connection connection) {
+        if (connection instanceof TelephonyConnection) {
+            TelephonyConnection telephonyConnection = (TelephonyConnection) connection;
+            maybeSendInternationalCallEvent(telephonyConnection);
+        }
+    }
+
     @Override
     public void triggerConferenceRecalculate() {
         if (mTelephonyConferenceController.shouldRecalculate()) {
@@ -899,18 +914,6 @@
         try {
             if (phone != null) {
                 originalConnection = phone.dial(number, null, videoState, extras);
-
-                if (phone instanceof GsmCdmaPhone) {
-                    GsmCdmaPhone gsmCdmaPhone = (GsmCdmaPhone) phone;
-                    if (gsmCdmaPhone.isNotificationOfWfcCallRequired(number)) {
-                        // Send connection event to InCall UI to inform the user of the fact they
-                        // are potentially placing an international call on WFC.
-                        Log.i(this, "placeOutgoingConnection - sending international call on WFC " +
-                                "confirmation event");
-                        connection.sendConnectionEvent(
-                                TelephonyManager.EVENT_NOTIFY_INTERNATIONAL_CALL_ON_WFC, null);
-                    }
-                }
             }
         } catch (CallStateException e) {
             Log.e(this, e, "placeOutgoingConnection, phone.dial exception: " + e);
@@ -1246,4 +1249,20 @@
                 android.provider.Settings.Secure.PREFERRED_TTY_MODE,
                 TelecomManager.TTY_MODE_OFF) != TelecomManager.TTY_MODE_OFF);
     }
+
+    private void maybeSendInternationalCallEvent(TelephonyConnection telephonyConnection) {
+        Phone phone = telephonyConnection.getPhone().getDefaultPhone();
+        if (phone instanceof GsmCdmaPhone) {
+            GsmCdmaPhone gsmCdmaPhone = (GsmCdmaPhone) phone;
+            if (gsmCdmaPhone.isNotificationOfWfcCallRequired(
+                    telephonyConnection.getOriginalConnection().getOrigDialString())) {
+                // Send connection event to InCall UI to inform the user of the fact they
+                // are potentially placing an international call on WFC.
+                Log.i(this, "placeOutgoingConnection - sending international call on WFC " +
+                        "confirmation event");
+                telephonyConnection.sendConnectionEvent(
+                        TelephonyManager.EVENT_NOTIFY_INTERNATIONAL_CALL_ON_WFC, null);
+            }
+        }
+    }
 }