Merge "Changes to testapps for EMBMS api tweaks"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index ae4ed14..f86cdef 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -79,10 +79,10 @@
     <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" />
     <protected-broadcast android:name= "com.android.cellbroadcastreceiver.GET_LATEST_CB_AREA_INFO" />
-    <protected-broadcast android:name= "android.intent.action.CURRENT_CARRIER_IDENTITY_CHANGED" />
     <protected-broadcast android:name= "android.telephony.action.SIM_CARD_STATE_CHANGED" />
     <protected-broadcast android:name= "android.telephony.action.SIM_APPLICATION_STATE_CHANGED" />
     <protected-broadcast android:name= "android.telephony.action.SIM_SLOT_STATUS_CHANGED" />
+    <protected-broadcast android:name= "android.telephony.action.SUBSCRIPTION_CARRIER_IDENTITY_CHANGED" />
 
     <uses-permission android:name="android.permission.BROADCAST_STICKY" />
     <uses-permission android:name="android.permission.CALL_PHONE" />
@@ -181,6 +181,7 @@
     <uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" />
     <uses-permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY" />
     <uses-permission android:name="android.permission.BIND_TELEPHONY_DATA_SERVICE" />
+    <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
 
     <application android:name="PhoneApp"
             android:persistent="true"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 8c450a0..72be3b2 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1165,6 +1165,11 @@
     <string name="hac_mode_title">Hearing aids</string>
     <string name="hac_mode_summary">Turn on hearing aid compatibility</string>
 
+    <!-- RTT settings: used to turn on/off Real-Time Text, an accessibility feature similar to
+         TTY that allows users to send text over a phone call. -->
+    <string name="rtt_mode_title">RTT</string>
+    <string name="rtt_mode_summary">Turn RTT on or off</string>
+
     <!-- Service option entries.  -->
     <string-array name="tty_mode_entries">
         <item>TTY Off</item>
diff --git a/res/xml/accessibility_settings.xml b/res/xml/accessibility_settings.xml
index 2c007f6..e674e74 100644
--- a/res/xml/accessibility_settings.xml
+++ b/res/xml/accessibility_settings.xml
@@ -32,4 +32,10 @@
         android:persistent="true"
         android:summary="@string/hac_mode_summary"/>
 
+    <SwitchPreference
+        android:key="button_rtt_key"
+        android:title="@string/rtt_mode_title"
+        android:persistent="true"
+        android:summary="@string/rtt_mode_summary"/>
+
 </PreferenceScreen>
diff --git a/sip/src/com/android/services/telephony/sip/SipConnectionService.java b/sip/src/com/android/services/telephony/sip/SipConnectionService.java
index a5f48d3..27be9b4 100644
--- a/sip/src/com/android/services/telephony/sip/SipConnectionService.java
+++ b/sip/src/com/android/services/telephony/sip/SipConnectionService.java
@@ -37,6 +37,7 @@
 
 import com.android.internal.telephony.CallStateException;
 import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.PhoneInternalInterface;
 import com.android.internal.telephony.sip.SipPhone;
 import com.android.services.telephony.DisconnectCauseUtil;
 
@@ -258,7 +259,9 @@
 
         try {
             com.android.internal.telephony.Connection originalConnection =
-                    phone.dial(number, request.getVideoState());
+                    phone.dial(number, new PhoneInternalInterface.DialArgs.Builder<>()
+                            .setVideoState(request.getVideoState())
+                            .build());
             return originalConnection;
         } catch (CallStateException e) {
             log("startCallWithPhone, exception: " + e);
diff --git a/src/com/android/phone/CallFeaturesSetting.java b/src/com/android/phone/CallFeaturesSetting.java
index 5a228a8..233530e 100644
--- a/src/com/android/phone/CallFeaturesSetting.java
+++ b/src/com/android/phone/CallFeaturesSetting.java
@@ -194,7 +194,12 @@
         public void onCallStateChanged(int state, String incomingNumber) {
             if (DBG) log("PhoneStateListener onCallStateChanged: state is " + state);
             if (mEnableVideoCalling != null) {
-                mEnableVideoCalling.setEnabled(state == TelephonyManager.CALL_STATE_IDLE);
+                // Use TelephonyManager#getCallStete instead of 'state' parameter because it needs
+                // to check the current state of all phone calls.
+                TelephonyManager telephonyManager =
+                        (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
+                mEnableVideoCalling.setEnabled(
+                        telephonyManager.getCallState() == TelephonyManager.CALL_STATE_IDLE);
             }
         }
     };
diff --git a/src/com/android/phone/LocationAccessPolicy.java b/src/com/android/phone/LocationAccessPolicy.java
deleted file mode 100644
index 6f2a5ec..0000000
--- a/src/com/android/phone/LocationAccessPolicy.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * 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;
-
-import android.Manifest;
-import android.annotation.NonNull;
-import android.annotation.UserIdInt;
-import android.app.ActivityManager;
-import android.app.AppOpsManager;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.pm.UserInfo;
-import android.os.Build;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.Settings;
-
-import java.util.List;
-
-/**
- * Helper for performing location access checks.
- */
-final class LocationAccessPolicy {
-
-    private LocationAccessPolicy() {
-        /* do nothing - hide ctor */
-    }
-
-    /**
-     * API to determine if the caller has permissions to get cell location.
-     *
-     * @param pkgName Package name of the application requesting access
-     * @param uid The uid of the package
-     * @param message Message to add to the exception if no location permission
-     * @return boolean true or false if permissions is granted
-     */
-    static boolean canAccessCellLocation(@NonNull Context context, @NonNull String pkgName,
-            int uid, String message) throws SecurityException {
-        context.getSystemService(AppOpsManager.class).checkPackage(uid, pkgName);
-        // We always require the location permission and also require the
-        // location mode to be on for non-legacy apps. Legacy apps are
-        // required to be in the foreground to at least mitigate the case
-        // where a legacy app the user is not using tracks their location.
-
-        // Grating ACCESS_FINE_LOCATION to an app automatically grants it ACCESS_COARSE_LOCATION.
-        context.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION, message);
-        final int opCode = AppOpsManager.permissionToOpCode(
-                Manifest.permission.ACCESS_COARSE_LOCATION);
-        if (opCode != AppOpsManager.OP_NONE && context.getSystemService(AppOpsManager.class)
-                .noteOp(opCode, uid, pkgName) != AppOpsManager.MODE_ALLOWED) {
-            return false;
-        }
-        if (!isLocationModeEnabled(context, UserHandle.getUserId(uid))
-                && !isLegacyForeground(context, pkgName)) {
-            return false;
-        }
-        // If the user or profile is current, permission is granted.
-        // Otherwise, uid must have INTERACT_ACROSS_USERS_FULL permission.
-        return isCurrentProfile(context, uid) || checkInteractAcrossUsersFull(context);
-    }
-
-    private static boolean isLocationModeEnabled(@NonNull Context context, @UserIdInt int userId) {
-        return Settings.Secure.getIntForUser(context.getContentResolver(),
-                Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF, userId)
-                != Settings.Secure.LOCATION_MODE_OFF;
-    }
-
-    private static boolean isLegacyForeground(@NonNull Context context, @NonNull String pkgName) {
-        return isLegacyVersion(context, pkgName) && isForegroundApp(context, pkgName);
-    }
-
-    private static boolean isLegacyVersion(@NonNull Context context, @NonNull String pkgName) {
-        try {
-            if (context.getPackageManager().getApplicationInfo(pkgName, 0)
-                    .targetSdkVersion <= Build.VERSION_CODES.O) {
-                return true;
-            }
-        } catch (PackageManager.NameNotFoundException e) {
-            // In case of exception, assume known app (more strict checking)
-            // Note: This case will never happen since checkPackage is
-            // called to verify validity before checking app's version.
-        }
-        return false;
-    }
-
-    private static boolean isForegroundApp(@NonNull Context context, @NonNull String pkgName) {
-        final ActivityManager am = context.getSystemService(ActivityManager.class);
-        final List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1);
-        if (!tasks.isEmpty()) {
-            return pkgName.equals(tasks.get(0).topActivity.getPackageName());
-        }
-        return false;
-    }
-
-    private static boolean checkInteractAcrossUsersFull(@NonNull Context context) {
-        return context.checkCallingOrSelfPermission(
-                android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
-                == PackageManager.PERMISSION_GRANTED;
-    }
-
-    private static boolean isCurrentProfile(@NonNull Context context, int uid) {
-        final int currentUser = ActivityManager.getCurrentUser();
-        final int callingUserId = UserHandle.getUserId(uid);
-        if (callingUserId == currentUser) {
-            return true;
-        } else {
-            List<UserInfo> userProfiles = context.getSystemService(
-                    UserManager.class).getProfiles(currentUser);
-            for (UserInfo user: userProfiles) {
-                if (user.id == callingUserId) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-}
diff --git a/src/com/android/phone/MobileNetworkSettings.java b/src/com/android/phone/MobileNetworkSettings.java
index 96309ad..0accb56 100644
--- a/src/com/android/phone/MobileNetworkSettings.java
+++ b/src/com/android/phone/MobileNetworkSettings.java
@@ -266,8 +266,10 @@
 
         private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
             /*
-             * Enable/disable the 'Enhanced 4G LTE Mode' when in/out of a call
-             * and depending on TTY mode and TTY support over VoLTE.
+             * Enable/disable the 'Enhanced 4G LTE Mode' and 'Carrier video calling'
+             * when in/out of a call. 'Enhanced 4G LTE Mode' depends on TTY mode
+             * and TTY support over VoLTE.
+             *
              * @see android.telephony.PhoneStateListener#onCallStateChanged(int,
              * java.lang.String)
              */
@@ -283,6 +285,7 @@
                 Preference pref = getPreferenceScreen().findPreference(BUTTON_4G_LTE_KEY);
                 if (pref != null) pref.setEnabled(enabled && hasActiveSubscriptions());
 
+                updateVideoCallState();
             }
         };
 
@@ -1708,7 +1711,8 @@
                     mVideoCallingPref.setEnabled(false);
                     mVideoCallingPref.setChecked(false);
                 } else {
-                    mVideoCallingPref.setEnabled(true);
+                    mVideoCallingPref.setEnabled(
+                            mTelephonyManager.getCallState() == TelephonyManager.CALL_STATE_IDLE);
                     mVideoCallingPref.setChecked(mImsMgr.isVtEnabledByUser());
                     mVideoCallingPref.setOnPreferenceChangeListener(this);
                 }
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index f10a609..c9c50cd 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -55,6 +55,7 @@
 import android.telephony.CellInfo;
 import android.telephony.ClientRequestStats;
 import android.telephony.IccOpenLogicalChannelResponse;
+import android.telephony.LocationAccessPolicy;
 import android.telephony.ModemActivityInfo;
 import android.telephony.NeighboringCellInfo;
 import android.telephony.NetworkScanRequest;
@@ -74,6 +75,7 @@
 import android.telephony.ims.aidl.IImsMmTelFeature;
 import android.telephony.ims.aidl.IImsRcsFeature;
 import android.telephony.ims.aidl.IImsRegistration;
+import android.telephony.ims.stub.ImsRegistrationImplBase;
 import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.Log;
@@ -1652,8 +1654,10 @@
 
     @Override
     public Bundle getCellLocation(String callingPackage) {
+        mPhone.getContext().getSystemService(AppOpsManager.class)
+                .checkPackage(Binder.getCallingUid(), callingPackage);
         if (!LocationAccessPolicy.canAccessCellLocation(mPhone.getContext(),
-                callingPackage, Binder.getCallingUid(), "getCellLocation")) {
+                callingPackage, Binder.getCallingUid(),Binder.getCallingPid())) {
             return null;
         }
 
@@ -1720,8 +1724,10 @@
     @Override
     @SuppressWarnings("unchecked")
     public List<NeighboringCellInfo> getNeighboringCellInfo(String callingPackage) {
+        mPhone.getContext().getSystemService(AppOpsManager.class)
+                .checkPackage(Binder.getCallingUid(), callingPackage);
         if (!LocationAccessPolicy.canAccessCellLocation(mPhone.getContext(),
-                callingPackage, Binder.getCallingUid(), "getNeighboringCellInfo")) {
+                callingPackage, Binder.getCallingUid(), Binder.getCallingPid())) {
             return null;
         }
 
@@ -1748,8 +1754,10 @@
 
     @Override
     public List<CellInfo> getAllCellInfo(String callingPackage) {
+        mPhone.getContext().getSystemService(AppOpsManager.class)
+                .checkPackage(Binder.getCallingUid(), callingPackage);
         if (!LocationAccessPolicy.canAccessCellLocation(mPhone.getContext(),
-                callingPackage, Binder.getCallingUid(), "getAllCellInfo")) {
+                callingPackage, Binder.getCallingUid(), Binder.getCallingPid())) {
             return null;
         }
 
@@ -3265,6 +3273,14 @@
         return mPhone.getContext().getResources().getBoolean(R.bool.hac_enabled);
     }
 
+    public boolean isRttSupported() {
+        boolean isCarrierSupported =
+                mApp.getCarrierConfig().getBoolean(CarrierConfigManager.KEY_RTT_SUPPORTED_BOOL);
+        boolean isDeviceSupported =
+                mPhone.getContext().getResources().getBoolean(R.bool.config_support_rtt);
+        return isCarrierSupported && isDeviceSupported;
+    }
+
     /**
      * Returns the unique device ID of phone, for example, the IMEI for
      * GSM and the MEID for CDMA phones. Return null if device ID is not available.
@@ -3286,22 +3302,13 @@
         }
     }
 
-    /*
-     * {@hide}
-     * Returns the IMS Registration Status
-     */
-    @Override
-    public boolean isImsRegistered() {
-        return mPhone.isImsRegistered();
-    }
-
     /**
      * {@hide}
      * Returns the IMS Registration Status on a particular subid
      *
      * @param subId
      */
-    public boolean isImsRegisteredForSubscriber(int subId) {
+    public boolean isImsRegistered(int subId) {
         Phone phone = getPhone(subId);
         if (phone != null) {
             return phone.isImsRegistered();
@@ -3315,27 +3322,53 @@
         return PhoneUtils.getSubIdForPhoneAccount(phoneAccount);
     }
 
-    /*
-     * {@hide}
-     * Returns the IMS Registration Status
+    /**
+     * @return the VoWiFi calling availability.
      */
-    public boolean isWifiCallingAvailable() {
-        return mPhone.isWifiCallingEnabled();
+    public boolean isWifiCallingAvailable(int subId) {
+        Phone phone = getPhone(subId);
+        if (phone != null) {
+            return phone.isWifiCallingEnabled();
+        } else {
+            return false;
+        }
     }
 
-    /*
-     * {@hide}
-     * Returns the IMS Registration Status
+    /**
+     * @return the VoLTE availability.
      */
-    public boolean isVolteAvailable() {
-        return mPhone.isVolteEnabled();
+    public boolean isVolteAvailable(int subId) {
+        Phone phone = getPhone(subId);
+        if (phone != null) {
+            return phone.isVolteEnabled();
+        } else {
+            return false;
+        }
     }
 
-    /*
-     * {@hide} Returns the IMS Registration Status
+    /**
+     * @return the VT calling availability.
      */
-    public boolean isVideoTelephonyAvailable() {
-        return mPhone.isVideoEnabled();
+    public boolean isVideoTelephonyAvailable(int subId) {
+        Phone phone = getPhone(subId);
+        if (phone != null) {
+            return phone.isVideoEnabled();
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * @return the IMS registration technology for the MMTEL feature. Valid return values are
+     * defined in {@link ImsRegistrationImplBase}.
+     */
+    public @ImsRegistrationImplBase.ImsRegistrationTech int getImsRegTechnologyForMmTel(int subId) {
+        Phone phone = getPhone(subId);
+        if (phone != null) {
+            return phone.getImsRegistrationTech();
+        } else {
+            return ImsRegistrationImplBase.REGISTRATION_TECH_NONE;
+        }
     }
 
     private boolean canReadPhoneState(String callingPackage, String message) {
diff --git a/src/com/android/phone/settings/AccessibilitySettingsFragment.java b/src/com/android/phone/settings/AccessibilitySettingsFragment.java
index af7d4bf..7ede23a 100644
--- a/src/com/android/phone/settings/AccessibilitySettingsFragment.java
+++ b/src/com/android/phone/settings/AccessibilitySettingsFragment.java
@@ -24,8 +24,10 @@
 import android.preference.PreferenceFragment;
 import android.preference.PreferenceScreen;
 import android.provider.Settings;
+import android.telecom.TelecomManager;
 import android.telephony.CarrierConfigManager;
 import android.telephony.PhoneStateListener;
+import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.util.Log;
 
@@ -41,6 +43,7 @@
 
     private static final String BUTTON_TTY_KEY = "button_tty_mode_key";
     private static final String BUTTON_HAC_KEY = "button_hac_key";
+    private static final String BUTTON_RTT_KEY = "button_rtt_key";
 
     private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
         /**
@@ -67,6 +70,7 @@
 
     private TtyModeListPreference mButtonTty;
     private SwitchPreference mButtonHac;
+    private SwitchPreference mButtonRtt;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
@@ -80,6 +84,7 @@
         mButtonTty = (TtyModeListPreference) findPreference(
                 getResources().getString(R.string.tty_mode_key));
         mButtonHac = (SwitchPreference) findPreference(BUTTON_HAC_KEY);
+        mButtonRtt = (SwitchPreference) findPreference(BUTTON_RTT_KEY);
 
         if (PhoneGlobals.getInstance().phoneMgr.isTtyModeSupported()) {
             mButtonTty.init();
@@ -96,6 +101,19 @@
             getPreferenceScreen().removePreference(mButtonHac);
             mButtonHac = null;
         }
+
+        if (PhoneGlobals.getInstance().phoneMgr.isRttSupported()) {
+            // TODO: this is going to be a on/off switch for now. Ask UX about how to integrate
+            // this settings with TTY
+            boolean rttOn = Settings.System.getInt(
+                    mContext.getContentResolver(), Settings.System.RTT_CALLING_MODE,
+                    TelecomManager.TTY_MODE_OFF)
+                    != TelecomManager.TTY_MODE_OFF;
+            mButtonRtt.setChecked(rttOn);
+        } else {
+            getPreferenceScreen().removePreference(mButtonRtt);
+            mButtonRtt = null;
+        }
     }
 
     @Override
@@ -129,7 +147,19 @@
                     hac == SettingsConstants.HAC_ENABLED
                             ? SettingsConstants.HAC_VAL_ON : SettingsConstants.HAC_VAL_OFF);
             return true;
+        } else if (preference == mButtonRtt) {
+            Log.i(LOG_TAG, "RTT setting changed -- now " + mButtonRtt.isChecked());
+            int rttMode = mButtonRtt.isChecked()
+                    ? TelecomManager.TTY_MODE_FULL : TelecomManager.TTY_MODE_OFF;
+            Settings.System.putInt(mContext.getContentResolver(), Settings.System.RTT_CALLING_MODE,
+                    rttMode);
+            // Update RTT config with IMS Manager
+            ImsManager imsManager = ImsManager.getInstance(getContext(),
+                    SubscriptionManager.getDefaultVoicePhoneId());
+            imsManager.setRttEnabled(mButtonRtt.isChecked());
+            return true;
         }
+
         return false;
     }
 
diff --git a/src/com/android/services/telephony/TelecomAccountRegistry.java b/src/com/android/services/telephony/TelecomAccountRegistry.java
index 17c6049..3fb8d32 100644
--- a/src/com/android/services/telephony/TelecomAccountRegistry.java
+++ b/src/com/android/services/telephony/TelecomAccountRegistry.java
@@ -234,9 +234,7 @@
                 extras.putBoolean(PhoneAccount.EXTRA_PLAY_CALL_RECORDING_TONE, true);
             }
 
-            boolean isDeviceRttSupported = mContext.getResources().getBoolean(
-                    R.bool.config_support_rtt);
-            if (isDeviceRttSupported && isCarrierRttSupported()) {
+            if (PhoneGlobals.getInstance().phoneMgr.isRttSupported()) {
                 capabilities |= PhoneAccount.CAPABILITY_RTT;
             }
 
@@ -405,12 +403,6 @@
                     b.getBoolean(CarrierConfigManager.KEY_SUPPORT_VIDEO_CONFERENCE_CALL_BOOL);
         }
 
-        private boolean isCarrierRttSupported() {
-            PersistableBundle b =
-                    PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
-            return b != null && b.getBoolean(CarrierConfigManager.KEY_RTT_SUPPORTED_BOOL);
-        }
-
         /**
          * Determines from carrier config whether merging of wifi calls is allowed when VoWIFI is
          * turned off.
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index 67e9739..b27baed 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -559,6 +559,16 @@
                     DisconnectCause.toString(cause));
             mHandler.obtainMessage(MSG_DISCONNECT).sendToTarget();
         }
+
+        @Override
+        public void onRttInitiated() {
+            sendRttInitiationSuccess();
+        }
+
+        @Override
+        public void onRttTerminated() {
+            sendRttSessionRemotelyTerminated();
+        }
     };
 
     protected com.android.internal.telephony.Connection mOriginalConnection;
@@ -567,6 +577,7 @@
     private boolean mIsStateOverridden = false;
     private Call.State mOriginalConnectionState = Call.State.IDLE;
     private Call.State mConnectionOverriddenState = Call.State.IDLE;
+    private RttTextStream mRttTextStream = null;
 
     private boolean mWasImsConnection;
 
@@ -992,6 +1003,8 @@
                 mIsCdmaVoicePrivacyEnabled);
         newProperties = changeBitmask(newProperties, PROPERTY_ASSISTED_DIALING_USED,
                 mIsUsingAssistedDialing);
+        newProperties = changeBitmask(newProperties, PROPERTY_IS_RTT,
+                (getConnectionProperties() & PROPERTY_IS_RTT) != 0);
 
         if (getConnectionProperties() != newProperties) {
             setConnectionProperties(newProperties);
@@ -1811,6 +1824,14 @@
         return false;
     }
 
+    public void setRttTextStream(RttTextStream s) {
+        mRttTextStream = s;
+    }
+
+    public RttTextStream getRttTextStream() {
+        return mRttTextStream;
+    }
+
     /**
      * For video calls, sets whether this connection supports pausing the outgoing video for the
      * call using the {@link android.telecom.VideoProfile#STATE_PAUSED} VideoState.
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 8584d42..2022733 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -650,6 +650,7 @@
         connection.setAddress(handle, PhoneConstants.PRESENTATION_ALLOWED);
         connection.setInitializing();
         connection.setVideoState(request.getVideoState());
+        connection.setRttTextStream(request.getRttTextStream());
 
         return connection;
     }
@@ -988,7 +989,11 @@
         com.android.internal.telephony.Connection originalConnection = null;
         try {
             if (phone != null) {
-                originalConnection = phone.dial(number, null, videoState, extras);
+                originalConnection = phone.dial(number, new ImsPhone.ImsDialArgs.Builder()
+                        .setVideoState(videoState)
+                        .setIntentExtras(extras)
+                        .setRttTextStream(connection.getRttTextStream())
+                        .build());
             }
         } catch (CallStateException e) {
             Log.e(this, e, "placeOutgoingConnection, phone.dial exception: " + e);
diff --git a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
index b4c93ee..3bd2716 100644
--- a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
+++ b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
@@ -539,7 +539,7 @@
         // was redialed on the same slot
         assertEquals(0, c.getNotifyPhoneAccountChangedCount());
         try {
-            verify(slot0Phone).dial(anyString(), any(), anyInt(), any());
+            verify(slot0Phone).dial(anyString(), any());
         } catch (CallStateException e) {
             // This shouldn't happen
             fail();
@@ -571,7 +571,7 @@
         // was never redialed
         assertEquals(0, c.getNotifyPhoneAccountChangedCount());
         try {
-            verify(slot0Phone, never()).dial(anyString(), any(), anyInt(), any());
+            verify(slot0Phone, never()).dial(anyString(), any());
         } catch (CallStateException e) {
             // This shouldn't happen
             fail();
@@ -611,7 +611,7 @@
         // redialed on another slot
         assertEquals(1, c.getNotifyPhoneAccountChangedCount());
         try {
-            verify(slot1Phone).dial(anyString(), any(), anyInt(), any());
+            verify(slot1Phone).dial(anyString(), any());
         } catch (CallStateException e) {
             // This shouldn't happen
             fail();
@@ -649,7 +649,7 @@
         // redialed on another slot
         assertEquals(1, c.getNotifyPhoneAccountChangedCount());
         try {
-            verify(slot1Phone).dial(anyString(), any(), anyInt(), any());
+            verify(slot1Phone).dial(anyString(), any());
         } catch (CallStateException e) {
             // This shouldn't happen
             fail();
@@ -700,8 +700,8 @@
         // redialed on another slot
         assertEquals(2, c.getNotifyPhoneAccountChangedCount());
         try {
-            verify(slot0Phone).dial(anyString(), any(), anyInt(), any());
-            verify(slot1Phone).dial(anyString(), any(), anyInt(), any());
+            verify(slot0Phone).dial(anyString(), any());
+            verify(slot1Phone).dial(anyString(), any());
         } catch (CallStateException e) {
             // This shouldn't happen
             fail();
@@ -750,8 +750,8 @@
         // redialed on another slot
         assertEquals(1, c.getNotifyPhoneAccountChangedCount());
         try {
-            verify(slot1Phone).dial(anyString(), any(), anyInt(), any());
-            verify(slot0Phone, never()).dial(anyString(), any(), anyInt(), any());
+            verify(slot1Phone).dial(anyString(), any());
+            verify(slot0Phone, never()).dial(anyString(), any());
         } catch (CallStateException e) {
             // This shouldn't happen
             fail();
@@ -850,7 +850,7 @@
 
     private void setPhonesDialConnection(Phone phone, Connection c) {
         try {
-            when(phone.dial(anyString(), anyInt())).thenReturn(c);
+            when(phone.dial(anyString(), any())).thenReturn(c);
         } catch (CallStateException e) {
             // this shouldn't happen
             fail();