Merge "DO NOT MERGE - qt-qpr1-dev-plus-aosp-without-vendor@5915889 into stage-aosp-master" into stage-aosp-master
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 4854db7..1309f77 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -437,7 +437,7 @@
<string name="deleting_fdn_contact" msgid="5669163206349319969">"正在删除固定拨号联系人..."</string>
<string name="fdn_contact_deleted" msgid="7154162327112259569">"已删除固定拨号联系人。"</string>
<string name="pin2_invalid" msgid="5470854099230755944">"固定拨号未更新,因为输入的 PIN 码有误。"</string>
- <string name="fdn_invalid_number" msgid="2062898833049589309">"未能更新 FDN,因为号码超过 20 位数。"</string>
+ <string name="fdn_invalid_number" msgid="2062898833049589309">"未能更新 FDN,因为号码超过 <xliff:g id="FDN_NUMBER_LIMIT_LENGTH">%d</xliff:g> 位数。"</string>
<string name="pin2_or_fdn_invalid" msgid="6025144083384701197">"固定拨号未更新。PIN2 码有误,或电话号码遭拒。"</string>
<string name="fdn_failed" msgid="540018079008319747">"固定拨号操作失败。"</string>
<string name="simContacts_emptyLoading" msgid="2203331234764498011">"正在从SIM卡读取..."</string>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index 3ccaa6c..02fa380 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -439,7 +439,7 @@
<string name="deleting_fdn_contact" msgid="5669163206349319969">"正在刪除固定撥號…"</string>
<string name="fdn_contact_deleted" msgid="7154162327112259569">"已刪除固定撥號。"</string>
<string name="pin2_invalid" msgid="5470854099230755944">"您所輸入的 PIN 不正確,因此未更新 FDN。"</string>
- <string name="fdn_invalid_number" msgid="2062898833049589309">"固定撥號的號碼超過 20 位數,因此無法更新。"</string>
+ <string name="fdn_invalid_number" msgid="2062898833049589309">"固定撥號的號碼超過 <xliff:g id="FDN_NUMBER_LIMIT_LENGTH">%d</xliff:g> 位數,因此無法更新。"</string>
<string name="pin2_or_fdn_invalid" msgid="6025144083384701197">"未更新 FDN。可能是因為 PIN2 碼不正確或電話號碼遭拒。"</string>
<string name="fdn_failed" msgid="540018079008319747">"FDN 操作失敗。"</string>
<string name="simContacts_emptyLoading" msgid="2203331234764498011">"正在從 SIM 卡讀取…"</string>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 7dae45d..689e239 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -977,7 +977,7 @@
<!-- FDN settings: error message displayed in a popup (toast) -->
<string name="pin2_invalid">FDN wasn\'t updated because you typed an incorrect PIN.</string>
<!-- FDN settings: error message displayed in a popup (toast) -->
- <string name="fdn_invalid_number">FDN wasn\'t updated because the number exceeds 20 digits.</string>
+ <string name="fdn_invalid_number">FDN wasn\'t updated because the number exceeds <xliff:g id="FDN_NUMBER_LIMIT_LENGTH">%d</xliff:g> digits.</string>
<!-- FDN settings: error message displayed in a popup (toast), when the entered
FDN number was inappropriate, OR, PIN2 the user entered was incorrect.
Because of API restriction, there's no way to determine which is the exact
diff --git a/src/com/android/phone/CarrierConfigLoader.java b/src/com/android/phone/CarrierConfigLoader.java
index 077652f..1d0138b 100644
--- a/src/com/android/phone/CarrierConfigLoader.java
+++ b/src/com/android/phone/CarrierConfigLoader.java
@@ -568,6 +568,13 @@
configPackagename = mPlatformCarrierConfigPackage;
configToSend = mConfigFromDefaultApp[phoneId];
}
+
+ // mOverrideConfigs is for testing. And it will override current configs.
+ PersistableBundle config = mOverrideConfigs[phoneId];
+ if (config != null) {
+ configToSend.putAll(config);
+ }
+
mSubscriptionInfoUpdater.updateSubscriptionByCarrierConfigAndNotifyComplete(
phoneId, configPackagename, configToSend,
mHandler.obtainMessage(EVENT_SUBSCRIPTION_INFO_UPDATED, phoneId, -1));
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 35743ef..bb7c31b 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -106,6 +106,7 @@
import android.telephony.ims.aidl.IImsRcsFeature;
import android.telephony.ims.aidl.IImsRegistration;
import android.telephony.ims.aidl.IImsRegistrationCallback;
+import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.feature.MmTelFeature;
import android.telephony.ims.stub.ImsConfigImplBase;
import android.telephony.ims.stub.ImsRegistrationImplBase;
@@ -142,8 +143,6 @@
import com.android.internal.telephony.RIL;
import com.android.internal.telephony.RILConstants;
import com.android.internal.telephony.ServiceStateTracker;
-import com.android.internal.telephony.SmsApplication;
-import com.android.internal.telephony.SmsApplication.SmsApplicationData;
import com.android.internal.telephony.SmsController;
import com.android.internal.telephony.SmsPermissions;
import com.android.internal.telephony.SubscriptionController;
@@ -176,7 +175,6 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -2906,6 +2904,10 @@
public void registerImsRegistrationCallback(int subId, IImsRegistrationCallback c)
throws RemoteException {
enforceReadPrivilegedPermission("registerImsRegistrationCallback");
+ if (!ImsManager.isImsSupportedOnDevice(mApp)) {
+ throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
+ "IMS not available on device.");
+ }
final long token = Binder.clearCallingIdentity();
try {
// TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
@@ -2942,6 +2944,10 @@
public void registerMmTelCapabilityCallback(int subId, IImsCapabilityCallback c)
throws RemoteException {
enforceReadPrivilegedPermission("registerMmTelCapabilityCallback");
+ if (!ImsManager.isImsSupportedOnDevice(mApp)) {
+ throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
+ "IMS not available on device.");
+ }
// TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
final long token = Binder.clearCallingIdentity();
try {
@@ -3007,6 +3013,44 @@
}
}
+ /**
+ * Determines if the MmTel feature capability is supported by the carrier configuration for this
+ * subscription.
+ * @param subId The subscription to use to check the configuration.
+ * @param callback The callback that will be used to send the result.
+ * @param capability The MmTelFeature capability that will be used to send the result.
+ * @param transportType The transport type of the MmTelFeature capability.
+ */
+ @Override
+ public void isMmTelCapabilitySupported(int subId, IIntegerConsumer callback, int capability,
+ int transportType) {
+ enforceReadPrivilegedPermission("isMmTelCapabilitySupported");
+ if (!ImsManager.isImsSupportedOnDevice(mApp)) {
+ throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
+ "IMS not available on device.");
+ }
+ final long token = Binder.clearCallingIdentity();
+ try {
+ int slotId = getSlotIndex(subId);
+ if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
+ Log.w(LOG_TAG, "isMmTelCapabilitySupported: called with an inactive subscription '"
+ + subId + "'");
+ throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION);
+ }
+ ImsManager.getInstance(mApp, slotId).isSupported(capability,
+ transportType, aBoolean -> {
+ try {
+ callback.accept((aBoolean == null) ? 0 : (aBoolean ? 1 : 0));
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "isMmTelCapabilitySupported: remote caller is not "
+ + "running. Ignore");
+ }
+ });
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
@Override
public boolean isAdvancedCallingSettingEnabled(int subId) {
enforceReadPrivilegedPermission("enforceReadPrivilegedPermission");
@@ -4473,6 +4517,40 @@
}
}
+ /**
+ * Get the MmTelFeature state associated with the requested subscription id.
+ * @param subId The subscription that the MmTelFeature is associated with.
+ * @param callback A callback with an integer containing the
+ * {@link android.telephony.ims.feature.ImsFeature.ImsState} associated with the MmTelFeature.
+ */
+ @Override
+ public void getImsMmTelFeatureState(int subId, IIntegerConsumer callback) {
+ enforceReadPrivilegedPermission("getImsMmTelFeatureState");
+ if (!ImsManager.isImsSupportedOnDevice(mApp)) {
+ throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
+ "IMS not available on device.");
+ }
+ final long token = Binder.clearCallingIdentity();
+ try {
+ int slotId = getSlotIndex(subId);
+ if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
+ Log.w(LOG_TAG, "getImsMmTelFeatureState: called with an inactive subscription '"
+ + subId + "'");
+ throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION);
+ }
+ ImsManager.getInstance(mApp, slotId).getImsServiceState(anInteger -> {
+ try {
+ callback.accept(anInteger == null ? ImsFeature.STATE_UNAVAILABLE : anInteger);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "getImsMmTelFeatureState: remote caller is no longer running. "
+ + "Ignore");
+ }
+ });
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
public void setImsRegistrationState(boolean registered) {
enforceModifyPermission();
@@ -5665,6 +5743,11 @@
// in and combined with those stale ones. In case this happens again,
// user can reset all network settings which will clean up this table.
cleanUpSmsRawTable(getDefaultPhone().getContext());
+ // Clean up IMS settings as well here.
+ int slotId = getSlotIndex(subId);
+ if (slotId > SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
+ ImsManager.getInstance(mApp, slotId).factoryReset();
+ }
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -6886,75 +6969,6 @@
}
}
- private void ensureUserRunning(int userId) {
- if (!mUserManager.isUserRunning(userId)) {
- throw new IllegalStateException("User " + userId + " does not exist or not running");
- }
- }
-
- /**
- * Returns a list of SMS apps on a given user.
- *
- * Only the shell user (UID 2000 or 0) can call it.
- * Target user must be running.
- */
- @Override
- public String[] getSmsApps(int userId) {
- TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "getSmsApps");
- ensureUserRunning(userId);
-
- final Collection<SmsApplicationData> apps =
- SmsApplication.getApplicationCollectionAsUser(mApp, userId);
-
- String[] ret = new String[apps.size()];
- int i = 0;
- for (SmsApplicationData app : apps) {
- ret[i++] = app.mPackageName;
- }
- return ret;
- }
-
- /**
- * Returns the default SMS app package name on a given user.
- *
- * Only the shell user (UID 2000 or 0) can call it.
- * Target user must be running.
- */
- @Override
- public String getDefaultSmsApp(int userId) {
- TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "getDefaultSmsApp");
- ensureUserRunning(userId);
-
- final ComponentName cn = SmsApplication.getDefaultSmsApplicationAsUser(mApp,
- /* updateIfNeeded= */ true, userId);
- return cn == null ? null : cn.getPackageName();
- }
-
- /**
- * Set a package as the default SMS app on a given user.
- *
- * Only the shell user (UID 2000 or 0) can call it.
- * Target user must be running.
- */
- @Override
- public void setDefaultSmsApp(int userId, String packageName) {
- TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "setDefaultSmsApp");
- ensureUserRunning(userId);
-
- boolean found = false;
- for (String pkg : getSmsApps(userId)) {
- if (TextUtils.equals(packageName, pkg)) {
- found = true;
- break;
- }
- }
- if (!found) {
- throw new IllegalArgumentException("Package " + packageName + " is not an SMS app");
- }
-
- SmsApplication.setDefaultApplicationAsUser(packageName, mApp, userId);
- }
-
@Override
public Map<Integer, List<EmergencyNumber>> getEmergencyNumberList(
String callingPackage) {
diff --git a/src/com/android/phone/TelephonyShellCommand.java b/src/com/android/phone/TelephonyShellCommand.java
index a34abc0..d8d1717 100644
--- a/src/com/android/phone/TelephonyShellCommand.java
+++ b/src/com/android/phone/TelephonyShellCommand.java
@@ -20,7 +20,6 @@
import android.os.Process;
import android.os.RemoteException;
import android.os.ShellCommand;
-import android.os.UserHandle;
import android.telephony.SubscriptionManager;
import android.telephony.emergency.EmergencyNumber;
import android.util.Log;
@@ -45,7 +44,6 @@
private static final int DEFAULT_PHONE_ID = 0;
private static final String IMS_SUBCOMMAND = "ims";
- private static final String SMS_SUBCOMMAND = "sms";
private static final String NUMBER_VERIFICATION_SUBCOMMAND = "numverify";
private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode";
@@ -58,10 +56,6 @@
// 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";
- private static final String SMS_SET_DEFAULT_APP = "set-default-app";
-
private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call";
@@ -82,9 +76,6 @@
case IMS_SUBCOMMAND: {
return handleImsCommand();
}
- case SMS_SUBCOMMAND: {
- return handleSmsCommand();
- }
case NUMBER_VERIFICATION_SUBCOMMAND:
return handleNumberVerificationCommand();
case EMERGENCY_NUMBER_TEST_MODE:
@@ -103,12 +94,9 @@
pw.println(" Print this help text.");
pw.println(" ims");
pw.println(" IMS Commands.");
- pw.println(" sms");
- pw.println(" SMS Commands.");
pw.println(" emergency-number-test-mode");
pw.println(" Emergency Number Test Mode Commands.");
onHelpIms();
- onHelpSms();
onHelpEmergencyNumber();
}
@@ -139,18 +127,6 @@
pw.println(" enables or disables handling or network conference event package data.");
}
- private void onHelpSms() {
- PrintWriter pw = getOutPrintWriter();
- pw.println("SMS Commands:");
- pw.println(" sms get-apps [--user USER_ID]");
- pw.println(" Print all SMS apps on a user.");
- pw.println(" sms get-default-app [--user USER_ID]");
- pw.println(" Get the default SMS app.");
- pw.println(" sms set-default-app [--user USER_ID] PACKAGE_NAME");
- pw.println(" Set PACKAGE_NAME as the default SMS app.");
- }
-
-
private void onHelpNumberVerification() {
PrintWriter pw = getOutPrintWriter();
pw.println("Number verification commands");
@@ -501,87 +477,6 @@
return slotId;
}
- private int handleSmsCommand() {
- String arg = getNextArg();
- if (arg == null) {
- onHelpSms();
- return 0;
- }
-
- try {
- switch (arg) {
- case SMS_GET_APPS: {
- return handleSmsGetApps();
- }
- case SMS_GET_DEFAULT_APP: {
- return handleSmsGetDefaultApp();
- }
- case SMS_SET_DEFAULT_APP: {
- return handleSmsSetDefaultApp();
- }
- default:
- getErrPrintWriter().println("Unknown command " + arg);
- }
- } catch (RemoteException e) {
- getErrPrintWriter().println("RemoteException: " + e.getMessage());
- }
-
- return -1;
- }
-
- private int maybeParseUserIdArg() {
- int userId = UserHandle.USER_SYSTEM;
- String opt;
- while ((opt = getNextOption()) != null) {
- switch (opt) {
- case "--user": {
- try {
- userId = Integer.parseInt(getNextArgRequired());
- } catch (NumberFormatException e) {
- getErrPrintWriter().println("Invalid user ID for --user");
- return -1;
- }
- break;
- }
- }
- }
- return userId;
- }
-
- private int handleSmsGetApps() throws RemoteException {
- final int userId = maybeParseUserIdArg();
- if (userId < 0) {
- return -1;
- }
-
- for (String packageName : mInterface.getSmsApps(userId)) {
- getOutPrintWriter().println(packageName);
- }
- return 0;
- }
-
- private int handleSmsGetDefaultApp() throws RemoteException {
- final int userId = maybeParseUserIdArg();
- if (userId < 0) {
- return -1;
- }
-
- getOutPrintWriter().println(mInterface.getDefaultSmsApp(userId));
- return 0;
- }
-
- private int handleSmsSetDefaultApp() throws RemoteException {
- final int userId = maybeParseUserIdArg();
- if (userId < 0) {
- return -1;
- }
-
- String packageName = getNextArgRequired();
- mInterface.setDefaultSmsApp(userId, packageName);
- getOutPrintWriter().println("SMS app set to " + mInterface.getDefaultSmsApp(userId));
- return 0;
- }
-
private boolean checkShellUid() {
// adb can run as root or as shell, depending on whether the device is rooted.
return Binder.getCallingUid() == Process.SHELL_UID
diff --git a/src/com/android/phone/settings/fdn/EditFdnContactScreen.java b/src/com/android/phone/settings/fdn/EditFdnContactScreen.java
index c358e27..0eda140 100644
--- a/src/com/android/phone/settings/fdn/EditFdnContactScreen.java
+++ b/src/com/android/phone/settings/fdn/EditFdnContactScreen.java
@@ -29,6 +29,7 @@
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
+import android.os.PersistableBundle;
import android.provider.ContactsContract.CommonDataKinds;
import android.telephony.PhoneNumberUtils;
import android.text.Editable;
@@ -52,6 +53,7 @@
import com.android.phone.PhoneGlobals;
import com.android.phone.R;
import com.android.phone.SubscriptionInfoHelper;
+import android.telephony.CarrierConfigManager;
/**
* Activity to let the user add or edit an FDN contact.
@@ -100,6 +102,7 @@
}
/** flag to track saving state */
private boolean mDataBusy;
+ private int mFdnNumberLimitLength = 20;
@Override
protected void onCreate(Bundle icicle) {
@@ -111,6 +114,17 @@
setContentView(R.layout.edit_fdn_contact_screen);
setupView();
setTitle(mAddContact ? R.string.add_fdn_contact : R.string.edit_fdn_contact);
+ PersistableBundle b = null;
+ if (mSubscriptionInfoHelper.hasSubId()) {
+ b = PhoneGlobals.getInstance().getCarrierConfigForSubId(
+ mSubscriptionInfoHelper.getSubId());
+ } else {
+ b = PhoneGlobals.getInstance().getCarrierConfig();
+ }
+ if (b != null) {
+ mFdnNumberLimitLength = b.getInt(
+ CarrierConfigManager.KEY_FDN_NUMBER_LENGTH_LIMIT_INT);
+ }
displayProgress(false);
}
@@ -294,7 +308,7 @@
* TODO: Fix this logic.
*/
private boolean isValidNumber(String number) {
- return (number.length() <= 20) && (number.length() > 0);
+ return (number.length() <= mFdnNumberLimitLength) && (number.length() > 0);
}
@@ -397,7 +411,8 @@
} else {
if (DBG) log("handleResult: failed!");
if (invalidNumber) {
- showStatus(getResources().getText(R.string.fdn_invalid_number));
+ showStatus(getResources().getString(R.string.fdn_invalid_number,
+ mFdnNumberLimitLength));
} else {
if (PhoneFactory.getDefaultPhone().getIccCard().getIccPin2Blocked()) {
showStatus(getResources().getText(R.string.fdn_enable_puk2_requested));
diff --git a/src/com/android/services/telephony/CdmaConference.java b/src/com/android/services/telephony/CdmaConference.java
index 69ff2a4..693fd16 100755
--- a/src/com/android/services/telephony/CdmaConference.java
+++ b/src/com/android/services/telephony/CdmaConference.java
@@ -18,7 +18,6 @@
import android.content.Context;
import android.os.PersistableBundle;
-import android.telecom.Conference;
import android.telecom.Connection;
import android.telecom.PhoneAccountHandle;
import android.telephony.CarrierConfigManager;
@@ -32,7 +31,7 @@
/**
* CDMA-based conference call.
*/
-public class CdmaConference extends Conference implements Holdable {
+public class CdmaConference extends TelephonyConferenceBase implements Holdable {
private int mCapabilities;
private int mProperties;
private boolean mIsHoldable;
diff --git a/src/com/android/services/telephony/CdmaConferenceController.java b/src/com/android/services/telephony/CdmaConferenceController.java
index 5d987f7..9afcd0a 100644
--- a/src/com/android/services/telephony/CdmaConferenceController.java
+++ b/src/com/android/services/telephony/CdmaConferenceController.java
@@ -48,7 +48,8 @@
* the conference from being created for 3 seconds. This is a more pleasant experience for the user.
*/
final class CdmaConferenceController {
- private final Connection.Listener mConnectionListener = new Connection.Listener() {
+ private final TelephonyConnection.TelephonyConnectionListener mTelephonyConnectionListener =
+ new TelephonyConnection.TelephonyConnectionListener() {
@Override
public void onStateChanged(Connection c, int state) {
recalculateConference();
@@ -139,7 +140,7 @@
private void addInternal(CdmaConnection connection) {
mCdmaConnections.add(connection);
- connection.addConnectionListener(mConnectionListener);
+ connection.addTelephonyConnectionListener(mTelephonyConnectionListener);
recalculateConference();
}
@@ -151,7 +152,7 @@
return;
}
- connection.removeConnectionListener(mConnectionListener);
+ connection.removeTelephonyConnectionListener(mTelephonyConnectionListener);
mCdmaConnections.remove(connection);
recalculateConference();
}
@@ -197,14 +198,14 @@
for (CdmaConnection connection : conferenceConnections) {
if (!existingChildConnections.contains(connection)) {
Log.i(this, "Adding connection to conference call: %s", connection);
- mConference.addConnection(connection);
+ mConference.addTelephonyConnection(connection);
}
existingChildConnections.remove(connection);
}
// 3) Remove any lingering old/disconnected/destroyed connections
for (Connection oldConnection : existingChildConnections) {
- mConference.removeConnection(oldConnection);
+ mConference.removeTelephonyConnection(oldConnection);
Log.i(this, "Removing connection from conference call: %s", oldConnection);
}
@@ -212,13 +213,13 @@
if (isNewlyCreated) {
Log.d(this, "Adding the conference call");
mConference.updateCallRadioTechAfterCreation();
- mConnectionService.addConference(mConference);
+ mConnectionService.addTelephonyConference(mConference);
}
} else if (conferenceConnections.isEmpty()) {
// There are no more connection so if we still have a conference, lets remove it.
if (mConference != null) {
Log.i(this, "Destroying the CDMA conference connection.");
- mConference.destroy();
+ mConference.destroyTelephonyConference();
mConference = null;
}
}
diff --git a/src/com/android/services/telephony/CdmaConnection.java b/src/com/android/services/telephony/CdmaConnection.java
index ca842b1..bd015e3 100644
--- a/src/com/android/services/telephony/CdmaConnection.java
+++ b/src/com/android/services/telephony/CdmaConnection.java
@@ -228,8 +228,8 @@
} catch (CallStateException e) {
Log.e(this, e, "Failed to hangup call waiting call");
}
- setDisconnected(DisconnectCauseUtil.toTelecomDisconnectCause(telephonyDisconnectCause,
- null, getPhone().getPhoneId()));
+ setTelephonyConnectionDisconnected(DisconnectCauseUtil.toTelecomDisconnectCause(
+ telephonyDisconnectCause, null, getPhone().getPhoneId()));
}
}
@@ -325,7 +325,7 @@
}
@Override
- protected void close() {
+ public void close() {
mIsConnectionTimeReset = false;
if (getPhone() != null) {
getPhone().unregisterForLineControlInfo(mHandler);
diff --git a/src/com/android/services/telephony/ImsConference.java b/src/com/android/services/telephony/ImsConference.java
index 1969b10..17549cf 100644
--- a/src/com/android/services/telephony/ImsConference.java
+++ b/src/com/android/services/telephony/ImsConference.java
@@ -21,7 +21,6 @@
import android.net.Uri;
import android.os.Bundle;
import android.os.PersistableBundle;
-import android.telecom.Conference;
import android.telecom.ConferenceParticipant;
import android.telecom.Connection;
import android.telecom.Connection.VideoProvider;
@@ -68,7 +67,7 @@
* connection and is responsible for managing the conference participant connections which represent
* the participants.
*/
-public class ImsConference extends Conference implements Holdable {
+public class ImsConference extends TelephonyConferenceBase implements Holdable {
/**
* Abstracts out fetching a feature flag. Makes testing easier.
@@ -78,149 +77,127 @@
}
/**
- * Listener used to respond to changes to conference participants. At the conference level we
- * are most concerned with handling destruction of a conference participant.
- */
- private final Connection.Listener mParticipantListener = new Connection.Listener() {
- /**
- * Participant has been destroyed. Remove it from the conference.
- *
- * @param connection The participant which was destroyed.
- */
- @Override
- public void onDestroyed(Connection connection) {
- ConferenceParticipantConnection participant =
- (ConferenceParticipantConnection) connection;
- removeConferenceParticipant(participant);
- updateManageConference();
- }
-
- };
-
- /**
* Listener used to respond to changes to the underlying radio connection for the conference
* host connection. Used to respond to SRVCC changes.
*/
private final TelephonyConnection.TelephonyConnectionListener mTelephonyConnectionListener =
new TelephonyConnection.TelephonyConnectionListener() {
- @Override
- public void onOriginalConnectionConfigured(TelephonyConnection c) {
- if (c == mConferenceHost) {
- handleOriginalConnectionChange();
- }
- }
+ /**
+ * Updates the state of the conference based on the new state of the host.
+ *
+ * @param c The host connection.
+ * @param state The new state
+ */
+ @Override
+ public void onStateChanged(android.telecom.Connection c, int state) {
+ setState(state);
+ }
- /**
- * 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) {
+ /**
+ * Disconnects the conference when its host connection disconnects.
+ *
+ * @param c The host connection.
+ * @param disconnectCause The host connection disconnect cause.
+ */
+ @Override
+ public void onDisconnected(android.telecom.Connection c,
+ DisconnectCause disconnectCause) {
+ setDisconnected(disconnectCause);
+ }
- 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);
+ setVideoState(c, videoState);
+ }
- /**
- * Listener used to respond to changes to the connection to the IMS conference server.
- */
- private final android.telecom.Connection.Listener mConferenceHostListener =
- new android.telecom.Connection.Listener() {
+ @Override
+ public void onVideoProviderChanged(android.telecom.Connection c,
+ Connection.VideoProvider videoProvider) {
+ Log.d(this, "onVideoProviderChanged: Connection: %s, VideoProvider: %s", c,
+ videoProvider);
+ setVideoProvider(c, videoProvider);
+ }
- /**
- * Updates the state of the conference based on the new state of the host.
- *
- * @param c The host connection.
- * @param state The new state
- */
- @Override
- public void onStateChanged(android.telecom.Connection c, int state) {
- setState(state);
- }
+ @Override
+ public void onConnectionCapabilitiesChanged(Connection c,
+ int connectionCapabilities) {
+ Log.d(this, "onConnectionCapabilitiesChanged: Connection: %s,"
+ + " connectionCapabilities: %s", c, connectionCapabilities);
+ int capabilites = ImsConference.this.getConnectionCapabilities();
+ boolean isVideoConferencingSupported = mConferenceHost == null ? false :
+ mConferenceHost.isCarrierVideoConferencingSupported();
+ setConnectionCapabilities(
+ applyHostCapabilities(capabilites, connectionCapabilities,
+ isVideoConferencingSupported));
+ }
- /**
- * Disconnects the conference when its host connection disconnects.
- *
- * @param c The host connection.
- * @param disconnectCause The host connection disconnect cause.
- */
- @Override
- public void onDisconnected(android.telecom.Connection c, DisconnectCause disconnectCause) {
- setDisconnected(disconnectCause);
- }
+ @Override
+ public void onConnectionPropertiesChanged(Connection c, int connectionProperties) {
+ Log.d(this, "onConnectionPropertiesChanged: Connection: %s,"
+ + " connectionProperties: %s", c, connectionProperties);
+ int properties = ImsConference.this.getConnectionProperties();
+ setConnectionProperties(applyHostProperties(properties, connectionProperties));
+ }
- @Override
- public void onVideoStateChanged(android.telecom.Connection c, int videoState) {
- Log.d(this, "onVideoStateChanged video state %d", videoState);
- setVideoState(c, videoState);
- }
+ @Override
+ public void onStatusHintsChanged(Connection c, StatusHints statusHints) {
+ Log.v(this, "onStatusHintsChanged");
+ updateStatusHints();
+ }
- @Override
- public void onVideoProviderChanged(android.telecom.Connection c,
- Connection.VideoProvider videoProvider) {
- Log.d(this, "onVideoProviderChanged: Connection: %s, VideoProvider: %s", c,
- videoProvider);
- setVideoProvider(c, videoProvider);
- }
+ @Override
+ public void onExtrasChanged(Connection c, Bundle extras) {
+ Log.v(this, "onExtrasChanged: c=" + c + " Extras=" + extras);
+ putExtras(extras);
+ }
- @Override
- public void onConnectionCapabilitiesChanged(Connection c, int connectionCapabilities) {
- Log.d(this, "onConnectionCapabilitiesChanged: Connection: %s," +
- " connectionCapabilities: %s", c, connectionCapabilities);
- int capabilites = ImsConference.this.getConnectionCapabilities();
- boolean isVideoConferencingSupported = mConferenceHost == null ? false :
- mConferenceHost.isCarrierVideoConferencingSupported();
- setConnectionCapabilities(applyHostCapabilities(capabilites, connectionCapabilities,
- isVideoConferencingSupported));
- }
+ @Override
+ public void onExtrasRemoved(Connection c, List<String> keys) {
+ Log.v(this, "onExtrasRemoved: c=" + c + " key=" + keys);
+ removeExtras(keys);
+ }
- @Override
- public void onConnectionPropertiesChanged(Connection c, int connectionProperties) {
- Log.d(this, "onConnectionPropertiesChanged: Connection: %s," +
- " connectionProperties: %s", c, connectionProperties);
- int properties = ImsConference.this.getConnectionProperties();
- setConnectionProperties(applyHostProperties(properties, connectionProperties));
- }
+ @Override
+ public void onConnectionEvent(Connection c, String event, Bundle extras) {
+ if (Connection.EVENT_MERGE_START.equals(event)) {
+ // Do not pass a merge start event on the underlying host connection; only
+ // indicate a merge has started on the connections which are merged into a
+ // conference.
+ return;
+ }
- @Override
- public void onStatusHintsChanged(Connection c, StatusHints statusHints) {
- Log.v(this, "onStatusHintsChanged");
- updateStatusHints();
- }
+ sendConnectionEvent(event, extras);
+ }
- @Override
- public void onExtrasChanged(Connection c, Bundle extras) {
- Log.v(this, "onExtrasChanged: c=" + c + " Extras=" + extras);
- putExtras(extras);
- }
+ @Override
+ public void onOriginalConnectionConfigured(TelephonyConnection c) {
+ if (c == mConferenceHost) {
+ handleOriginalConnectionChange();
+ }
+ }
- @Override
- public void onExtrasRemoved(Connection c, List<String> keys) {
- Log.v(this, "onExtrasRemoved: c=" + c + " key=" + keys);
- removeExtras(keys);
- }
+ /**
+ * 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) {
- @Override
- public void onConnectionEvent(Connection c, String event, Bundle extras) {
- if (Connection.EVENT_MERGE_START.equals(event)) {
- // Do not pass a merge start event on the underlying host connection; we only
- // indicate a merge has started on the connections which are merged into a
- // conference.
- return;
- }
- sendConnectionEvent(event, extras);
- }
- };
+ if (c == null || participants == null) {
+ return;
+ }
+ Log.v(this, "onConferenceParticipantsChanged: %d participants",
+ participants.size());
+ TelephonyConnection telephonyConnection = (TelephonyConnection) c;
+ handleConferenceParticipantsUpdate(telephonyConnection, participants);
+ }
+ };
/**
* The telephony connection service; used to add new participant connections to Telecom.
@@ -447,7 +424,7 @@
* Invoked when the Conference and all its {@link Connection}s should be disconnected.
* <p>
* Hangs up the call via the conference host connection. When the host connection has been
- * successfully disconnected, the {@link #mConferenceHostListener} listener receives an
+ * successfully disconnected, the {@link #mTelephonyConnectionListener} listener receives an
* {@code onDestroyed} event, which triggers the conference participant connections to be
* disconnected.
*/
@@ -702,7 +679,6 @@
setConnectionTime(mConferenceHost.getConnectTimeMillis());
}
- mConferenceHost.addConnectionListener(mConferenceHostListener);
mConferenceHost.addTelephonyConnectionListener(mTelephonyConnectionListener);
setConnectionCapabilities(applyHostCapabilities(getConnectionCapabilities(),
mConferenceHost.getConnectionCapabilities(),
@@ -804,6 +780,13 @@
"handleConferenceParticipantsUpdate: updateState, participant = %s",
participant);
connection.updateState(participant.getState());
+ if (participant.getState() == Connection.STATE_DISCONNECTED) {
+ /**
+ * Per {@link ConferenceParticipantConnection#updateState(int)}, we will
+ * destroy the connection when its disconnected.
+ */
+ handleConnectionDestruction(connection);
+ }
connection.setVideoState(parent.getVideoState());
}
}
@@ -817,6 +800,13 @@
newParticipant.getHandle(),
newParticipant.getEndpoint()));
connection.updateState(newParticipant.getState());
+ /**
+ * Per {@link ConferenceParticipantConnection#updateState(int)}, we will
+ * destroy the connection when its disconnected.
+ */
+ if (newParticipant.getState() == Connection.STATE_DISCONNECTED) {
+ handleConnectionDestruction(connection);
+ }
connection.setVideoState(parent.getVideoState());
}
}
@@ -832,9 +822,8 @@
if (!participantUserEntities.contains(entry.getKey())) {
ConferenceParticipantConnection participant = entry.getValue();
participant.setDisconnected(new DisconnectCause(DisconnectCause.CANCELED));
- participant.removeConnectionListener(mParticipantListener);
mTelephonyConnectionService.removeConnection(participant);
- removeConnection(participant);
+ removeTelephonyConnection(participant);
entryIterator.remove();
oldParticipantsRemoved = true;
}
@@ -951,9 +940,8 @@
// again anyways.
entry.setDisconnected(new DisconnectCause(DisconnectCause.CANCELED,
DisconnectCause.REASON_EMULATING_SINGLE_CALL));
- entry.removeConnectionListener(mParticipantListener);
mTelephonyConnectionService.removeConnection(entry);
- removeConnection(entry);
+ removeTelephonyConnection(entry);
valueIterator.remove();
}
@@ -985,7 +973,6 @@
ConferenceParticipantConnection connection = new ConferenceParticipantConnection(
parent.getOriginalConnection(), participant,
!isConferenceHost() /* isRemotelyHosted */);
- connection.addConnectionListener(mParticipantListener);
if (participant.getConnectTime() == 0) {
connection.setConnectTimeMillis(parent.getConnectTimeMillis());
connection.setConnectionStartElapsedRealTime(parent.getConnectElapsedTimeMillis());
@@ -1007,7 +994,7 @@
mTelephonyConnectionService.addExistingConnection(mConferenceHostPhoneAccountHandle,
connection, this);
- addConnection(connection);
+ addTelephonyConnection(connection);
}
/**
@@ -1018,7 +1005,6 @@
private void removeConferenceParticipant(ConferenceParticipantConnection participant) {
Log.i(this, "removeConferenceParticipant: %s", participant);
- participant.removeConnectionListener(mParticipantListener);
synchronized(mUpdateSyncRoot) {
mConferenceParticipantConnections.remove(new Pair<>(participant.getUserEntity(),
participant.getEndpoint()));
@@ -1036,12 +1022,12 @@
for (ConferenceParticipantConnection connection :
mConferenceParticipantConnections.values()) {
- connection.removeConnectionListener(mParticipantListener);
// Mark disconnect cause as cancelled to ensure that the call is not logged in the
// call log.
connection.setDisconnected(new DisconnectCause(DisconnectCause.CANCELED));
mTelephonyConnectionService.removeConnection(connection);
connection.destroy();
+ handleConnectionDestruction(connection);
}
mConferenceParticipantConnections.clear();
}
@@ -1154,7 +1140,7 @@
mConferenceHost.isOutgoingCall());
// This is a newly created conference connection as a result of SRVCC
c.setConferenceSupported(true);
- c.setConnectionProperties(
+ c.setTelephonyConnectionProperties(
c.getConnectionProperties() | Connection.PROPERTY_IS_DOWNGRADED_CONFERENCE);
c.updateState();
// Copy the connect time from the conferenceHost
@@ -1163,12 +1149,11 @@
mTelephonyConnectionService.addExistingConnection(phoneAccountHandle, c);
mTelephonyConnectionService.addConnectionToConferenceController(c);
} // CDMA case not applicable for SRVCC
- mConferenceHost.removeConnectionListener(mConferenceHostListener);
mConferenceHost.removeTelephonyConnectionListener(mTelephonyConnectionListener);
mConferenceHost = null;
setDisconnected(new DisconnectCause(DisconnectCause.OTHER));
disconnectConferenceParticipants();
- destroy();
+ destroyTelephonyConference();
}
updateStatusHints();
@@ -1207,7 +1192,7 @@
}
setDisconnected(disconnectCause);
disconnectConferenceParticipants();
- destroy();
+ destroyTelephonyConference();
break;
case Connection.STATE_ACTIVE:
setActive();
@@ -1338,4 +1323,15 @@
public boolean isEmulatingSinglePartyCall() {
return mIsEmulatingSinglePartyCall;
}
+
+ /**
+ * Handles destruction of a {@link ConferenceParticipantConnection}.
+ * We remove the participant from the list of tracked participants in the conference and
+ * update whether the conference can be managed.
+ * @param participant the conference participant.
+ */
+ private void handleConnectionDestruction(ConferenceParticipantConnection participant) {
+ removeConferenceParticipant(participant);
+ updateManageConference();
+ }
}
diff --git a/src/com/android/services/telephony/ImsConferenceController.java b/src/com/android/services/telephony/ImsConferenceController.java
index b193c7f..315aaad 100644
--- a/src/com/android/services/telephony/ImsConferenceController.java
+++ b/src/com/android/services/telephony/ImsConferenceController.java
@@ -66,13 +66,7 @@
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.
- */
- private final Connection.Listener mConnectionListener = new Connection.Listener() {
@Override
public void onStateChanged(Connection c, int state) {
Log.v(this, "onStateChanged: %s", Log.pii(c.getAddress()));
@@ -151,7 +145,6 @@
}
mTelephonyConnections.add(connection);
- connection.addConnectionListener(mConnectionListener);
connection.addTelephonyConnectionListener(mTelephonyConnectionListener);
recalculateConference();
}
@@ -179,7 +172,6 @@
Log.v(this, "remove connection: %s", connection);
}
- connection.removeConnectionListener(mConnectionListener);
if (connection instanceof TelephonyConnection) {
TelephonyConnection telephonyConnection = (TelephonyConnection) connection;
telephonyConnection.removeTelephonyConnectionListener(mTelephonyConnectionListener);
@@ -395,13 +387,11 @@
// Cleanup TelephonyConnection which backed the original connection and remove from telecom.
// 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,
+ connection.setTelephonyConnectionDisconnected(new DisconnectCause(DisconnectCause.OTHER,
android.telephony.DisconnectCause.toString(
android.telephony.DisconnectCause.IMS_MERGED_SUCCESSFULLY)));
- connection.destroy();
+ connection.close();
mImsConferences.add(conference);
// If one of the participants failed to join the conference, recalculate will set the
// conferenceable connections for the conference to show merge calls option.
diff --git a/src/com/android/services/telephony/TelephonyConference.java b/src/com/android/services/telephony/TelephonyConference.java
index c66d6f2..afbe89d 100644
--- a/src/com/android/services/telephony/TelephonyConference.java
+++ b/src/com/android/services/telephony/TelephonyConference.java
@@ -16,7 +16,6 @@
package com.android.services.telephony;
-import android.telecom.Conference;
import android.telecom.Connection;
import android.telecom.PhoneAccountHandle;
@@ -30,7 +29,7 @@
* TelephonyConnection-based conference call for GSM conferences and IMS conferences (which may
* be either GSM-based or CDMA-based).
*/
-public class TelephonyConference extends Conference implements Holdable {
+public class TelephonyConference extends TelephonyConferenceBase implements Holdable {
private boolean mIsHoldable;
diff --git a/src/com/android/services/telephony/TelephonyConferenceBase.java b/src/com/android/services/telephony/TelephonyConferenceBase.java
new file mode 100644
index 0000000..31d0f56
--- /dev/null
+++ b/src/com/android/services/telephony/TelephonyConferenceBase.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2019 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.services.telephony;
+
+import android.annotation.NonNull;
+import android.telecom.Conference;
+import android.telecom.Connection;
+import android.telecom.PhoneAccountHandle;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Base class for the various Telephony {@link Conference} implementations ({@link CdmaConference},
+ * {@link TelephonyConference}, and {@link ImsConference}). Adds some common listener code which
+ * all of these conferences use.
+ */
+public class TelephonyConferenceBase extends Conference {
+ /**
+ * Listener for conference events.
+ */
+ public abstract static class TelephonyConferenceListener {
+ /**
+ * Listener called when a connection is added or removed from a conference.
+ * @param connection The connection.
+ */
+ public void onConferenceMembershipChanged(Connection connection) {};
+ }
+
+ private final Set<TelephonyConferenceListener> mListeners = Collections.newSetFromMap(
+ new ConcurrentHashMap<>(8, 0.9f, 1));
+
+ /**
+ * Adds a listener to this conference.
+ * @param listener The listener.
+ */
+ public void addListener(@NonNull TelephonyConferenceListener listener) {
+ mListeners.add(listener);
+ }
+
+ /**
+ * Removes a listener from this conference.
+ * @param listener The listener.
+ */
+ public void removeListener(@NonNull TelephonyConferenceListener listener) {
+ mListeners.remove(listener);
+ }
+
+ /**
+ * Constructs a new Conference with a mandatory {@link PhoneAccountHandle}
+ *
+ * @param phoneAccount The {@code PhoneAccountHandle} associated with the conference.
+ */
+ public TelephonyConferenceBase(PhoneAccountHandle phoneAccount) {
+ super(phoneAccount);
+ }
+
+ /**
+ * Adds a connection to this {@link Conference}.
+ * <p>
+ * Should be used in place of {@link Conference#addConnection(Connection)} to ensure
+ * {@link TelephonyConferenceListener}s are informed of the change.
+ *
+ * @param connection The connection.
+ */
+ public void addTelephonyConnection(@NonNull Connection connection) {
+ addConnection(connection);
+ notifyConferenceMembershipChanged(connection);
+ }
+
+ /**
+ * Removes a {@link Connection} from this {@link Conference}.
+ * <p>
+ * Should be used instead of {@link Conference#removeConnection(Connection)} to ensure
+ * {@link TelephonyConferenceListener}s are notified of the change.
+ *
+ * @param connection The connection.
+ */
+ public void removeTelephonyConnection(@NonNull Connection connection) {
+ removeConnection(connection);
+ notifyConferenceMembershipChanged(connection);
+ }
+
+ /**
+ * Destroys the current {@link Conference} and notifies {@link TelephonyConferenceListener}s of
+ * the change to conference membership.
+ * <p>
+ * Should be used instead of {@link Conference#destroy()} to ensure telephony listeners are
+ * notified.
+ */
+ public void destroyTelephonyConference() {
+ // Conference#removeConnection modifies the list of participants, so we need to use an
+ // iterator here to ensure all participants are removed.
+ // Technically Conference#destroy does this, but we want to notify listeners of the state
+ // change so we'll do it here first.
+ Iterator<Connection> connectionIterator = getConnections().iterator();
+ while (connectionIterator.hasNext()) {
+ removeTelephonyConnection(connectionIterator.next());
+ }
+ destroy();
+ }
+
+ /**
+ * Notifies {@link TelephonyConferenceListener}s of a connection being added or removed from
+ * the conference.
+ * @param connection The conference.
+ */
+ private void notifyConferenceMembershipChanged(@NonNull Connection connection) {
+ for (TelephonyConferenceListener listener : mListeners) {
+ listener.onConferenceMembershipChanged(connection);
+ }
+ }
+}
diff --git a/src/com/android/services/telephony/TelephonyConferenceController.java b/src/com/android/services/telephony/TelephonyConferenceController.java
index e9eef46..95281b3 100644
--- a/src/com/android/services/telephony/TelephonyConferenceController.java
+++ b/src/com/android/services/telephony/TelephonyConferenceController.java
@@ -41,25 +41,26 @@
final class TelephonyConferenceController {
private static final int TELEPHONY_CONFERENCE_MAX_SIZE = 5;
- private final Connection.Listener mConnectionListener = new Connection.Listener() {
- @Override
- public void onStateChanged(Connection c, int state) {
- Log.v(this, "onStateChange triggered in Conf Controller : connection = "+ c
- + " state = " + state);
- recalculate();
- }
+ private final TelephonyConnection.TelephonyConnectionListener mTelephonyConnectionListener =
+ new TelephonyConnection.TelephonyConnectionListener() {
+ @Override
+ public void onStateChanged(Connection c, int state) {
+ Log.v(this, "onStateChange triggered in Conf Controller : connection = " + c
+ + " state = " + state);
+ recalculate();
+ }
- /** ${inheritDoc} */
- @Override
- public void onDisconnected(Connection c, DisconnectCause disconnectCause) {
- recalculate();
- }
+ @Override
+ public void onDisconnected(Connection c, DisconnectCause disconnectCause) {
+ recalculate();
+ }
- @Override
- public void onDestroyed(Connection connection) {
- remove(connection);
- }
- };
+ @Override
+ public void onDestroyed(Connection connection) {
+ // Only TelephonyConnections are added.
+ remove((TelephonyConnection) connection);
+ }
+ };
/** The known connections. */
private final List<TelephonyConnection> mTelephonyConnections = new ArrayList<>();
@@ -85,18 +86,18 @@
return;
}
mTelephonyConnections.add(connection);
- connection.addConnectionListener(mConnectionListener);
+ connection.addTelephonyConnectionListener(mTelephonyConnectionListener);
recalculate();
}
- void remove(Connection connection) {
+ void remove(TelephonyConnection connection) {
if (!mTelephonyConnections.contains(connection)) {
// Debug only since TelephonyConnectionService tries to clean up the connections tracked
// when the original connection changes. It does this proactively.
Log.d(this, "remove - connection not tracked; connection=%s", connection);
return;
}
- connection.removeConnectionListener(mConnectionListener);
+ connection.removeTelephonyConnectionListener(mTelephonyConnectionListener);
mTelephonyConnections.remove(connection);
recalculate();
}
@@ -219,7 +220,7 @@
// No more connections are conferenced, destroy any existing conference.
if (mTelephonyConference != null) {
Log.d(this, "with a conference to destroy!");
- mTelephonyConference.destroy();
+ mTelephonyConference.destroyTelephonyConference();
mTelephonyConference = null;
}
} else {
@@ -229,7 +230,7 @@
for (Connection connection : existingConnections) {
if (connection instanceof TelephonyConnection &&
!conferencedConnections.contains(connection)) {
- mTelephonyConference.removeConnection(connection);
+ mTelephonyConference.removeTelephonyConnection(connection);
}
}
if (allConnInService) {
@@ -237,7 +238,7 @@
// Add any new ones
for (Connection connection : conferencedConnections) {
if (!existingConnections.contains(connection)) {
- mTelephonyConference.addConnection(connection);
+ mTelephonyConference.addTelephonyConnection(connection);
}
}
} else {
@@ -262,7 +263,7 @@
for (Connection connection : conferencedConnections) {
Log.d(this, "Adding a connection to a conference call: %s %s",
mTelephonyConference, connection);
- mTelephonyConference.addConnection(connection);
+ mTelephonyConference.addTelephonyConnection(connection);
}
mTelephonyConference.updateCallRadioTechAfterCreation();
mConnectionService.addConference(mTelephonyConference);
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index 7f846a9..c1d2995 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -16,6 +16,8 @@
package com.android.services.telephony;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Context;
import android.graphics.drawable.Icon;
import android.net.Uri;
@@ -186,7 +188,7 @@
case MSG_SET_VIDEO_STATE:
int videoState = (int) msg.obj;
- setVideoState(videoState);
+ setTelephonyVideoState(videoState);
// A change to the video state of the call can influence whether or not it
// can be part of a conference, whether another call can be added, and
@@ -198,7 +200,7 @@
case MSG_SET_VIDEO_PROVIDER:
VideoProvider videoProvider = (VideoProvider) msg.obj;
- setVideoProvider(videoProvider);
+ setTelephonyVideoProvider(videoProvider);
break;
case MSG_SET_AUDIO_QUALITY:
@@ -238,9 +240,9 @@
// If starting the hold tone, send a connection event to Telecom which will
// cause it to play the on hold tone.
if (playTone) {
- sendConnectionEvent(EVENT_ON_HOLD_TONE_START, null);
+ sendTelephonyConnectionEvent(EVENT_ON_HOLD_TONE_START, null);
} else {
- sendConnectionEvent(EVENT_ON_HOLD_TONE_END, null);
+ sendTelephonyConnectionEvent(EVENT_ON_HOLD_TONE_END, null);
}
}
break;
@@ -285,7 +287,7 @@
case MSG_ON_CONNECTION_EVENT:
SomeArgs args = (SomeArgs) msg.obj;
try {
- sendConnectionEvent((String) args.arg1, (Bundle) args.arg2);
+ sendTelephonyConnectionEvent((String) args.arg1, (Bundle) args.arg2);
} finally {
args.recycle();
@@ -304,7 +306,7 @@
ssn.code);
if (ssn.notificationType == SuppServiceNotification.NOTIFICATION_TYPE_CODE_1
&& ssn.code == SuppServiceNotification.CODE_1_CALL_FORWARDED) {
- sendConnectionEvent(TelephonyManager.EVENT_CALL_FORWARDED, null);
+ sendTelephonyConnectionEvent(TelephonyManager.EVENT_CALL_FORWARDED, null);
}
sendSuppServiceNotificationEvent(ssn.notificationType, ssn.code);
}
@@ -322,7 +324,8 @@
extras.putInt(TelephonyManager.EXTRA_NOTIFICATION_CODE, code);
extras.putCharSequence(TelephonyManager.EXTRA_NOTIFICATION_MESSAGE,
getSuppServiceMessage(type, code));
- sendConnectionEvent(TelephonyManager.EVENT_SUPPLEMENTARY_SERVICE_NOTIFICATION, extras);
+ sendTelephonyConnectionEvent(TelephonyManager.EVENT_SUPPLEMENTARY_SERVICE_NOTIFICATION,
+ extras);
}
/**
@@ -423,6 +426,20 @@
List<ConferenceParticipant> participants) {}
public void onConferenceStarted() {}
public void onConferenceSupportedChanged(Connection c, boolean isConferenceSupported) {}
+
+ public void onConnectionCapabilitiesChanged(Connection c, int connectionCapabilities) {}
+ public void onConnectionEvent(Connection c, String event, Bundle extras) {}
+ public void onConnectionPropertiesChanged(Connection c, int connectionProperties) {}
+ public void onExtrasChanged(Connection c, Bundle extras) {}
+ public void onExtrasRemoved(Connection c, List<String> keys) {}
+ public void onStateChanged(android.telecom.Connection c, int state) {}
+ public void onStatusHintsChanged(Connection c, StatusHints statusHints) {}
+ public void onDestroyed(Connection c) {}
+ public void onDisconnected(android.telecom.Connection c,
+ android.telecom.DisconnectCause disconnectCause) {}
+ public void onVideoProviderChanged(android.telecom.Connection c,
+ Connection.VideoProvider videoProvider) {}
+ public void onVideoStateChanged(android.telecom.Connection c, int videoState) {}
}
private final PostDialListener mPostDialListener = new PostDialListener() {
@@ -556,7 +573,7 @@
// Inform the InCallService of the fact that the call pull failed (it may choose to
// display a message informing the user of the pull failure).
- sendConnectionEvent(Connection.EVENT_CALL_PULL_FAILED, null);
+ sendTelephonyConnectionEvent(Connection.EVENT_CALL_PULL_FAILED, null);
// Swap the ImsPhoneConnection we used to do the pull for the ImsExternalConnection
// which originally represented the call.
@@ -571,7 +588,7 @@
*/
@Override
public void onHandoverToWifiFailed() {
- sendConnectionEvent(TelephonyManager.EVENT_HANDOVER_TO_WIFI_FAILED, null);
+ sendTelephonyConnectionEvent(TelephonyManager.EVENT_HANDOVER_TO_WIFI_FAILED, null);
}
/**
@@ -1086,6 +1103,7 @@
if (getConnectionCapabilities() != newCapabilities) {
setConnectionCapabilities(newCapabilities);
+ notifyConnectionCapabilitiesChanged(newCapabilities);
}
}
@@ -1122,10 +1140,15 @@
isNetworkIdentifiedEmergencyCall());
if (getConnectionProperties() != newProperties) {
- setConnectionProperties(newProperties);
+ setTelephonyConnectionProperties(newProperties);
}
}
+ public void setTelephonyConnectionProperties(int newProperties) {
+ setConnectionProperties(newProperties);
+ notifyConnectionPropertiesChanged(newProperties);
+ }
+
protected final void updateAddress() {
updateConnectionCapabilities();
updateConnectionProperties();
@@ -1200,11 +1223,11 @@
mOriginalConnection.addListener(mOriginalConnectionListener);
// Set video state and capabilities
- setVideoState(mOriginalConnection.getVideoState());
+ setTelephonyVideoState(mOriginalConnection.getVideoState());
setOriginalConnectionCapabilities(mOriginalConnection.getConnectionCapabilities());
setIsNetworkIdentifiedEmergencyCall(mOriginalConnection.isNetworkIdentifiedEmergencyCall());
setAudioModeIsVoip(mOriginalConnection.getAudioModeIsVoip());
- setVideoProvider(mOriginalConnection.getVideoProvider());
+ setTelephonyVideoProvider(mOriginalConnection.getVideoProvider());
setAudioQuality(mOriginalConnection.getAudioQuality());
setTechnologyTypeExtra();
@@ -1239,8 +1262,8 @@
} else {
extrasToRemove.add(Connection.EXTRA_DISABLE_ADD_CALL);
}
- putExtras(extrasToPut);
- removeExtras(extrasToRemove);
+ putTelephonyExtras(extrasToPut);
+ removeTelephonyExtras(extrasToRemove);
// updateState can set mOriginalConnection to null if its state is DISCONNECTED, so this
// should be executed *after* the above setters have run.
@@ -1290,7 +1313,7 @@
newExtras = new Bundle();
}
newExtras.putInt(TelecomManager.EXTRA_CALL_TECHNOLOGY_TYPE, getPhone().getPhoneType());
- putExtras(newExtras);
+ putTelephonyExtras(newExtras);
}
}
@@ -1301,7 +1324,7 @@
newExtras = new Bundle();
}
newExtras.putBoolean(Connection.EXTRA_DISABLE_ADD_CALL, true);
- putExtras(newExtras);
+ putTelephonyExtras(newExtras);
} else {
removeExtras(Connection.EXTRA_DISABLE_ADD_CALL);
}
@@ -1483,7 +1506,7 @@
// There are a few cases where mOriginalConnection has not been set yet. For
// example, when the radio has to be turned on to make an emergency call,
// mOriginalConnection could not be set for many seconds.
- setDisconnected(DisconnectCauseUtil.toTelecomDisconnectCause(
+ setTelephonyConnectionDisconnected(DisconnectCauseUtil.toTelecomDisconnectCause(
android.telephony.DisconnectCause.LOCAL,
"Local Disconnect before connection established."));
close();
@@ -1604,7 +1627,7 @@
}
// Ensure extras are propagated to Telecom.
- putExtras(mOriginalConnectionExtras);
+ putTelephonyExtras(mOriginalConnectionExtras);
} else {
Log.d(this, "Extras update not required");
}
@@ -1673,19 +1696,19 @@
setActiveInternal();
break;
case HOLDING:
- setOnHold();
+ setTelephonyConnectionOnHold();
break;
case DIALING:
case ALERTING:
if (mOriginalConnection != null && mOriginalConnection.isPulledCall()) {
- setPulling();
+ setTelephonyConnectionPulling();
} else {
- setDialing();
+ setTelephonyConnectionDialing();
}
break;
case INCOMING:
case WAITING:
- setRinging();
+ setTelephonyConnectionRinging();
break;
case DISCONNECTED:
if (shouldTreatAsEmergencyCall()
@@ -1706,11 +1729,12 @@
preciseDisconnectCause =
mOriginalConnection.getPreciseDisconnectCause();
}
- setDisconnected(DisconnectCauseUtil.toTelecomDisconnectCause(
- mOriginalConnection.getDisconnectCause(),
- preciseDisconnectCause,
- mOriginalConnection.getVendorDisconnectCause(),
- getPhone().getPhoneId()));
+ setTelephonyConnectionDisconnected(
+ DisconnectCauseUtil.toTelecomDisconnectCause(
+ mOriginalConnection.getDisconnectCause(),
+ preciseDisconnectCause,
+ mOriginalConnection.getVendorDisconnectCause(),
+ getPhone().getPhoneId()));
close();
}
break;
@@ -1800,13 +1824,14 @@
}
}
}
- setActive();
+ setTelephonyConnectionActive();
}
- protected void close() {
+ public void close() {
Log.v(this, "close");
clearOriginalConnection();
destroy();
+ notifyDestroyed();
}
/**
@@ -2157,13 +2182,13 @@
: R.string.status_hint_label_wifi_call;
Context context = getPhone().getContext();
- setStatusHints(new StatusHints(
+ setTelephonyStatusHints(new StatusHints(
context.getString(labelId),
Icon.createWithResource(
context, R.drawable.ic_signal_wifi_4_bar_24dp),
null /* extras */));
} else {
- setStatusHints(null);
+ setTelephonyStatusHints(null);
}
}
@@ -2391,12 +2416,153 @@
}
/**
- * Notifies listeners of a change to conference participant(s).
+ * Set this {@link TelephonyConnection} to an active state.
+ * <p>
+ * Note: This should be used instead of {@link #setActive()} to ensure listeners are notified.
+ */
+ public void setTelephonyConnectionActive() {
+ setActive();
+ notifyStateChanged(getState());
+ }
+
+ /**
+ * Set this {@link TelephonyConnection} to a ringing state.
+ * <p>
+ * Note: This should be used instead of {@link #setRinging()} to ensure listeners are notified.
+ */
+ public void setTelephonyConnectionRinging() {
+ setRinging();
+ notifyStateChanged(getState());
+ }
+
+ /**
+ * Set this {@link TelephonyConnection} to an initializing state.
+ * <p>
+ * Note: This should be used instead of {@link #setInitializing()} to ensure listeners are
+ * notified.
+ */
+ public void setTelephonyConnectionInitializing() {
+ setInitializing();
+ notifyStateChanged(getState());
+ }
+
+ /**
+ * Set this {@link TelephonyConnection} to a dialing state.
+ * <p>
+ * Note: This should be used instead of {@link #setDialing()} to ensure listeners are notified.
+ */
+ public void setTelephonyConnectionDialing() {
+ setDialing();
+ notifyStateChanged(getState());
+ }
+
+ /**
+ * Set this {@link TelephonyConnection} to a pulling state.
+ * <p>
+ * Note: This should be used instead of {@link #setPulling()} to ensure listeners are notified.
+ */
+ public void setTelephonyConnectionPulling() {
+ setPulling();
+ notifyStateChanged(getState());
+ }
+
+ /**
+ * Set this {@link TelephonyConnection} to a held state.
+ * <p>
+ * Note: This should be used instead of {@link #setOnHold()} to ensure listeners are notified.
+ */
+ public void setTelephonyConnectionOnHold() {
+ setOnHold();
+ notifyStateChanged(getState());
+ }
+
+ /**
+ * Set this {@link TelephonyConnection} to a held state.
+ * <p>
+ * Note: This should be used instead of
+ * {@link #setDisconnected(android.telecom.DisconnectCause)} to ensure listeners are notified.
+ */
+ public void setTelephonyConnectionDisconnected(@NonNull
+ android.telecom.DisconnectCause disconnectCause) {
+ setDisconnected(disconnectCause);
+ notifyDisconnected(disconnectCause);
+ notifyStateChanged(getState());
+ }
+
+ /**
+ * Sends a connection event for this {@link TelephonyConnection}.
+ * <p>
+ * Note: This should be used instead of {@link #sendConnectionEvent(String, Bundle)} to ensure
+ * listeners are notified.
+ */
+ public void sendTelephonyConnectionEvent(@NonNull String event, @Nullable Bundle extras) {
+ sendConnectionEvent(event, extras);
+ notifyTelephonyConnectionEvent(event, extras);
+ }
+
+ /**
+ * Sets the extras associated with this {@link TelephonyConnection}.
+ * <p>
+ * Note: This should be used instead of {@link #putExtras(Bundle)} to ensure listeners are
+ * notified.
+ */
+ public void putTelephonyExtras(@NonNull Bundle extras) {
+ putExtras(extras);
+ notifyPutExtras(extras);
+ }
+
+ /**
+ * Removes the specified extras associated with this {@link TelephonyConnection}.
+ * <p>
+ * Note: This should be used instead of {@link #removeExtras(String...)} to ensure listeners are
+ * notified.
+ */
+ public void removeTelephonyExtras(@NonNull List<String> keys) {
+ removeExtras(keys);
+ notifyRemoveExtras(keys);
+ }
+
+ /**
+ * Sets the video state associated with this {@link TelephonyConnection}.
+ * <p>
+ * Note: This should be used instead of {@link #setVideoState(int)} to ensure listeners are
+ * notified.
+ */
+ public void setTelephonyVideoState(@VideoProfile.VideoState int videoState) {
+ setVideoState(videoState);
+ notifyVideoStateChanged(videoState);
+ }
+
+ /**
+ * Sets the video provider associated with this {@link TelephonyConnection}.
+ * <p>
+ * Note: This should be used instead of {@link #setVideoProvider(VideoProvider)} to ensure
+ * listeners are notified.
+ */
+ public void setTelephonyVideoProvider(@Nullable VideoProvider videoProvider) {
+ setVideoProvider(videoProvider);
+ notifyVideoProviderChanged(videoProvider);
+ }
+
+ /**
+ * Sets the status hints associated with this {@link TelephonyConnection}.
+ * <p>
+ * Note: This should be used instead of {@link #setStatusHints(StatusHints)} to ensure listeners
+ * are notified.
+ */
+ public void setTelephonyStatusHints(@Nullable StatusHints statusHints) {
+ setStatusHints(statusHints);
+ notifyStatusHintsChanged(statusHints);
+ }
+
+ /**
+ * Notifies {@link TelephonyConnectionListener}s of a change to conference participant data
+ * received via the {@link ImsConference} (i.e. conference event package).
*
* @param conferenceParticipants The participants.
*/
- protected final void updateConferenceParticipants(
- List<ConferenceParticipant> conferenceParticipants) {
+ private void updateConferenceParticipants(
+ @NonNull List<ConferenceParticipant> conferenceParticipants) {
for (TelephonyConnectionListener l : mTelephonyListeners) {
l.onConferenceParticipantsChanged(this, conferenceParticipants);
}
@@ -2405,7 +2571,6 @@
/**
* Called by a {@link ConnectionService} to notify Telecom that a {@link Conference#onMerge()}
* operation has started.
- * <p>
*/
protected void notifyConferenceStarted() {
for (TelephonyConnectionListener l : mTelephonyListeners) {
@@ -2414,14 +2579,126 @@
}
/**
- * Notifies listeners when a change has occurred to the Connection which impacts its ability to
- * be a part of a conference call.
+ * Notifies {@link TelephonyConnectionListener}s 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) {
+ private void notifyConferenceSupportedChanged(boolean isConferenceSupported) {
for (TelephonyConnectionListener l : mTelephonyListeners) {
l.onConferenceSupportedChanged(this, isConferenceSupported);
}
}
+
+ /**
+ * Notifies {@link TelephonyConnectionListener}s of changes to the connection capabilities.
+ * @param newCapabilities the new capabilities.
+ */
+ private void notifyConnectionCapabilitiesChanged(int newCapabilities) {
+ for (TelephonyConnectionListener listener : mTelephonyListeners) {
+ listener.onConnectionCapabilitiesChanged(this, newCapabilities);
+ }
+ }
+
+ /**
+ * Notifies {@link TelephonyConnectionListener}s of changes to the connection properties.
+ * @param newProperties the new properties.
+ */
+ private void notifyConnectionPropertiesChanged(int newProperties) {
+ for (TelephonyConnectionListener listener : mTelephonyListeners) {
+ listener.onConnectionPropertiesChanged(this, newProperties);
+ }
+ }
+
+ /**
+ * Notifies {@link TelephonyConnectionListener}s when a connection is destroyed.
+ */
+ private void notifyDestroyed() {
+ for (TelephonyConnectionListener listener : mTelephonyListeners) {
+ listener.onDestroyed(this);
+ }
+ }
+
+ /**
+ * Notifies {@link TelephonyConnectionListener}s when a connection disconnects.
+ * @param cause The disconnect cause.
+ */
+ private void notifyDisconnected(android.telecom.DisconnectCause cause) {
+ for (TelephonyConnectionListener listener : mTelephonyListeners) {
+ listener.onDisconnected(this, cause);
+ }
+ }
+
+ /**
+ * Notifies {@link TelephonyConnectionListener}s of connection state changes.
+ * @param newState The new state.
+ */
+ private void notifyStateChanged(int newState) {
+ for (TelephonyConnectionListener listener : mTelephonyListeners) {
+ listener.onStateChanged(this, newState);
+ }
+ }
+
+ /**
+ * Notifies {@link TelephonyConnectionListener}s of telephony connection events.
+ * @param event The event.
+ * @param extras Any extras.
+ */
+ private void notifyTelephonyConnectionEvent(String event, Bundle extras) {
+ for (TelephonyConnectionListener listener : mTelephonyListeners) {
+ listener.onConnectionEvent(this, event, extras);
+ }
+ }
+
+ /**
+ * Notifies {@link TelephonyConnectionListener}s when extras are added to the connection.
+ * @param extras The new extras.
+ */
+ private void notifyPutExtras(Bundle extras) {
+ for (TelephonyConnectionListener listener : mTelephonyListeners) {
+ listener.onExtrasChanged(this, extras);
+ }
+ }
+
+ /**
+ * Notifies {@link TelephonyConnectionListener}s when extra keys are removed from a connection.
+ * @param keys The removed keys.
+ */
+ private void notifyRemoveExtras(List<String> keys) {
+ for (TelephonyConnectionListener listener : mTelephonyListeners) {
+ listener.onExtrasRemoved(this, keys);
+ }
+ }
+
+ /**
+ * Notifies {@link TelephonyConnectionListener}s of a change to the video state of a connection.
+ * @param videoState The new video state.
+ */
+ private void notifyVideoStateChanged(@VideoProfile.VideoState int videoState) {
+ for (TelephonyConnectionListener listener : mTelephonyListeners) {
+ listener.onVideoStateChanged(this, videoState);
+ }
+ }
+
+ /**
+ * Notifies {@link TelephonyConnectionListener}s of changes to the video provider for a
+ * connection.
+ * @param videoProvider The new video provider.
+ */
+ private void notifyVideoProviderChanged(VideoProvider videoProvider) {
+ for (TelephonyConnectionListener listener : mTelephonyListeners) {
+ listener.onVideoProviderChanged(this, videoProvider);
+ }
+ }
+
+ /**
+ * Notifies {@link TelephonyConnectionListener}s of changes to the status hints for a
+ * connection.
+ * @param statusHints The new status hints.
+ */
+ private void notifyStatusHintsChanged(StatusHints statusHints) {
+ for (TelephonyConnectionListener listener : mTelephonyListeners) {
+ listener.onStatusHintsChanged(this, statusHints);
+ }
+ }
}
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 5e3a899..7b55bfc 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -103,11 +103,11 @@
}
@Override
public void addConference(TelephonyConference mTelephonyConference) {
- TelephonyConnectionService.this.addConference(mTelephonyConference);
+ TelephonyConnectionService.this.addTelephonyConference(mTelephonyConference);
}
@Override
public void addConference(ImsConference mImsConference) {
- TelephonyConnectionService.this.addConference(mImsConference);
+ TelephonyConnectionService.this.addTelephonyConference(mImsConference);
}
@Override
public void removeConnection(Connection connection) {
@@ -129,11 +129,9 @@
public void addConnectionToConferenceController(TelephonyConnection connection) {
TelephonyConnectionService.this.addConnectionToConferenceController(connection);
}
- };
- private final Connection.Listener mConnectionListener = new Connection.Listener() {
@Override
- public void onConferenceChanged(Connection connection, Conference conference) {
+ public void onConferenceMembershipChanged(Connection connection) {
mHoldTracker.updateHoldCapability(connection.getPhoneAccountHandle());
}
};
@@ -320,6 +318,14 @@
}
};
+ private final TelephonyConferenceBase.TelephonyConferenceListener mTelephonyConferenceListener =
+ new TelephonyConferenceBase.TelephonyConferenceListener() {
+ @Override
+ public void onConferenceMembershipChanged(Connection connection) {
+ mHoldTracker.updateHoldCapability(connection.getPhoneAccountHandle());
+ }
+ };
+
@Override
public void onCreate() {
super.onCreate();
@@ -628,11 +634,10 @@
} else {
Log.w(this, "onCreateOutgoingConnection, failed to turn on radio");
- originalConnection.setDisconnected(
+ closeOrDestroyConnection(originalConnection,
DisconnectCauseUtil.toTelecomDisconnectCause(
android.telephony.DisconnectCause.POWER_OFF,
"Failed to turn on radio."));
- originalConnection.destroy();
}
}
@@ -658,12 +663,11 @@
addExistingConnection(PhoneUtils.makePstnPhoneAccountHandleWithPrefix(
phone, "", isEmergencyNumber && noActiveSimCard), repConnection);
// Remove the old connection from Telecom after.
- connectionToEvaluate.setDisconnected(
+ closeOrDestroyConnection(connectionToEvaluate,
DisconnectCauseUtil.toTelecomDisconnectCause(
android.telephony.DisconnectCause.OUTGOING_CANCELED,
"Reconnecting outgoing Emergency Call.",
phone.getPhoneId()));
- connectionToEvaluate.destroy();
} else {
placeOutgoingConnection((TelephonyConnection) connectionToEvaluate, phone, request);
}
@@ -829,8 +833,8 @@
phone.getPhoneId()));
}
connection.setAddress(handle, PhoneConstants.PRESENTATION_ALLOWED);
- connection.setInitializing();
- connection.setVideoState(request.getVideoState());
+ connection.setTelephonyConnectionInitializing();
+ connection.setTelephonyVideoState(request.getVideoState());
connection.setRttTextStream(request.getRttTextStream());
connection.setTtyEnabled(isTtyModeEnabled);
return connection;
@@ -1087,7 +1091,6 @@
@Override
public void onConnectionAdded(Connection connection) {
if (connection instanceof Holdable && !isExternalConnection(connection)) {
- connection.addConnectionListener(mConnectionListener);
mHoldTracker.addHoldable(
connection.getPhoneAccountHandle(), (Holdable) connection);
}
@@ -1218,9 +1221,7 @@
} else {
// We have run out of Phones to use. Disconnect the call and destroy the connection.
Log.i(this, "retryOutgoingOriginalConnection, no more Phones to use. Disconnecting.");
- c.setDisconnected(new DisconnectCause(DisconnectCause.ERROR));
- c.clearOriginalConnection();
- c.destroy();
+ closeOrDestroyConnection(c, new DisconnectCause(DisconnectCause.ERROR));
}
}
@@ -1282,10 +1283,10 @@
cause = android.telephony.DisconnectCause.OTASP_PROVISIONING_IN_PROCESS;
break;
}
- connection.setDisconnected(DisconnectCauseUtil.toTelecomDisconnectCause(
- cause, e.getMessage(), phone.getPhoneId()));
- connection.clearOriginalConnection();
- connection.destroy();
+ connection.setTelephonyConnectionDisconnected(
+ DisconnectCauseUtil.toTelecomDisconnectCause(cause, e.getMessage(),
+ phone.getPhoneId()));
+ connection.close();
return;
}
@@ -1306,10 +1307,10 @@
startActivity(intent);
}
Log.d(this, "placeOutgoingConnection, phone.dial returned null");
- connection.setDisconnected(DisconnectCauseUtil.toTelecomDisconnectCause(
- telephonyDisconnectCause, "Connection is null", phone.getPhoneId()));
- connection.clearOriginalConnection();
- connection.destroy();
+ connection.setTelephonyConnectionDisconnected(
+ DisconnectCauseUtil.toTelecomDisconnectCause(telephonyDisconnectCause,
+ "Connection is null", phone.getPhoneId()));
+ connection.close();
} else {
connection.setOriginalConnection(originalConnection);
}
@@ -1824,7 +1825,7 @@
// are potentially placing an international call on WFC.
Log.i(this, "placeOutgoingConnection - sending international call on WFC " +
"confirmation event");
- telephonyConnection.sendConnectionEvent(
+ telephonyConnection.sendTelephonyConnectionEvent(
TelephonyManager.EVENT_NOTIFY_INTERNATIONAL_CALL_ON_WFC, null);
}
}
@@ -1840,4 +1841,26 @@
}
}
}
+
+ private void closeOrDestroyConnection(Connection connection, DisconnectCause cause) {
+ if (connection instanceof TelephonyConnection) {
+ TelephonyConnection telephonyConnection = (TelephonyConnection) connection;
+ telephonyConnection.setTelephonyConnectionDisconnected(cause);
+ // Close destroys the connection and notifies TelephonyConnection listeners.
+ telephonyConnection.close();
+ } else {
+ connection.setDisconnected(cause);
+ connection.destroy();
+ }
+ }
+
+ /**
+ * Adds a {@link Conference} to the telephony ConnectionService and registers a listener for
+ * changes to the conference. Should be used instead of {@link #addConference(Conference)}.
+ * @param conference The conference.
+ */
+ public void addTelephonyConference(@NonNull TelephonyConferenceBase conference) {
+ addConference(conference);
+ conference.addListener(mTelephonyConferenceListener);
+ }
}
diff --git a/src/com/android/services/telephony/TelephonyConnectionServiceProxy.java b/src/com/android/services/telephony/TelephonyConnectionServiceProxy.java
index 1ced34a..604cf03 100644
--- a/src/com/android/services/telephony/TelephonyConnectionServiceProxy.java
+++ b/src/com/android/services/telephony/TelephonyConnectionServiceProxy.java
@@ -36,4 +36,10 @@
void addExistingConnection(PhoneAccountHandle phoneAccountHandle,
Connection connection, Conference conference);
void addConnectionToConferenceController(TelephonyConnection connection);
+
+ /**
+ * Called when a connection's conference membership changes.
+ * @param connection The connection.
+ */
+ void onConferenceMembershipChanged(Connection connection);
}
diff --git a/tests/src/com/android/services/telephony/ImsConferenceControllerTest.java b/tests/src/com/android/services/telephony/ImsConferenceControllerTest.java
index aa832aa..edfc34f 100644
--- a/tests/src/com/android/services/telephony/ImsConferenceControllerTest.java
+++ b/tests/src/com/android/services/telephony/ImsConferenceControllerTest.java
@@ -16,14 +16,13 @@
package com.android.services.telephony;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.any;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
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.assertFalse;
import android.os.Looper;
import android.test.suitebuilder.annotation.SmallTest;
@@ -32,7 +31,6 @@
import org.junit.Before;
import org.junit.Test;
-
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -85,7 +83,7 @@
mControllerTest.add(mTestTelephonyConnectionA);
mTestTelephonyConnectionA.setActive();
- mTestTelephonyConnectionB.setOnHold();
+ mTestTelephonyConnectionB.setTelephonyConnectionOnHold();
assertTrue(mTestTelephonyConnectionA.getConferenceables()
.contains(mTestTelephonyConnectionB));
@@ -125,10 +123,9 @@
mControllerTest.add(mTestTelephonyConnectionA);
mTestTelephonyConnectionA.setActive();
- mTestTelephonyConnectionB.setOnHold();
+ mTestTelephonyConnectionB.setTelephonyConnectionOnHold();
verify(mMockTelephonyConnectionServiceProxy, times(2))
.addConference(any(ImsConference.class));
-
}
}
diff --git a/tests/src/com/android/services/telephony/TelephonyConferenceControllerTest.java b/tests/src/com/android/services/telephony/TelephonyConferenceControllerTest.java
index 275bcc6..4fc8c02 100644
--- a/tests/src/com/android/services/telephony/TelephonyConferenceControllerTest.java
+++ b/tests/src/com/android/services/telephony/TelephonyConferenceControllerTest.java
@@ -16,6 +16,13 @@
package com.android.services.telephony;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
import android.os.Looper;
import android.telecom.Conference;
import android.telecom.Connection;
@@ -23,18 +30,9 @@
import org.junit.Before;
import org.junit.Test;
-
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.mockito.ArgumentCaptor;
-
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import static org.mockito.Mockito.any;
-
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertFalse;
import java.util.ArrayList;
import java.util.Collection;
@@ -94,8 +92,8 @@
// add telephony connection A
mControllerTest.add(mTestTelephonyConnectionA);
- mTestTelephonyConnectionA.setActive();
- mTestTelephonyConnectionB.setOnHold();
+ mTestTelephonyConnectionA.setTelephonyConnectionActive();
+ mTestTelephonyConnectionB.setTelephonyConnectionOnHold();
assertTrue(mTestTelephonyConnectionA.getConferenceables()
.contains(mTestTelephonyConnectionB));
@@ -146,8 +144,8 @@
// add telephony connection A
mControllerTest.add(mTestTelephonyConnectionA);
- mTestTelephonyConnectionA.setActive();
- mTestTelephonyConnectionB.setOnHold();
+ mTestTelephonyConnectionA.setTelephonyConnectionActive();
+ mTestTelephonyConnectionB.setTelephonyConnectionOnHold();
assertTrue(mTestTelephonyConnectionA.getConferenceables()
.contains(mTestTelephonyConnectionB));