Merge "Add handling of RADIO_NOT_AVAILABLE in TimeConsumingPreferenceActivity" into lmp-mr1-wfc-dev
diff --git a/src/com/android/services/telephony/ImsConference.java b/src/com/android/services/telephony/ImsConference.java
index e692a30..b63b75c 100644
--- a/src/com/android/services/telephony/ImsConference.java
+++ b/src/com/android/services/telephony/ImsConference.java
@@ -322,6 +322,26 @@
}
/**
+ * Determines if this conference is hosted on the current device or the peer device.
+ *
+ * @return {@code true} if this conference is hosted on the current device, {@code false} if it
+ * is hosted on the peer device.
+ */
+ public boolean isConferenceHost() {
+ if (mConferenceHost == null) {
+ return false;
+ }
+ com.android.internal.telephony.Connection originalConnection =
+ mConferenceHost.getOriginalConnection();
+ if (!(originalConnection instanceof ImsPhoneConnection)) {
+ return false;
+ }
+
+ ImsPhoneConnection imsPhoneConnection = (ImsPhoneConnection) originalConnection;
+ return imsPhoneConnection.isMultiparty() && imsPhoneConnection.isConferenceHost();
+ }
+
+ /**
* Updates the manage conference capability of the conference. Where there are one or more
* conference event package participants, the conference management is permitted. Where there
* are no conference event package participants, conference management is not permitted.
diff --git a/src/com/android/services/telephony/ImsConferenceController.java b/src/com/android/services/telephony/ImsConferenceController.java
index e93ebd4..21c61f8 100644
--- a/src/com/android/services/telephony/ImsConferenceController.java
+++ b/src/com/android/services/telephony/ImsConferenceController.java
@@ -16,6 +16,8 @@
package com.android.services.telephony;
+import com.android.internal.telephony.imsphone.ImsPhoneConnection;
+
import android.net.Uri;
import android.telecom.Conference;
import android.telecom.Connection;
@@ -155,6 +157,15 @@
Log.d(this, "recalc - %s %s", connection.getState(), connection);
}
+ // If this connection is a member of a conference hosted on another device, it is not
+ // conferenceable with any other connections.
+ if (isMemberOfPeerConference(connection)) {
+ if (Log.VERBOSE) {
+ Log.v(this, "Skipping connection in peer conference: %s", connection);
+ }
+ continue;
+ }
+
switch (connection.getState()) {
case Connection.STATE_ACTIVE:
activeConnections.add(connection);
@@ -168,11 +179,18 @@
connection.setConferenceableConnections(Collections.<Connection>emptyList());
}
- for (Conference conference : mImsConferences) {
+ for (ImsConference conference : mImsConferences) {
if (Log.DEBUG) {
Log.d(this, "recalc - %s %s", conference.getState(), conference);
}
+ if (!conference.isConferenceHost()) {
+ if (Log.VERBOSE) {
+ Log.v(this, "skipping conference (not hosted on this device): %s", conference);
+ }
+ continue;
+ }
+
switch (conference.getState()) {
case Connection.STATE_ACTIVE:
activeConnections.add(conference);
@@ -209,6 +227,16 @@
// Set the conference as conferenceable with all the connections
for (ImsConference conference : mImsConferences) {
+ // If this conference is not being hosted on the current device, we cannot conference it
+ // with any other connections.
+ if (!conference.isConferenceHost()) {
+ if (Log.VERBOSE) {
+ Log.v(this, "skipping conference (not hosted on this device): %s",
+ conference);
+ }
+ continue;
+ }
+
List<Connection> nonConferencedConnections =
new ArrayList<>(mTelephonyConnections.size());
for (Connection c : mTelephonyConnections) {
@@ -224,6 +252,27 @@
}
/**
+ * Determines if a connection is a member of a conference hosted on another device.
+ *
+ * @param connection The connection.
+ * @return {@code true} if the connection is a member of a conference hosted on another device.
+ */
+ private boolean isMemberOfPeerConference(Connection connection) {
+ if (!(connection instanceof TelephonyConnection)) {
+ return false;
+ }
+ TelephonyConnection telephonyConnection = (TelephonyConnection) connection;
+ com.android.internal.telephony.Connection originalConnection =
+ telephonyConnection.getOriginalConnection();
+ if (!(originalConnection instanceof ImsPhoneConnection)) {
+ return false;
+ }
+
+ ImsPhoneConnection imsPhoneConnection = (ImsPhoneConnection) originalConnection;
+ return imsPhoneConnection.isMultiparty() && !imsPhoneConnection.isConferenceHost();
+ }
+
+ /**
* Starts a new ImsConference for a connection which just entered a multiparty state.
*/
private void recalculateConference() {
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index ac384fd..d079df7 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -50,6 +50,7 @@
private static final int MSG_RINGBACK_TONE = 2;
private static final int MSG_HANDOVER_STATE_CHANGED = 3;
private static final int MSG_DISCONNECT = 4;
+ private static final int MSG_MULTIPARTY_STATE_CHANGED = 5;
private final Handler mHandler = new Handler() {
@Override
@@ -87,6 +88,14 @@
case MSG_DISCONNECT:
updateState();
break;
+ case MSG_MULTIPARTY_STATE_CHANGED:
+ boolean isMultiParty = (Boolean) msg.obj;
+ Log.i(this, "Update multiparty state to %s", isMultiParty ? "Y" : "N");
+ mIsMultiParty = isMultiParty;
+ if (isMultiParty) {
+ notifyConferenceStarted();
+ }
+ break;
}
}
};
@@ -182,6 +191,7 @@
public void onAudioQualityChanged(int audioQuality) {
setAudioQuality(audioQuality);
}
+
/**
* Handles a change in the state of conference participant(s), as reported by the
* {@link com.android.internal.telephony.Connection}.
@@ -192,6 +202,17 @@
public void onConferenceParticipantsChanged(List<ConferenceParticipant> participants) {
updateConferenceParticipants(participants);
}
+
+ /**
+ * Handles a change to the multiparty state for this connection.
+ *
+ * @param isMultiParty {@code true} if the call became multiparty, {@code false}
+ * otherwise.
+ */
+ @Override
+ public void onMultipartyStateChanged(boolean isMultiParty) {
+ handleMultipartyStateChange(isMultiParty);
+ }
};
private com.android.internal.telephony.Connection mOriginalConnection;
@@ -693,6 +714,24 @@
}
}
+ /**
+ * Handles requests to update the multiparty state received via the
+ * {@link com.android.internal.telephony.Connection.Listener#onMultipartyStateChanged(boolean)}
+ * listener.
+ * <p>
+ * Note: We post this to the mHandler to ensure that if a conference must be created as a
+ * result of the multiparty state change, the conference creation happens on the correct
+ * thread. This ensures that the thread check in
+ * {@link com.android.internal.telephony.PhoneBase#checkCorrectThread(android.os.Handler)}
+ * does not fire.
+ *
+ * @param isMultiParty {@code true} if this connection is multiparty, {@code false} otherwise.
+ */
+ private void handleMultipartyStateChange(boolean isMultiParty) {
+ Log.i(this, "Update multiparty state to %s", isMultiParty ? "Y" : "N");
+ mHandler.obtainMessage(MSG_MULTIPARTY_STATE_CHANGED, isMultiParty).sendToTarget();
+ }
+
private void setActiveInternal() {
if (getState() == STATE_ACTIVE) {
Log.w(this, "Should not be called if this is already ACTIVE");