Merge "Add ability to disable conference event package handling from command line."
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 49c1571..c4c33ca 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -199,6 +199,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/ecc/input/eccdata.txt b/ecc/input/eccdata.txt
index bf5d92c..403cad7 100644
--- a/ecc/input/eccdata.txt
+++ b/ecc/input/eccdata.txt
@@ -600,11 +600,8 @@
countries {
iso_code: "DE"
eccs {
- phone_number: "110"
- types: POLICE
- }
- eccs {
phone_number: "112"
+ types: POLICE
types: AMBULANCE
types: FIRE
}
diff --git a/ecc/output/eccdata b/ecc/output/eccdata
index 2b9007a..917273d 100644
--- a/ecc/output/eccdata
+++ b/ecc/output/eccdata
Binary files differ
diff --git a/res/layout/emergency_dialer.xml b/res/layout/emergency_dialer.xml
index 6247379..892b8f4 100644
--- a/res/layout/emergency_dialer.xml
+++ b/res/layout/emergency_dialer.xml
@@ -108,7 +108,7 @@
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:backgroundTint="#ffe53935"
+ android:backgroundTint="#ffe32926"
android:focusable="false"
android:clickable="false"
style="?android:attr/buttonStyle"/>
diff --git a/src/com/android/phone/CallBarringDeselectAllPreference.java b/src/com/android/phone/CallBarringDeselectAllPreference.java
index 153bc0c..e9310f8 100644
--- a/src/com/android/phone/CallBarringDeselectAllPreference.java
+++ b/src/com/android/phone/CallBarringDeselectAllPreference.java
@@ -18,7 +18,6 @@
import android.content.Context;
import android.os.Bundle;
-import android.telephony.ServiceState;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
@@ -52,9 +51,7 @@
protected void showDialog(Bundle state) {
// Finds out if the password field should be shown or not.
ImsPhone imsPhone = mPhone != null ? (ImsPhone) mPhone.getImsPhone() : null;
- mShowPassword = !(imsPhone != null
- && ((imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE)
- || imsPhone.isUtEnabled()));
+ mShowPassword = !(imsPhone != null && imsPhone.isUtEnabled());
// Selects dialog message depending on if the password field is shown or not.
setDialogMessage(getContext().getString(mShowPassword
diff --git a/src/com/android/phone/CallBarringEditPreference.java b/src/com/android/phone/CallBarringEditPreference.java
index 72b3ea5..edff1e3 100644
--- a/src/com/android/phone/CallBarringEditPreference.java
+++ b/src/com/android/phone/CallBarringEditPreference.java
@@ -26,7 +26,6 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
-import android.telephony.ServiceState;
import android.text.method.DigitsKeyListener;
import android.text.method.PasswordTransformationMethod;
import android.util.AttributeSet;
@@ -257,9 +256,7 @@
private void setShowPassword() {
ImsPhone imsPhone = mPhone != null ? (ImsPhone) mPhone.getImsPhone() : null;
- mShowPassword = !(imsPhone != null
- && ((imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE)
- || imsPhone.isUtEnabled()));
+ mShowPassword = !(imsPhone != null && imsPhone.isUtEnabled());
}
@Override
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/EmergencyCallbackModeExitDialog.java b/src/com/android/phone/EmergencyCallbackModeExitDialog.java
index 2492f46..dcfa024 100644
--- a/src/com/android/phone/EmergencyCallbackModeExitDialog.java
+++ b/src/com/android/phone/EmergencyCallbackModeExitDialog.java
@@ -68,6 +68,7 @@
private boolean mInEmergencyCall = false;
private static final int ECM_TIMER_RESET = 1;
private Phone mPhone = null;
+ private boolean mIsResumed = false;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -100,6 +101,18 @@
}
@Override
+ public void onResume() {
+ super.onResume();
+ mIsResumed = true;
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mIsResumed = false;
+ }
+
+ @Override
public void onDestroy() {
super.onDestroy();
try {
@@ -176,7 +189,7 @@
* Shows Emergency Callback Mode dialog and starts countdown timer
*/
private void showEmergencyCallbackModeExitDialog() {
- if (!this.isResumed()) {
+ if (!mIsResumed) {
Log.w(TAG, "Tried to show dialog, but activity was already finished");
return;
}
diff --git a/src/com/android/phone/GsmUmtsCallBarringOptions.java b/src/com/android/phone/GsmUmtsCallBarringOptions.java
index a6f9844..3c9cd84 100644
--- a/src/com/android/phone/GsmUmtsCallBarringOptions.java
+++ b/src/com/android/phone/GsmUmtsCallBarringOptions.java
@@ -27,7 +27,6 @@
import android.preference.Preference;
import android.preference.PreferenceScreen;
import android.telephony.CarrierConfigManager;
-import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.Log;
@@ -423,9 +422,7 @@
boolean useDisableaAll = true;
ImsPhone imsPhone = mPhone != null ? (ImsPhone) mPhone.getImsPhone() : null;
- if (imsPhone != null
- && ((imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE)
- || imsPhone.isUtEnabled())) {
+ if (imsPhone != null && imsPhone.isUtEnabled()) {
usePassword = false;
useDisableaAll = false;
}
diff --git a/src/com/android/phone/GsmUmtsCallForwardOptions.java b/src/com/android/phone/GsmUmtsCallForwardOptions.java
index b8ea8fd..10bd8d7 100644
--- a/src/com/android/phone/GsmUmtsCallForwardOptions.java
+++ b/src/com/android/phone/GsmUmtsCallForwardOptions.java
@@ -18,6 +18,7 @@
import java.util.ArrayList;
public class GsmUmtsCallForwardOptions extends TimeConsumingPreferenceActivity {
+ private static final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 2);
private static final String LOG_TAG = "GsmUmtsCallForwardOptions";
private static final String NUM_PROJECTION[] = {
@@ -62,6 +63,7 @@
mPhone = mSubscriptionInfoHelper.getPhone();
PersistableBundle b = null;
+ boolean supportCFNRc = true;
if (mSubscriptionInfoHelper.hasSubId()) {
b = PhoneGlobals.getInstance().getCarrierConfigForSubId(
mSubscriptionInfoHelper.getSubId());
@@ -73,6 +75,8 @@
CarrierConfigManager.KEY_CALL_FORWARDING_MAP_NON_NUMBER_TO_VOICEMAIL_BOOL);
mCallForwardByUssd = b.getBoolean(
CarrierConfigManager.KEY_USE_CALL_FORWARDING_USSD_BOOL);
+ supportCFNRc = b.getBoolean(
+ CarrierConfigManager.KEY_CALL_FORWARDING_WHEN_UNREACHABLE_SUPPORTED_BOOL);
}
PreferenceScreen prefSet = getPreferenceScreen();
@@ -89,7 +93,16 @@
mPreferences.add(mButtonCFU);
mPreferences.add(mButtonCFB);
mPreferences.add(mButtonCFNRy);
- mPreferences.add(mButtonCFNRc);
+
+ if (supportCFNRc) {
+ mPreferences.add(mButtonCFNRc);
+ } else {
+ // When CFNRc is not supported, mButtonCFNRc is grayed out from the menu.
+ // Default state for the preferences in this PreferenceScreen is disabled.
+ // Only preferences listed in the ArrayList mPreferences will be enabled.
+ // By not adding mButtonCFNRc to mPreferences it will be kept disabled.
+ if (DBG) Log.d(LOG_TAG, "onCreate: CFNRc is not supported, grey out the item.");
+ }
if (mCallForwardByUssd) {
//the call forwarding ussd command's behavior is similar to the call forwarding when
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index d0eda12..e5e9fe7 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -153,6 +153,7 @@
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;
@@ -2040,7 +2041,7 @@
private int getTargetSdk(String packageName) {
try {
final ApplicationInfo ai = mApp.getPackageManager().getApplicationInfoAsUser(
- packageName, 0, UserHandle.getUserId(Binder.getCallingUid()));
+ packageName, 0, UserHandle.getUserHandleForUid(Binder.getCallingUid()));
if (ai != null) return ai.targetSdkVersion;
} catch (PackageManager.NameNotFoundException unexpected) {
loge("Failed to get package info for pkg="
@@ -2720,7 +2721,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);
@@ -4811,13 +4812,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);
@@ -4868,7 +4869,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);
@@ -5319,14 +5320,19 @@
}
/**
- * Determines whether the user has turned on RTT. Only returns true if the device and carrier
- * both also support RTT.
+ * Determines whether the user has turned on RTT. If the carrier wants to ignore the user-set
+ * RTT setting, will return true if the device and carrier both support RTT.
+ * Otherwise. only returns true if the device and carrier both also support RTT.
*/
public boolean isRttEnabled(int subscriptionId) {
final long identity = Binder.clearCallingIdentity();
try {
- return isRttSupported(subscriptionId) && Settings.Secure.getInt(
+ boolean isRttSupported = isRttSupported(subscriptionId);
+ boolean isUserRttSettingOn = Settings.Secure.getInt(
mApp.getContentResolver(), Settings.Secure.RTT_CALLING_MODE, 0) != 0;
+ boolean shouldIgnoreUserRttSetting = mApp.getCarrierConfigForSubId(subscriptionId)
+ .getBoolean(CarrierConfigManager.KEY_IGNORE_RTT_MODE_SETTING_BOOL);
+ return isRttSupported && (isUserRttSettingOn || shouldIgnoreUserRttSetting);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -6453,7 +6459,10 @@
if (card != null) {
cardId = card.getCardId();
} else {
- cardId = slot.getIccId();
+ cardId = slot.getEid();
+ if (TextUtils.isEmpty(cardId)) {
+ cardId = slot.getIccId();
+ }
}
if (cardId != null) {
@@ -7007,6 +7016,33 @@
}
}
+ @Override
+ public boolean isApplicationOnUicc(int subId, int appType) {
+ enforceReadPrivilegedPermission("isApplicationOnUicc");
+ Phone phone = getPhone(subId);
+ if (phone == null) {
+ return false;
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ UiccCard uiccCard = phone.getUiccCard();
+ if (uiccCard == null) {
+ return false;
+ }
+ UiccProfile uiccProfile = uiccCard.getUiccProfile();
+ if (uiccProfile == null) {
+ return false;
+ }
+ if (TelephonyManager.APPTYPE_SIM <= appType
+ && appType <= TelephonyManager.APPTYPE_ISIM) {
+ return uiccProfile.isApplicationOnIcc(AppType.values()[appType]);
+ }
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
/**
* Get whether making changes to modem configurations will trigger reboot.
* Return value defaults to true.
diff --git a/src/com/android/phone/settings/AccessibilitySettingsFragment.java b/src/com/android/phone/settings/AccessibilitySettingsFragment.java
index 942f28c..5a70fe2 100644
--- a/src/com/android/phone/settings/AccessibilitySettingsFragment.java
+++ b/src/com/android/phone/settings/AccessibilitySettingsFragment.java
@@ -166,10 +166,17 @@
int rttMode = mButtonRtt.isChecked() ? 1 : 0;
Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.RTT_CALLING_MODE,
rttMode);
- // Update RTT config with IMS Manager
- ImsManager imsManager = ImsManager.getInstance(getContext(),
- SubscriptionManager.getDefaultVoicePhoneId());
- imsManager.setRttEnabled(mButtonRtt.isChecked());
+ // Update RTT config with IMS Manager if the always-on carrier config isn't set to true.
+ CarrierConfigManager configManager = (CarrierConfigManager) mContext.getSystemService(
+ Context.CARRIER_CONFIG_SERVICE);
+ for (int subId : SubscriptionController.getInstance().getActiveSubIdList(true)) {
+ if (!configManager.getConfigForSubId(subId).getBoolean(
+ CarrierConfigManager.KEY_IGNORE_RTT_MODE_SETTING_BOOL, false)) {
+ int phoneId = SubscriptionController.getInstance().getPhoneId(subId);
+ ImsManager imsManager = ImsManager.getInstance(getContext(), phoneId);
+ imsManager.setRttEnabled(mButtonRtt.isChecked());
+ }
+ }
return true;
}
@@ -199,18 +206,23 @@
}
private boolean shouldShowRttSetting() {
- int subscriptionId = SubscriptionManager.getDefaultVoiceSubscriptionId();
- if (subscriptionId == SubscriptionManager.INVALID_SUBSCRIPTION_ID
- || subscriptionId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
- for (int subId : SubscriptionController.getInstance().getActiveSubIdList(true)) {
- if (PhoneGlobals.getInstance().phoneMgr.isRttSupported(subId)) {
+ CarrierConfigManager configManager =
+ (CarrierConfigManager) mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
+ // Go through all the subs -- if we want to display the RTT setting for any of them, do
+ // display it.
+ for (int subId : SubscriptionController.getInstance().getActiveSubIdList(true)) {
+ // In order to display the setting, we want:
+ // 1. The subscription supports RTT
+ // 2. The subscription isn't configured by the carrier to have the setting always-on
+ // (see the documentation for the carrier config key)
+ if (PhoneGlobals.getInstance().phoneMgr.isRttSupported(subId)) {
+ if (!configManager.getConfigForSubId(subId).getBoolean(
+ CarrierConfigManager.KEY_IGNORE_RTT_MODE_SETTING_BOOL, false)) {
return true;
}
}
- return false;
- } else {
- return PhoneGlobals.getInstance().phoneMgr.isRttSupported(subscriptionId);
}
+ return false;
}
/**
diff --git a/src/com/android/services/telephony/DisconnectCauseUtil.java b/src/com/android/services/telephony/DisconnectCauseUtil.java
index cf3f913..94e8c4a 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));
}
/**
@@ -793,11 +797,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 245f2e8..4da92e2 100644
--- a/src/com/android/services/telephony/ImsConference.java
+++ b/src/com/android/services/telephony/ImsConference.java
@@ -829,7 +829,7 @@
// If the single party call emulation fature flag is enabled, we can potentially treat
// the conference as a single party call when there is just one participant.
if (mFeatureFlagProxy.isUsingSinglePartyCallEmulation()) {
- if (oldParticipantCount > 1 && newParticipantCount == 1) {
+ if (oldParticipantCount != 1 && newParticipantCount == 1) {
// If number of participants goes to 1, emulate a single party call.
startEmulatingSinglePartyCall();
} else if (mIsEmulatingSinglePartyCall && !isSinglePartyConference) {
@@ -1312,4 +1312,12 @@
return isMaximumConferenceSizeEnforced()
&& getNumberOfParticipants() >= getMaximumConferenceSize();
}
+
+ /**
+ * @return {@code True} if the ImsConference is emulating single party call.
+ */
+ @VisibleForTesting
+ public boolean isEmulatingSinglePartyCall() {
+ return mIsEmulatingSinglePartyCall;
+ }
}
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/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index 7e29e85..84fa40c 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -1159,7 +1159,8 @@
&& isShowingOriginalDialString()) {
Log.i(this, "new original dial string is null, convert to: "
+ mOriginalConnection.getOrigDialString());
- originalConnection.setConverted(mOriginalConnection.getOrigDialString());
+ originalConnection.restoreDialedNumberAfterConversion(
+ mOriginalConnection.getOrigDialString());
}
clearOriginalConnection();
@@ -2219,6 +2220,8 @@
if (isIms) {
isVoWifiEnabled = ImsUtil.isWfcEnabled(phone.getContext(), phone.getPhoneId());
}
+ boolean isRttMergeSupported = getCarrierConfig()
+ .getBoolean(CarrierConfigManager.KEY_ALLOW_MERGING_RTT_CALLS_BOOL);
PhoneAccountHandle phoneAccountHandle = isIms ? PhoneUtils
.makePstnPhoneAccountHandle(phone.getDefaultPhone())
: PhoneUtils.makePstnPhoneAccountHandle(phone);
@@ -2243,7 +2246,7 @@
if (mTreatAsEmergencyCall) {
isConferenceSupported = false;
Log.d(this, "refreshConferenceSupported = false; emergency call");
- } else if (isRtt()) {
+ } else if (isRtt() && !isRttMergeSupported) {
isConferenceSupported = false;
Log.d(this, "refreshConferenceSupported = false; rtt call");
} else if (!isConferencingSupported || isIms && !isImsConferencingSupported) {
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 927b2c9..0e5a612 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -25,6 +25,9 @@
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
import android.provider.Settings;
import android.telecom.Conference;
import android.telecom.Connection;
@@ -176,6 +179,8 @@
// destroyed.
@VisibleForTesting
public Pair<WeakReference<TelephonyConnection>, Queue<Phone>> mEmergencyRetryCache;
+ private Handler mDdsSwitchHandler;
+ private HandlerThread mHandlerThread;
/**
* Keeps track of the status of a SIM slot.
@@ -329,11 +334,17 @@
IntentFilter intentFilter = new IntentFilter(
TelecomManager.ACTION_TTY_PREFERRED_MODE_CHANGED);
registerReceiver(mTtyBroadcastReceiver, intentFilter);
+
+ mHandlerThread = new HandlerThread("DdsSwitchHandlerThread");
+ mHandlerThread.start();
+ Looper looper = mHandlerThread.getLooper();
+ mDdsSwitchHandler = new Handler(looper);
}
@Override
public boolean onUnbind(Intent intent) {
unregisterReceiver(mTtyBroadcastReceiver);
+ mHandlerThread.quitSafely();
return super.onUnbind(intent);
}
@@ -523,14 +534,14 @@
} else {
final Connection resultConnection = getTelephonyConnection(request, numberToDial,
true, handle, phone);
- CompletableFuture<Boolean> phoneFuture = delayDialForDdsSwitch(phone);
- phoneFuture.whenComplete((result, error) -> {
- if (error != null) {
- Log.w(this, "onCreateOutgoingConn - delayDialForDdsSwitch exception= "
- + error.getMessage());
+ mDdsSwitchHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ boolean result = delayDialForDdsSwitch(phone);
+ Log.i(this,
+ "onCreateOutgoingConn - delayDialForDdsSwitch result = " + result);
+ placeOutgoingConnection(request, resultConnection, phone);
}
- Log.i(this, "onCreateOutgoingConn - delayDialForDdsSwitch result = " + result);
- placeOutgoingConnection(request, resultConnection, phone);
});
return resultConnection;
}
@@ -604,14 +615,14 @@
adjustAndPlaceOutgoingConnection(phone, originalConnection, request, numberToDial,
handle, originalPhoneType, false);
} else {
- delayDialForDdsSwitch(phone).whenComplete((result, error) -> {
- if (error != null) {
- Log.w(this, "handleOnComplete - delayDialForDdsSwitch exception= "
- + error.getMessage());
+ mDdsSwitchHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ boolean result = delayDialForDdsSwitch(phone);
+ Log.i(this, "handleOnComplete - delayDialForDdsSwitch result = " + result);
+ adjustAndPlaceOutgoingConnection(phone, originalConnection, request,
+ numberToDial, handle, originalPhoneType, true);
}
- Log.i(this, "handleOnComplete - delayDialForDdsSwitch result = " + result);
- adjustAndPlaceOutgoingConnection(phone, originalConnection, request,
- numberToDial, handle, originalPhoneType, true);
});
}
@@ -1234,6 +1245,11 @@
com.android.internal.telephony.Connection originalConnection = null;
try {
if (phone != null) {
+ EmergencyNumber emergencyNumber =
+ phone.getEmergencyNumberTracker().getEmergencyNumber(number);
+ if (emergencyNumber != null) {
+ phone.notifyOutgoingEmergencyCall(emergencyNumber);
+ }
originalConnection = phone.dial(number, new ImsPhone.ImsDialArgs.Builder()
.setVideoState(videoState)
.setIntentExtras(extras)
@@ -1375,13 +1391,22 @@
return chosenPhone;
}
- private CompletableFuture<Boolean> delayDialForDdsSwitch(Phone phone) {
+ /**
+ * If needed, block until the the default data is is switched for outgoing emergency call, or
+ * timeout expires.
+ */
+ private boolean delayDialForDdsSwitch(Phone phone) {
if (phone == null) {
- return CompletableFuture.completedFuture(Boolean.TRUE);
+ return true;
}
- return possiblyOverrideDefaultDataForEmergencyCall(phone)
- .completeOnTimeout(false, DEFAULT_DATA_SWITCH_TIMEOUT_MS,
- TimeUnit.MILLISECONDS);
+ try {
+ return possiblyOverrideDefaultDataForEmergencyCall(phone).get(
+ DEFAULT_DATA_SWITCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ } catch (Exception e) {
+ Log.w(this, "onCreateOutgoingConn - delayDialForDdsSwitch exception= "
+ + e.getMessage());
+ return false;
+ }
}
/**
diff --git a/tests/src/com/android/services/telephony/ImsConferenceTest.java b/tests/src/com/android/services/telephony/ImsConferenceTest.java
index 68b5b3b..568549b 100644
--- a/tests/src/com/android/services/telephony/ImsConferenceTest.java
+++ b/tests/src/com/android/services/telephony/ImsConferenceTest.java
@@ -16,19 +16,16 @@
package com.android.services.telephony;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.times;
-
-import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.net.Uri;
import android.os.Looper;
@@ -39,15 +36,10 @@
import android.telecom.PhoneAccountHandle;
import android.test.suitebuilder.annotation.SmallTest;
-import com.android.internal.telephony.PhoneConstants;
-
import org.junit.Before;
import org.junit.Test;
-
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
import java.util.Arrays;
@@ -179,6 +171,31 @@
}
/**
+ * Verify that the single party emulate correctly when the conference start with only
+ * one participant.
+ */
+ @Test
+ @SmallTest
+ public void testSinglePartyEmulationWithOneParticipantAtBeginning() {
+ when(mMockTelecomAccountRegistry.isUsingSimCallManager(any(PhoneAccountHandle.class)))
+ .thenReturn(false);
+
+ ImsConference imsConference = new ImsConference(mMockTelecomAccountRegistry,
+ mMockTelephonyConnectionServiceProxy, mConferenceHost,
+ null /* phoneAccountHandle */, () -> true /* featureFlagProxy */);
+
+ ConferenceParticipant participant1 = new ConferenceParticipant(
+ Uri.parse("tel:6505551212"),
+ "A",
+ Uri.parse("sip:6505551212@testims.com"),
+ Connection.STATE_ACTIVE,
+ Call.Details.DIRECTION_INCOMING);
+ imsConference.handleConferenceParticipantsUpdate(mConferenceHost,
+ Arrays.asList(participant1));
+ assertTrue(imsConference.isEmulatingSinglePartyCall());
+ }
+
+ /**
* Verify that we do not use single party emulation when a sim call manager is in use.
*/
@Test