Merge "Add CarrierConfigLoader service." into m-wireless-dev
diff --git a/src/com/android/phone/TimeConsumingPreferenceActivity.java b/src/com/android/phone/TimeConsumingPreferenceActivity.java
index bab9469..08a5a95 100644
--- a/src/com/android/phone/TimeConsumingPreferenceActivity.java
+++ b/src/com/android/phone/TimeConsumingPreferenceActivity.java
@@ -179,6 +179,8 @@
public void onException(Preference preference, CommandException exception) {
if (exception.getCommandError() == CommandException.Error.FDN_CHECK_FAILURE) {
onError(preference, FDN_CHECK_FAILURE);
+ } else if (exception.getCommandError() == CommandException.Error.RADIO_NOT_AVAILABLE) {
+ onError(preference, RADIO_OFF_ERROR);
} else {
preference.setEnabled(false);
onError(preference, EXCEPTION_ERROR);
diff --git a/src/com/android/phone/settings/PhoneAccountSettingsFragment.java b/src/com/android/phone/settings/PhoneAccountSettingsFragment.java
index 6ca146c..7f04302 100644
--- a/src/com/android/phone/settings/PhoneAccountSettingsFragment.java
+++ b/src/com/android/phone/settings/PhoneAccountSettingsFragment.java
@@ -98,8 +98,8 @@
mDefaultOutgoingAccount = (AccountSelectionPreference)
getPreferenceScreen().findPreference(DEFAULT_OUTGOING_ACCOUNT_KEY);
- if (mTelecomManager.hasMultipleCallCapableAccounts()) {
mDefaultOutgoingAccount.setListener(this);
+ if (mTelecomManager.getCallCapablePhoneAccounts().size() > 1) {
updateDefaultOutgoingAccountsModel();
} else {
getPreferenceScreen().removePreference(mDefaultOutgoingAccount);
diff --git a/src/com/android/services/telephony/CdmaConference.java b/src/com/android/services/telephony/CdmaConference.java
index fdd2110..6a55efe 100755
--- a/src/com/android/services/telephony/CdmaConference.java
+++ b/src/com/android/services/telephony/CdmaConference.java
@@ -42,7 +42,7 @@
public void updateCapabilities(int capabilities) {
capabilities |= Connection.CAPABILITY_MUTE | Connection.CAPABILITY_GENERIC_CONFERENCE;
- setCapabilities(capabilities);
+ setConnectionCapabilities(capabilities);
}
/**
diff --git a/src/com/android/services/telephony/ImsConference.java b/src/com/android/services/telephony/ImsConference.java
index 9afb4ad..02a569f 100644
--- a/src/com/android/services/telephony/ImsConference.java
+++ b/src/com/android/services/telephony/ImsConference.java
@@ -168,8 +168,8 @@
public void onConnectionCapabilitiesChanged(Connection c, int connectionCapabilities) {
Log.d(this, "onCallCapabilitiesChanged: Connection: %s, callCapabilities: %s", c,
connectionCapabilities);
- int capabilites = ImsConference.this.getCapabilities();
- setCapabilities(applyVideoCapabilities(capabilites, connectionCapabilities));
+ int capabilites = ImsConference.this.getConnectionCapabilities();
+ setConnectionCapabilities(applyVideoCapabilities(capabilites, connectionCapabilities));
}
};
@@ -202,7 +202,10 @@
public ImsConference(TelephonyConnectionService telephonyConnectionService,
TelephonyConnection conferenceHost) {
- super(null);
+ super((conferenceHost != null && conferenceHost.getCall() != null &&
+ conferenceHost.getCall().getPhone() != null) ?
+ PhoneUtils.makePstnPhoneAccountHandle(
+ conferenceHost.getCall().getPhone()) : null);
// Specify the connection time of the conference to be the connection time of the original
// connection.
@@ -210,36 +213,30 @@
mTelephonyConnectionService = telephonyConnectionService;
setConferenceHost(conferenceHost);
- if (conferenceHost != null && conferenceHost.getCall() != null
- && conferenceHost.getCall().getPhone() != null) {
- mPhoneAccount = PhoneUtils.makePstnPhoneAccountHandle(
- conferenceHost.getCall().getPhone());
- Log.v(this, "set phacc to " + mPhoneAccount);
- }
int capabilities = Connection.CAPABILITY_SUPPORT_HOLD | Connection.CAPABILITY_HOLD |
Connection.CAPABILITY_MUTE;
- capabilities = applyVideoCapabilities(capabilities, mConferenceHost.getCallCapabilities());
+ capabilities = applyVideoCapabilities(capabilities, mConferenceHost.getConnectionCapabilities());
setConnectionCapabilities(capabilities);
}
private int applyVideoCapabilities(int conferenceCapabilities, int capabilities) {
- if (can(capabilities, Connection.CAPABILITY_SUPPORTS_VT_LOCAL)) {
+ if (can(capabilities, Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL)) {
conferenceCapabilities = applyCapability(conferenceCapabilities,
- Connection.CAPABILITY_SUPPORTS_VT_LOCAL);
+ Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL);
} else {
conferenceCapabilities = removeCapability(conferenceCapabilities,
- Connection.CAPABILITY_SUPPORTS_VT_LOCAL);
+ Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL);
}
- if (can(capabilities, Connection.CAPABILITY_SUPPORTS_VT_REMOTE)) {
+ if (can(capabilities, Connection.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL)) {
conferenceCapabilities = applyCapability(conferenceCapabilities,
- Connection.CAPABILITY_SUPPORTS_VT_REMOTE);
+ Connection.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL);
} else {
conferenceCapabilities = removeCapability(conferenceCapabilities,
- Connection.CAPABILITY_SUPPORTS_VT_REMOTE);
+ Connection.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL);
}
if (can(capabilities, Connection.CAPABILITY_CAN_UPGRADE_TO_VIDEO)) {
@@ -412,6 +409,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 eea079a..de5720c 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}.
@@ -203,6 +213,17 @@
public void onCallSubstateChanged(int callSubstate) {
setCallSubstate(callSubstate);
}
+
+ /*
+ * 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;
@@ -481,9 +502,9 @@
int newCapabilities = buildConnectionCapabilities();
newCapabilities = changeCapability(newCapabilities,
- CAPABILITY_SUPPORTS_VT_REMOTE, mRemoteVideoCapable);
+ CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL, mRemoteVideoCapable);
newCapabilities = changeCapability(newCapabilities,
- CAPABILITY_SUPPORTS_VT_LOCAL, mLocalVideoCapable);
+ CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL, mLocalVideoCapable);
newCapabilities = changeCapability(newCapabilities,
CAPABILITY_HIGH_DEF_AUDIO, mHasHighDefAudio);
newCapabilities = changeCapability(newCapabilities, CAPABILITY_WIFI, mIsWifi);
@@ -721,6 +742,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");