summaryrefslogtreecommitdiff
path: root/telecomm/java/android/telecom/Connection.java
diff options
context:
space:
mode:
Diffstat (limited to 'telecomm/java/android/telecom/Connection.java')
-rw-r--r--telecomm/java/android/telecom/Connection.java321
1 files changed, 265 insertions, 56 deletions
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index ff220f3a4c30..a093d54568d3 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -35,6 +35,7 @@ import android.util.ArraySet;
import android.view.Surface;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
@@ -52,6 +53,37 @@ import java.util.concurrent.ConcurrentHashMap;
* Implementations are then responsible for updating the state of the {@code Connection}, and
* must call {@link #destroy()} to signal to the framework that the {@code Connection} is no
* longer used and associated resources may be recovered.
+ * <p>
+ * Subclasses of {@code Connection} override the {@code on*} methods to provide the the
+ * {@link ConnectionService}'s implementation of calling functionality. The {@code on*} methods are
+ * called by Telecom to inform an instance of a {@code Connection} of actions specific to that
+ * {@code Connection} instance.
+ * <p>
+ * Basic call support requires overriding the following methods: {@link #onAnswer()},
+ * {@link #onDisconnect()}, {@link #onReject()}, {@link #onAbort()}
+ * <p>
+ * Where a {@code Connection} has {@link #CAPABILITY_SUPPORT_HOLD}, the {@link #onHold()} and
+ * {@link #onUnhold()} methods should be overridden to provide hold support for the
+ * {@code Connection}.
+ * <p>
+ * Where a {@code Connection} supports a variation of video calling (e.g. the
+ * {@code CAPABILITY_SUPPORTS_VT_*} capability bits), {@link #onAnswer(int)} should be overridden
+ * to support answering a call as a video call.
+ * <p>
+ * Where a {@code Connection} has {@link #PROPERTY_IS_EXTERNAL_CALL} and
+ * {@link #CAPABILITY_CAN_PULL_CALL}, {@link #onPullExternalCall()} should be overridden to provide
+ * support for pulling the external call.
+ * <p>
+ * Where a {@code Connection} supports conference calling {@link #onSeparate()} should be
+ * overridden.
+ * <p>
+ * There are a number of other {@code on*} methods which a {@code Connection} can choose to
+ * implement, depending on whether it is concerned with the associated calls from Telecom. If,
+ * for example, call events from a {@link InCallService} are handled,
+ * {@link #onCallEvent(String, Bundle)} should be overridden. Another example is
+ * {@link #onExtrasChanged(Bundle)}, which should be overridden if the {@code Connection} wishes to
+ * make use of extra information provided via the {@link Call#putExtras(Bundle)} and
+ * {@link Call#removeExtras(String...)} methods.
*/
public abstract class Connection extends Conferenceable {
@@ -100,7 +132,6 @@ public abstract class Connection extends Conferenceable {
* <p>
* A connection can only be in this state if the {@link #PROPERTY_IS_EXTERNAL_CALL} property and
* {@link #CAPABILITY_CAN_PULL_CALL} capability bits are set on the connection.
- * @hide
*/
public static final int STATE_PULLING_CALL = 7;
@@ -284,7 +315,6 @@ public abstract class Connection extends Conferenceable {
* <p>
* Should only be set on a {@code Connection} where {@link #PROPERTY_IS_EXTERNAL_CALL}
* is set.
- * @hide
*/
public static final int CAPABILITY_CAN_PULL_CALL = 0x01000000;
@@ -332,13 +362,22 @@ public abstract class Connection extends Conferenceable {
* external connections. Only those {@link InCallService}s which have the
* {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true} in its
* manifest will see external connections.
- * @hide
*/
public static final int PROPERTY_IS_EXTERNAL_CALL = 1<<4;
+ /**
+ * Indicates that the connection has CDMA Enhanced Voice Privacy enabled.
+ */
+ public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 1<<5;
+
+ /**
+ * Indicates that the connection represents a downgraded IMS conference.
+ * @hide
+ */
+ public static final int PROPERTY_IS_DOWNGRADED_CONFERENCE = 1<<6;
//**********************************************************************************************
- // Next PROPERTY value: 1<<5
+ // Next PROPERTY value: 1<<7
//**********************************************************************************************
/**
@@ -365,9 +404,25 @@ public abstract class Connection extends Conferenceable {
public static final String EXTRA_CALL_SUBJECT = "android.telecom.extra.CALL_SUBJECT";
/**
+ * Boolean connection extra key set on a {@link Connection} in
+ * {@link Connection#STATE_RINGING} state to indicate that answering the call will cause the
+ * current active foreground call to be dropped.
+ */
+ public static final String EXTRA_ANSWERING_DROPS_FG_CALL =
+ "android.telecom.extra.ANSWERING_DROPS_FG_CALL";
+
+ /**
+ * Boolean connection extra key on a {@link Connection} which indicates that adding an
+ * additional call is disallowed.
+ * @hide
+ */
+ public static final String EXTRA_DISABLE_ADD_CALL =
+ "android.telecom.extra.DISABLE_ADD_CALL";
+
+ /**
* Connection event used to inform Telecom that it should play the on hold tone. This is used
* to play a tone when the peer puts the current call on hold. Sent to Telecom via
- * {@link #sendConnectionEvent(String)}.
+ * {@link #sendConnectionEvent(String, Bundle)}.
* @hide
*/
public static final String EVENT_ON_HOLD_TONE_START =
@@ -376,7 +431,7 @@ public abstract class Connection extends Conferenceable {
/**
* Connection event used to inform Telecom that it should stop the on hold tone. This is used
* to stop a tone when the peer puts the current call on hold. Sent to Telecom via
- * {@link #sendConnectionEvent(String)}.
+ * {@link #sendConnectionEvent(String, Bundle)}.
* @hide
*/
public static final String EVENT_ON_HOLD_TONE_END =
@@ -391,10 +446,47 @@ public abstract class Connection extends Conferenceable {
* {@link Call.Details#PROPERTY_IS_EXTERNAL_CALL} and
* {@link Call.Details#CAPABILITY_CAN_PULL_CALL}, but the {@link ConnectionService} could not
* pull the external call due to an error condition.
- * @hide
+ * <p>
+ * Sent via {@link #sendConnectionEvent(String, Bundle)}. The {@link Bundle} parameter is
+ * expected to be null when this connection event is used.
*/
public static final String EVENT_CALL_PULL_FAILED = "android.telecom.event.CALL_PULL_FAILED";
+ /**
+ * Connection event used to inform {@link InCallService}s when the merging of two calls has
+ * failed. The User Interface should use this message to inform the user of the error.
+ * <p>
+ * Sent via {@link #sendConnectionEvent(String, Bundle)}. The {@link Bundle} parameter is
+ * expected to be null when this connection event is used.
+ */
+ public static final String EVENT_CALL_MERGE_FAILED = "android.telecom.event.CALL_MERGE_FAILED";
+
+ /**
+ * Connection event used to inform {@link InCallService}s when a call has been put on hold by
+ * the remote party.
+ * <p>
+ * This is different than the {@link Connection#STATE_HOLDING} state which indicates that the
+ * call is being held locally on the device. When a capable {@link ConnectionService} receives
+ * signalling to indicate that the remote party has put the call on hold, it can send this
+ * connection event.
+ * @hide
+ */
+ public static final String EVENT_CALL_REMOTELY_HELD =
+ "android.telecom.event.CALL_REMOTELY_HELD";
+
+ /**
+ * Connection event used to inform {@link InCallService}s when a call which was remotely held
+ * (see {@link #EVENT_CALL_REMOTELY_HELD}) has been un-held by the remote party.
+ * <p>
+ * This is different than the {@link Connection#STATE_HOLDING} state which indicates that the
+ * call is being held locally on the device. When a capable {@link ConnectionService} receives
+ * signalling to indicate that the remote party has taken the call off hold, it can send this
+ * connection event.
+ * @hide
+ */
+ public static final String EVENT_CALL_REMOTELY_UNHELD =
+ "android.telecom.event.CALL_REMOTELY_UNHELD";
+
// Flag controlling whether PII is emitted into the logs
private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG);
@@ -441,69 +533,94 @@ public abstract class Connection extends Conferenceable {
mConnectionCapabilities |= capability;
}
-
+ /**
+ * Renders a set of capability bits ({@code CAPABILITY_*}) as a human readable string.
+ *
+ * @param capabilities A capability bit field.
+ * @return A human readable string representation.
+ */
public static String capabilitiesToString(int capabilities) {
+ return capabilitiesToStringInternal(capabilities, true /* isLong */);
+ }
+
+ /**
+ * Renders a set of capability bits ({@code CAPABILITY_*}) as a *short* human readable
+ * string.
+ *
+ * @param capabilities A capability bit field.
+ * @return A human readable string representation.
+ * @hide
+ */
+ public static String capabilitiesToStringShort(int capabilities) {
+ return capabilitiesToStringInternal(capabilities, false /* isLong */);
+ }
+
+ private static String capabilitiesToStringInternal(int capabilities, boolean isLong) {
StringBuilder builder = new StringBuilder();
- builder.append("[Capabilities:");
+ builder.append("[");
+ if (isLong) {
+ builder.append("Capabilities:");
+ }
+
if (can(capabilities, CAPABILITY_HOLD)) {
- builder.append(" CAPABILITY_HOLD");
+ builder.append(isLong ? " CAPABILITY_HOLD" : " hld");
}
if (can(capabilities, CAPABILITY_SUPPORT_HOLD)) {
- builder.append(" CAPABILITY_SUPPORT_HOLD");
+ builder.append(isLong ? " CAPABILITY_SUPPORT_HOLD" : " sup_hld");
}
if (can(capabilities, CAPABILITY_MERGE_CONFERENCE)) {
- builder.append(" CAPABILITY_MERGE_CONFERENCE");
+ builder.append(isLong ? " CAPABILITY_MERGE_CONFERENCE" : " mrg_cnf");
}
if (can(capabilities, CAPABILITY_SWAP_CONFERENCE)) {
- builder.append(" CAPABILITY_SWAP_CONFERENCE");
+ builder.append(isLong ? " CAPABILITY_SWAP_CONFERENCE" : " swp_cnf");
}
if (can(capabilities, CAPABILITY_RESPOND_VIA_TEXT)) {
- builder.append(" CAPABILITY_RESPOND_VIA_TEXT");
+ builder.append(isLong ? " CAPABILITY_RESPOND_VIA_TEXT" : " txt");
}
if (can(capabilities, CAPABILITY_MUTE)) {
- builder.append(" CAPABILITY_MUTE");
+ builder.append(isLong ? " CAPABILITY_MUTE" : " mut");
}
if (can(capabilities, CAPABILITY_MANAGE_CONFERENCE)) {
- builder.append(" CAPABILITY_MANAGE_CONFERENCE");
+ builder.append(isLong ? " CAPABILITY_MANAGE_CONFERENCE" : " mng_cnf");
}
if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_RX)) {
- builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_RX");
+ builder.append(isLong ? " CAPABILITY_SUPPORTS_VT_LOCAL_RX" : " VTlrx");
}
if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_TX)) {
- builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_TX");
+ builder.append(isLong ? " CAPABILITY_SUPPORTS_VT_LOCAL_TX" : " VTltx");
}
if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL)) {
- builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL");
+ builder.append(isLong ? " CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL" : " VTlbi");
}
if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_RX)) {
- builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_RX");
+ builder.append(isLong ? " CAPABILITY_SUPPORTS_VT_REMOTE_RX" : " VTrrx");
}
if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_TX)) {
- builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_TX");
+ builder.append(isLong ? " CAPABILITY_SUPPORTS_VT_REMOTE_TX" : " VTrtx");
}
if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL)) {
- builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL");
+ builder.append(isLong ? " CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL" : " VTrbi");
}
if (can(capabilities, CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO)) {
- builder.append(" CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO");
+ builder.append(isLong ? " CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO" : " !v2a");
}
if (can(capabilities, CAPABILITY_SPEED_UP_MT_AUDIO)) {
- builder.append(" CAPABILITY_SPEED_UP_MT_AUDIO");
+ builder.append(isLong ? " CAPABILITY_SPEED_UP_MT_AUDIO" : " spd_aud");
}
if (can(capabilities, CAPABILITY_CAN_UPGRADE_TO_VIDEO)) {
- builder.append(" CAPABILITY_CAN_UPGRADE_TO_VIDEO");
+ builder.append(isLong ? " CAPABILITY_CAN_UPGRADE_TO_VIDEO" : " a2v");
}
if (can(capabilities, CAPABILITY_CAN_PAUSE_VIDEO)) {
- builder.append(" CAPABILITY_CAN_PAUSE_VIDEO");
+ builder.append(isLong ? " CAPABILITY_CAN_PAUSE_VIDEO" : " paus_VT");
}
if (can(capabilities, CAPABILITY_CONFERENCE_HAS_NO_CHILDREN)) {
- builder.append(" CAPABILITY_SINGLE_PARTY_CONFERENCE");
+ builder.append(isLong ? " CAPABILITY_SINGLE_PARTY_CONFERENCE" : " 1p_cnf");
}
if (can(capabilities, CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION)) {
- builder.append(" CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION");
+ builder.append(isLong ? " CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION" : " rsp_by_con");
}
if (can(capabilities, CAPABILITY_CAN_PULL_CALL)) {
- builder.append(" CAPABILITY_CAN_PULL_CALL");
+ builder.append(isLong ? " CAPABILITY_CAN_PULL_CALL" : " pull");
}
builder.append("]");
@@ -511,34 +628,55 @@ public abstract class Connection extends Conferenceable {
}
/**
- * Builds a string representation of a properties bit-mask.
+ * Renders a set of property bits ({@code PROPERTY_*}) as a human readable string.
*
- * @param properties The properties bit-mask.
- * @return String representation.
- * @hide
+ * @param properties A property bit field.
+ * @return A human readable string representation.
*/
public static String propertiesToString(int properties) {
+ return propertiesToStringInternal(properties, true /* isLong */);
+ }
+
+ /**
+ * Renders a set of property bits ({@code PROPERTY_*}) as a *short* human readable string.
+ *
+ * @param properties A property bit field.
+ * @return A human readable string representation.
+ * @hide
+ */
+ public static String propertiesToStringShort(int properties) {
+ return propertiesToStringInternal(properties, false /* isLong */);
+ }
+
+ private static String propertiesToStringInternal(int properties, boolean isLong) {
StringBuilder builder = new StringBuilder();
- builder.append("[Properties:");
+ builder.append("[");
+ if (isLong) {
+ builder.append("Properties:");
+ }
if (can(properties, PROPERTY_SHOW_CALLBACK_NUMBER)) {
- builder.append(" PROPERTY_SHOW_CALLBACK_NUMBER");
+ builder.append(isLong ? " PROPERTY_SHOW_CALLBACK_NUMBER" : " clbk");
}
if (can(properties, PROPERTY_HIGH_DEF_AUDIO)) {
- builder.append(" PROPERTY_HIGH_DEF_AUDIO");
+ builder.append(isLong ? " PROPERTY_HIGH_DEF_AUDIO" : " HD");
}
if (can(properties, PROPERTY_WIFI)) {
- builder.append(" PROPERTY_WIFI");
+ builder.append(isLong ? " PROPERTY_WIFI" : " wifi");
}
if (can(properties, PROPERTY_GENERIC_CONFERENCE)) {
- builder.append(" PROPERTY_GENERIC_CONFERENCE");
+ builder.append(isLong ? " PROPERTY_GENERIC_CONFERENCE" : " gen_conf");
}
if (can(properties, PROPERTY_IS_EXTERNAL_CALL)) {
- builder.append(" PROPERTY_IS_EXTERNAL_CALL");
+ builder.append(isLong ? " PROPERTY_IS_EXTERNAL_CALL" : " xtrnl");
+ }
+
+ if (can(properties, PROPERTY_HAS_CDMA_VOICE_PRIVACY)) {
+ builder.append(isLong ? " PROPERTY_HAS_CDMA_VOICE_PRIVACY" : " priv");
}
builder.append("]");
@@ -574,6 +712,8 @@ public abstract class Connection extends Conferenceable {
public void onExtrasChanged(Connection c, Bundle extras) {}
public void onExtrasRemoved(Connection c, List<String> keys) {}
public void onConnectionEvent(Connection c, String event, Bundle extras) {}
+ /** @hide */
+ public void onConferenceSupportedChanged(Connection c, boolean isConferenceSupported) {}
}
/**
@@ -1385,6 +1525,15 @@ public abstract class Connection extends Conferenceable {
/**
* Returns the extras associated with this connection.
+ * <p>
+ * Extras should be updated using {@link #putExtras(Bundle)}.
+ * <p>
+ * Telecom or an {@link InCallService} can also update the extras via
+ * {@link android.telecom.Call#putExtras(Bundle)}, and
+ * {@link Call#removeExtras(List)}.
+ * <p>
+ * The connection is notified of changes to the extras made by Telecom or an
+ * {@link InCallService} by {@link #onExtrasChanged(Bundle)}.
*
* @return The extras associated with this connection.
*/
@@ -1472,6 +1621,8 @@ public abstract class Connection extends Conferenceable {
return "RINGING";
case STATE_DIALING:
return "DIALING";
+ case STATE_PULLING_CALL:
+ return "PULLING_CALL";
case STATE_ACTIVE:
return "ACTIVE";
case STATE_HOLDING:
@@ -1493,7 +1644,6 @@ public abstract class Connection extends Conferenceable {
/**
* Returns the connection's properties, as a bit mask of the {@code PROPERTY_*} constants.
- * @hide
*/
public final int getConnectionProperties() {
return mConnectionProperties;
@@ -1594,6 +1744,16 @@ public abstract class Connection extends Conferenceable {
}
/**
+ * Sets state to pulling (e.g. the connection is being pulled to the local device from another
+ * device). Only applicable for {@link Connection}s with
+ * {@link Connection#PROPERTY_IS_EXTERNAL_CALL} and {@link Connection#CAPABILITY_CAN_PULL_CALL}.
+ */
+ public final void setPulling() {
+ checkImmutable();
+ setState(STATE_PULLING_CALL);
+ }
+
+ /**
* Sets state to be on hold.
*/
public final void setOnHold() {
@@ -1699,7 +1859,6 @@ public abstract class Connection extends Conferenceable {
* Sets the connection's properties as a bit mask of the {@code PROPERTY_*} constants.
*
* @param connectionProperties The new connection properties.
- * @hide
*/
public final void setConnectionProperties(int connectionProperties) {
checkImmutable();
@@ -1880,6 +2039,9 @@ public abstract class Connection extends Conferenceable {
* New or existing keys are replaced in the {@code Connection} extras. Keys which are no longer
* in the new extras, but were present the last time {@code setExtras} was called are removed.
* <p>
+ * Alternatively you may use the {@link #putExtras(Bundle)}, and
+ * {@link #removeExtras(String...)} methods to modify the extras.
+ * <p>
* No assumptions should be made as to how an In-Call UI or service will handle these extras.
* Keys should be fully qualified (e.g., com.example.MY_EXTRA) to avoid conflicts.
*
@@ -1924,7 +2086,6 @@ public abstract class Connection extends Conferenceable {
* Keys should be fully qualified (e.g., com.example.MY_EXTRA) to avoid conflicts.
*
* @param extras The extras to add.
- * @hide
*/
public final void putExtras(@NonNull Bundle extras) {
checkImmutable();
@@ -1988,10 +2149,9 @@ public abstract class Connection extends Conferenceable {
}
/**
- * Removes an extra from this {@code Connection}.
+ * Removes extras from this {@code Connection}.
*
- * @param keys The key of the extra key to remove.
- * @hide
+ * @param keys The keys of the extras to remove.
*/
public final void removeExtras(List<String> keys) {
synchronized (mExtrasLock) {
@@ -2008,6 +2168,15 @@ public abstract class Connection extends Conferenceable {
}
/**
+ * Removes extras from this {@code Connection}.
+ *
+ * @param keys The keys of the extras to remove.
+ */
+ public final void removeExtras(String ... keys) {
+ removeExtras(Arrays.asList(keys));
+ }
+
+ /**
* Notifies this Connection that the {@link #getAudioState()} property has a new value.
*
* @param state The new connection audio state.
@@ -2129,7 +2298,6 @@ public abstract class Connection extends Conferenceable {
* capability and {@link Connection#PROPERTY_IS_EXTERNAL_CALL} property bits must be set.
* <p>
* For more information on external calls, see {@link Connection#PROPERTY_IS_EXTERNAL_CALL}.
- * @hide
*/
public void onPullExternalCall() {}
@@ -2138,11 +2306,16 @@ public abstract class Connection extends Conferenceable {
* <p>
* The {@link InCallService} issues a Call event via {@link Call#sendCallEvent(String, Bundle)}.
* <p>
+ * Where possible, the Connection should make an attempt to handle {@link Call} events which
+ * are part of the {@code android.telecom.*} namespace. The Connection should ignore any events
+ * it does not wish to handle. Unexpected events should be handled gracefully, as it is
+ * possible that a {@link InCallService} has defined its own Call events which a Connection is
+ * not aware of.
+ * <p>
* See also {@link Call#sendCallEvent(String, Bundle)}.
*
* @param event The call event.
* @param extras Extras associated with the call event.
- * @hide
*/
public void onCallEvent(String event, Bundle extras) {}
@@ -2155,7 +2328,6 @@ public abstract class Connection extends Conferenceable {
* {@link Call#removeExtras(List)}.
*
* @param extras The new extras bundle.
- * @hide
*/
public void onExtrasChanged(Bundle extras) {}
@@ -2330,17 +2502,54 @@ public abstract class Connection extends Conferenceable {
}
/**
- * Sends an event associated with this {@code Connection}, with associated event extras.
- *
- * Events are exposed to {@link InCallService} implementations via the
- * {@link Call.Callback#onConnectionEvent(Call, String, Bundle)} API.
- *
+ * Notifies listeners 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.
+ * @hide
+ */
+ protected void notifyConferenceSupportedChanged(boolean isConferenceSupported) {
+ for (Listener l : mListeners) {
+ l.onConferenceSupportedChanged(this, isConferenceSupported);
+ }
+ }
+
+ /**
+ * Sends an event associated with this {@code Connection} with associated event extras to the
+ * {@link InCallService}.
+ * <p>
+ * Connection events are used to communicate point in time information from a
+ * {@link ConnectionService} to a {@link InCallService} implementations. An example of a
+ * custom connection event includes notifying the UI when a WIFI call has been handed over to
+ * LTE, which the InCall UI might use to inform the user that billing charges may apply. The
+ * Android Telephony framework will send the {@link #EVENT_CALL_MERGE_FAILED} connection event
+ * when a call to {@link Call#mergeConference()} has failed to complete successfully. A
+ * connection event could also be used to trigger UI in the {@link InCallService} which prompts
+ * the user to make a choice (e.g. whether they want to incur roaming costs for making a call),
+ * which is communicated back via {@link Call#sendCallEvent(String, Bundle)}.
+ * <p>
+ * Events are exposed to {@link InCallService} implementations via
+ * {@link Call.Callback#onConnectionEvent(Call, String, Bundle)}.
+ * <p>
* No assumptions should be made as to how an In-Call UI or service will handle these events.
- * Events should be fully qualified (e.g., com.example.event.MY_EVENT) to avoid conflicts.
+ * The {@link ConnectionService} must assume that the In-Call UI could even chose to ignore
+ * some events altogether.
+ * <p>
+ * Events should be fully qualified (e.g. {@code com.example.event.MY_EVENT}) to avoid
+ * conflicts between {@link ConnectionService} implementations. Further, custom
+ * {@link ConnectionService} implementations shall not re-purpose events in the
+ * {@code android.*} namespace, nor shall they define new event types in this namespace. When
+ * defining a custom event type, ensure the contents of the extras {@link Bundle} is clearly
+ * defined. Extra keys for this bundle should be named similar to the event type (e.g.
+ * {@code com.example.extra.MY_EXTRA}).
+ * <p>
+ * When defining events and the associated extras, it is important to keep their behavior
+ * consistent when the associated {@link ConnectionService} is updated. Support for deprecated
+ * events/extras should me maintained to ensure backwards compatibility with older
+ * {@link InCallService} implementations which were built to support the older behavior.
*
* @param event The connection event.
- * @param extras Bundle containing extra information associated with the event.
- * @hide
+ * @param extras Optional bundle containing extra information associated with the event.
*/
public void sendConnectionEvent(String event, Bundle extras) {
for (Listener l : mListeners) {