Support filtering out conference originator from manage conference list.
Some carriers will include the conference originator in the conference
event package data. This means that my own phone number can show up in
the "manage conference" screen.
Added a method in TelecomAccountRegistry to get the device phone number
given a phone account.
In ImsConference, when adding new participants add a check to see if the
participant # is the same as the conference host's number.
Also, caching and reusing the phone account handle instead of re-creating
it each time.
Bug: 22629231
Change-Id: I76067f330482c1fa2562bd89dfad659850da428f
diff --git a/src/com/android/services/telephony/ImsConference.java b/src/com/android/services/telephony/ImsConference.java
index 7105b50..c4ae4a1 100644
--- a/src/com/android/services/telephony/ImsConference.java
+++ b/src/com/android/services/telephony/ImsConference.java
@@ -33,6 +33,7 @@
import com.android.internal.telephony.CallStateException;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.imsphone.ImsPhone;
import com.android.internal.telephony.imsphone.ImsPhoneConnection;
import com.android.phone.PhoneUtils;
import com.android.phone.R;
@@ -42,6 +43,7 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
/**
@@ -194,6 +196,16 @@
private TelephonyConnection mConferenceHost;
/**
+ * The PhoneAccountHandle of the conference host.
+ */
+ private PhoneAccountHandle mConferenceHostPhoneAccountHandle;
+
+ /**
+ * The address of the conference host.
+ */
+ private Uri mConferenceHostAddress;
+
+ /**
* The known conference participant connections. The HashMap is keyed by endpoint Uri.
* A {@link ConcurrentHashMap} is used as there is a possibility for radio events impacting the
* available participants to occur at the same time as an access via the connection service.
@@ -491,9 +503,24 @@
}
mConferenceHost = conferenceHost;
+
+ // Attempt to get the conference host's address (e.g. the host's own phone number).
+ // We need to look at the default phone for the ImsPhone when creating the phone account
+ // for the
+ if (mConferenceHost.getPhone() != null && mConferenceHost.getPhone() instanceof ImsPhone) {
+ // Look up the conference host's address; we need this later for filtering out the
+ // conference host in conference event package data.
+ ImsPhone imsPhone = (ImsPhone) mConferenceHost.getPhone();
+ mConferenceHostPhoneAccountHandle =
+ PhoneUtils.makePstnPhoneAccountHandle(imsPhone.getDefaultPhone());
+ mConferenceHostAddress = TelecomAccountRegistry.getInstance(mTelephonyConnectionService)
+ .getAddress(mConferenceHostPhoneAccountHandle);
+ }
+
mConferenceHost.addConnectionListener(mConferenceHostListener);
mConferenceHost.addTelephonyConnectionListener(mTelephonyConnectionListener);
setState(mConferenceHost.getState());
+
updateStatusHints();
}
@@ -520,9 +547,13 @@
participantUserEntities.add(userEntity);
if (!mConferenceParticipantConnections.containsKey(userEntity)) {
- createConferenceParticipantConnection(parent, participant);
- newParticipants.add(participant);
- newParticipantsAdded = true;
+ // Some carriers will also include the conference host in the CEP. We will filter
+ // that out here.
+ if (!isParticipantHost(mConferenceHostAddress, participant.getHandle())) {
+ createConferenceParticipantConnection(parent, participant);
+ newParticipants.add(participant);
+ newParticipantsAdded = true;
+ }
} else {
ConferenceParticipantConnection connection =
mConferenceParticipantConnections.get(userEntity);
@@ -590,9 +621,8 @@
}
mConferenceParticipantConnections.put(participant.getHandle(), connection);
- PhoneAccountHandle phoneAccountHandle =
- PhoneUtils.makePstnPhoneAccountHandle(parent.getPhone());
- mTelephonyConnectionService.addExistingConnection(phoneAccountHandle, connection);
+ mTelephonyConnectionService.addExistingConnection(mConferenceHostPhoneAccountHandle,
+ connection);
addConnection(connection);
}
@@ -629,6 +659,50 @@
}
/**
+ * Determines if the passed in participant handle is the same as the conference host's handle.
+ * Starts with a simple equality check. However, the handles from a conference event package
+ * will be a SIP uri, so we need to pull that apart to look for the participant's phone number.
+ *
+ * @param hostHandle The handle of the connection hosting the conference.
+ * @param handle The handle of the conference participant.
+ * @return {@code true} if the host's handle matches the participant's handle, {@code false}
+ * otherwise.
+ */
+ private boolean isParticipantHost(Uri hostHandle, Uri handle) {
+ // If host and participant handles are the same, bail early.
+ if (Objects.equals(hostHandle, handle)) {
+ return true;
+ }
+
+ // Conference event package participants are identified using SIP URIs (see RFC3261).
+ // A valid SIP uri has the format: sip:user:password@host:port;uri-parameters?headers
+ // Per RFC3261, the "user" can be a telephone number.
+ // For example: sip:1650555121;phone-context=blah.com@host.com
+ // In this case, the phone number is in the user field of the URI, and the parameters can be
+ // ignored.
+ //
+ // A SIP URI can also specify a phone number in a format similar to:
+ // sip:+1-212-555-1212@something.com;user=phone
+ // In this case, the phone number is again in user field and the parameters can be ignored.
+ // We can get the user field in these instances by splitting the string on the @, ;, or :
+ // and looking at the first found item.
+
+ String number = handle.getSchemeSpecificPart();
+ String numberParts[] = number.split("[@;:]");
+
+ if (numberParts.length == 0) {
+ return false;
+ }
+ number = numberParts[0];
+
+ // The host number will be a tel: uri. Per RFC3966, the part after tel: is the phone
+ // number.
+ String hostNumber = hostHandle.getSchemeSpecificPart();
+
+ return Objects.equals(hostNumber, number);
+ }
+
+ /**
* Handles a change in the original connection backing the conference host connection. This can
* happen if an SRVCC event occurs on the original IMS connection, requiring a fallback to
* GSM or CDMA.
diff --git a/src/com/android/services/telephony/TelecomAccountRegistry.java b/src/com/android/services/telephony/TelecomAccountRegistry.java
index 1676032..154fc33 100644
--- a/src/com/android/services/telephony/TelecomAccountRegistry.java
+++ b/src/com/android/services/telephony/TelecomAccountRegistry.java
@@ -363,6 +363,21 @@
}
/**
+ * Returns the address (e.g. the phone number) associated with a subscription.
+ *
+ * @param handle The phone account handle to find the subscription address for.
+ * @return The address.
+ */
+ Uri getAddress(PhoneAccountHandle handle) {
+ for (AccountEntry entry : mAccounts) {
+ if (entry.getPhoneAccountHandle().equals(handle)) {
+ return entry.mAccount.getAddress();
+ }
+ }
+ return null;
+ }
+
+ /**
* Sets up all the phone accounts for SIMs on first boot.
*/
void setupOnBoot() {