/* * Copyright (C) 2014 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 android.telecom; import android.annotation.SystemApi; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import java.lang.String; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.CopyOnWriteArrayList; /** * Represents an ongoing phone call that the in-call app should present to the user. */ public final class Call { /** * The state of a {@code Call} when newly created. */ public static final int STATE_NEW = 0; /** * The state of an outgoing {@code Call} when dialing the remote number, but not yet connected. */ public static final int STATE_DIALING = 1; /** * The state of an incoming {@code Call} when ringing locally, but not yet connected. */ public static final int STATE_RINGING = 2; /** * The state of a {@code Call} when in a holding state. */ public static final int STATE_HOLDING = 3; /** * The state of a {@code Call} when actively supporting conversation. */ public static final int STATE_ACTIVE = 4; /** * The state of a {@code Call} when no further voice or other communication is being * transmitted, the remote side has been or will inevitably be informed that the {@code Call} * is no longer active, and the local data transport has or inevitably will release resources * associated with this {@code Call}. */ public static final int STATE_DISCONNECTED = 7; /** * The state of an outgoing {@code Call} when waiting on user to select a * {@link PhoneAccount} through which to place the call. */ public static final int STATE_SELECT_PHONE_ACCOUNT = 8; /** * @hide * @deprecated use STATE_SELECT_PHONE_ACCOUNT. */ @Deprecated @SystemApi public static final int STATE_PRE_DIAL_WAIT = STATE_SELECT_PHONE_ACCOUNT; /** * The initial state of an outgoing {@code Call}. * Common transitions are to {@link #STATE_DIALING} state for a successful call or * {@link #STATE_DISCONNECTED} if it failed. */ public static final int STATE_CONNECTING = 9; /** * The state of a {@code Call} when the user has initiated a disconnection of the call, but the * call has not yet been disconnected by the underlying {@code ConnectionService}. The next * state of the call is (potentially) {@link #STATE_DISCONNECTED}. */ public static final int STATE_DISCONNECTING = 10; /** * The key to retrieve the optional {@code PhoneAccount}s Telecom can bundle with its Call * extras. Used to pass the phone accounts to display on the front end to the user in order to * select phone accounts to (for example) place a call. */ public static final String AVAILABLE_PHONE_ACCOUNTS = "selectPhoneAccountAccounts"; public static class Details { /** Call can currently be put on hold or unheld. */ public static final int CAPABILITY_HOLD = 0x00000001; /** Call supports the hold feature. */ public static final int CAPABILITY_SUPPORT_HOLD = 0x00000002; /** * Calls within a conference can be merged. A {@link ConnectionService} has the option to * add a {@link Conference} call before the child {@link Connection}s are merged. This is how * CDMA-based {@link Connection}s are implemented. For these unmerged {@link Conference}s, this * capability allows a merge button to be shown while the conference call is in the foreground * of the in-call UI. *
* This is only intended for use by a {@link Conference}. */ public static final int CAPABILITY_MERGE_CONFERENCE = 0x00000004; /** * Calls within a conference can be swapped between foreground and background. * See {@link #CAPABILITY_MERGE_CONFERENCE} for additional information. *
* This is only intended for use by a {@link Conference}.
*/
public static final int CAPABILITY_SWAP_CONFERENCE = 0x00000008;
/**
* @hide
*/
public static final int CAPABILITY_UNUSED_1 = 0x00000010;
/** Call supports responding via text option. */
public static final int CAPABILITY_RESPOND_VIA_TEXT = 0x00000020;
/** Call can be muted. */
public static final int CAPABILITY_MUTE = 0x00000040;
/**
* Call supports conference call management. This capability only applies to {@link Conference}
* calls which can have {@link Connection}s as children.
*/
public static final int CAPABILITY_MANAGE_CONFERENCE = 0x00000080;
/**
* Local device supports receiving video.
*/
public static final int CAPABILITY_SUPPORTS_VT_LOCAL_RX = 0x00000100;
/**
* Local device supports transmitting video.
*/
public static final int CAPABILITY_SUPPORTS_VT_LOCAL_TX = 0x00000200;
/**
* Local device supports bidirectional video calling.
*/
public static final int CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL =
CAPABILITY_SUPPORTS_VT_LOCAL_RX | CAPABILITY_SUPPORTS_VT_LOCAL_TX;
/**
* Remote device supports receiving video.
*/
public static final int CAPABILITY_SUPPORTS_VT_REMOTE_RX = 0x00000400;
/**
* Remote device supports transmitting video.
*/
public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 0x00000800;
/**
* Remote device supports bidirectional video calling.
*/
public static final int CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL =
CAPABILITY_SUPPORTS_VT_REMOTE_RX | CAPABILITY_SUPPORTS_VT_REMOTE_TX;
/**
* Call is able to be separated from its parent {@code Conference}, if any.
*/
public static final int CAPABILITY_SEPARATE_FROM_CONFERENCE = 0x00001000;
/**
* Call is able to be individually disconnected when in a {@code Conference}.
*/
public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 0x00002000;
/**
* Speed up audio setup for MT call.
* @hide
*/
public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00040000;
/**
* Call can be upgraded to a video call.
* @hide
*/
public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 0x00080000;
/**
* For video calls, indicates whether the outgoing video for the call can be paused using
* the {@link android.telecom.VideoProfile#STATE_PAUSED} VideoState.
*/
public static final int CAPABILITY_CAN_PAUSE_VIDEO = 0x00100000;
//******************************************************************************************
// Next CAPABILITY value: 0x00004000
//******************************************************************************************
/**
* Whether the call is currently a conference.
*/
public static final int PROPERTY_CONFERENCE = 0x00000001;
/**
* Whether the call is a generic conference, where we do not know the precise state of
* participants in the conference (eg. on CDMA).
*/
public static final int PROPERTY_GENERIC_CONFERENCE = 0x00000002;
/**
* Whether the call is made while the device is in emergency callback mode.
*/
public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 0x00000004;
/**
* Connection is using WIFI.
*/
public static final int PROPERTY_WIFI = 0x00000008;
/**
* Call is using high definition audio.
*/
public static final int PROPERTY_HIGH_DEF_AUDIO = 0x00000010;
//******************************************************************************************
// Next PROPERTY value: 0x00000020
//******************************************************************************************
private final Uri mHandle;
private final int mHandlePresentation;
private final String mCallerDisplayName;
private final int mCallerDisplayNamePresentation;
private final PhoneAccountHandle mAccountHandle;
private final int mCallCapabilities;
private final int mCallProperties;
private final DisconnectCause mDisconnectCause;
private final long mConnectTimeMillis;
private final GatewayInfo mGatewayInfo;
private final int mVideoState;
private final StatusHints mStatusHints;
private final Bundle mExtras;
private final Bundle mIntentExtras;
/**
* Whether the supplied capabilities supports the specified capability.
*
* @param capabilities A bit field of capabilities.
* @param capability The capability to check capabilities for.
* @return Whether the specified capability is supported.
*/
public static boolean can(int capabilities, int capability) {
return (capabilities & capability) != 0;
}
/**
* Whether the capabilities of this {@code Details} supports the specified capability.
*
* @param capability The capability to check capabilities for.
* @return Whether the specified capability is supported.
*/
public boolean can(int capability) {
return can(mCallCapabilities, capability);
}
/**
* Render 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) {
StringBuilder builder = new StringBuilder();
builder.append("[Capabilities:");
if (can(capabilities, CAPABILITY_HOLD)) {
builder.append(" CAPABILITY_HOLD");
}
if (can(capabilities, CAPABILITY_SUPPORT_HOLD)) {
builder.append(" CAPABILITY_SUPPORT_HOLD");
}
if (can(capabilities, CAPABILITY_MERGE_CONFERENCE)) {
builder.append(" CAPABILITY_MERGE_CONFERENCE");
}
if (can(capabilities, CAPABILITY_SWAP_CONFERENCE)) {
builder.append(" CAPABILITY_SWAP_CONFERENCE");
}
if (can(capabilities, CAPABILITY_RESPOND_VIA_TEXT)) {
builder.append(" CAPABILITY_RESPOND_VIA_TEXT");
}
if (can(capabilities, CAPABILITY_MUTE)) {
builder.append(" CAPABILITY_MUTE");
}
if (can(capabilities, CAPABILITY_MANAGE_CONFERENCE)) {
builder.append(" CAPABILITY_MANAGE_CONFERENCE");
}
if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_RX)) {
builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_RX");
}
if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_TX)) {
builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_TX");
}
if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL)) {
builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL");
}
if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_RX)) {
builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_RX");
}
if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_TX)) {
builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_TX");
}
if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL)) {
builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL");
}
if (can(capabilities, CAPABILITY_SPEED_UP_MT_AUDIO)) {
builder.append(" CAPABILITY_SPEED_UP_MT_AUDIO");
}
if (can(capabilities, CAPABILITY_CAN_UPGRADE_TO_VIDEO)) {
builder.append(" CAPABILITY_CAN_UPGRADE_TO_VIDEO");
}
if (can(capabilities, CAPABILITY_CAN_PAUSE_VIDEO)) {
builder.append(" CAPABILITY_CAN_PAUSE_VIDEO");
}
builder.append("]");
return builder.toString();
}
/**
* Whether the supplied properties includes the specified property.
*
* @param properties A bit field of properties.
* @param property The property to check properties for.
* @return Whether the specified property is supported.
*/
public static boolean hasProperty(int properties, int property) {
return (properties & property) != 0;
}
/**
* Whether the properties of this {@code Details} includes the specified property.
*
* @param property The property to check properties for.
* @return Whether the specified property is supported.
*/
public boolean hasProperty(int property) {
return hasProperty(mCallProperties, property);
}
/**
* Render a set of property bits ({@code PROPERTY_*}) as a human readable string.
*
* @param properties A property bit field.
* @return A human readable string representation.
*/
public static String propertiesToString(int properties) {
StringBuilder builder = new StringBuilder();
builder.append("[Properties:");
if (hasProperty(properties, PROPERTY_CONFERENCE)) {
builder.append(" PROPERTY_CONFERENCE");
}
if (hasProperty(properties, PROPERTY_GENERIC_CONFERENCE)) {
builder.append(" PROPERTY_GENERIC_CONFERENCE");
}
if (hasProperty(properties, PROPERTY_WIFI)) {
builder.append(" PROPERTY_WIFI");
}
if (hasProperty(properties, PROPERTY_HIGH_DEF_AUDIO)) {
builder.append(" PROPERTY_HIGH_DEF_AUDIO");
}
if (hasProperty(properties, PROPERTY_EMERGENCY_CALLBACK_MODE)) {
builder.append(" PROPERTY_EMERGENCY_CALLBACK_MODE");
}
builder.append("]");
return builder.toString();
}
/**
* @return The handle (e.g., phone number) to which the {@code Call} is currently
* connected.
*/
public Uri getHandle() {
return mHandle;
}
/**
* @return The presentation requirements for the handle. See
* {@link TelecomManager} for valid values.
*/
public int getHandlePresentation() {
return mHandlePresentation;
}
/**
* @return The display name for the caller.
*/
public String getCallerDisplayName() {
return mCallerDisplayName;
}
/**
* @return The presentation requirements for the caller display name. See
* {@link TelecomManager} for valid values.
*/
public int getCallerDisplayNamePresentation() {
return mCallerDisplayNamePresentation;
}
/**
* @return The {@code PhoneAccountHandle} whereby the {@code Call} is currently being
* routed.
*/
public PhoneAccountHandle getAccountHandle() {
return mAccountHandle;
}
/**
* @return A bitmask of the capabilities of the {@code Call}, as defined by the various
* {@code CAPABILITY_*} constants in this class.
*/
public int getCallCapabilities() {
return mCallCapabilities;
}
/**
* @return A bitmask of the properties of the {@code Call}, as defined by the various
* {@code PROPERTY_*} constants in this class.
*/
public int getCallProperties() {
return mCallProperties;
}
/**
* @return For a {@link #STATE_DISCONNECTED} {@code Call}, the disconnect cause expressed
* by {@link android.telecom.DisconnectCause}.
*/
public DisconnectCause getDisconnectCause() {
return mDisconnectCause;
}
/**
* @return The time the {@code Call} has been connected. This information is updated
* periodically, but user interfaces should not rely on this to display any "call time
* clock".
*/
public final long getConnectTimeMillis() {
return mConnectTimeMillis;
}
/**
* @return Information about any calling gateway the {@code Call} may be using.
*/
public GatewayInfo getGatewayInfo() {
return mGatewayInfo;
}
/**
* @return The video state of the {@code Call}.
*/
public int getVideoState() {
return mVideoState;
}
/**
* @return The current {@link android.telecom.StatusHints}, or {@code null} if none
* have been set.
*/
public StatusHints getStatusHints() {
return mStatusHints;
}
/**
* @return The extras associated with this call.
*/
public Bundle getExtras() {
return mExtras;
}
/**
* @return The extras used with the original intent to place this call.
*/
public Bundle getIntentExtras() {
return mIntentExtras;
}
@Override
public boolean equals(Object o) {
if (o instanceof Details) {
Details d = (Details) o;
return
Objects.equals(mHandle, d.mHandle) &&
Objects.equals(mHandlePresentation, d.mHandlePresentation) &&
Objects.equals(mCallerDisplayName, d.mCallerDisplayName) &&
Objects.equals(mCallerDisplayNamePresentation,
d.mCallerDisplayNamePresentation) &&
Objects.equals(mAccountHandle, d.mAccountHandle) &&
Objects.equals(mCallCapabilities, d.mCallCapabilities) &&
Objects.equals(mCallProperties, d.mCallProperties) &&
Objects.equals(mDisconnectCause, d.mDisconnectCause) &&
Objects.equals(mConnectTimeMillis, d.mConnectTimeMillis) &&
Objects.equals(mGatewayInfo, d.mGatewayInfo) &&
Objects.equals(mVideoState, d.mVideoState) &&
Objects.equals(mStatusHints, d.mStatusHints) &&
Objects.equals(mExtras, d.mExtras) &&
Objects.equals(mIntentExtras, d.mIntentExtras);
}
return false;
}
@Override
public int hashCode() {
return
Objects.hashCode(mHandle) +
Objects.hashCode(mHandlePresentation) +
Objects.hashCode(mCallerDisplayName) +
Objects.hashCode(mCallerDisplayNamePresentation) +
Objects.hashCode(mAccountHandle) +
Objects.hashCode(mCallCapabilities) +
Objects.hashCode(mCallProperties) +
Objects.hashCode(mDisconnectCause) +
Objects.hashCode(mConnectTimeMillis) +
Objects.hashCode(mGatewayInfo) +
Objects.hashCode(mVideoState) +
Objects.hashCode(mStatusHints) +
Objects.hashCode(mExtras) +
Objects.hashCode(mIntentExtras);
}
/** {@hide} */
public Details(
Uri handle,
int handlePresentation,
String callerDisplayName,
int callerDisplayNamePresentation,
PhoneAccountHandle accountHandle,
int capabilities,
int properties,
DisconnectCause disconnectCause,
long connectTimeMillis,
GatewayInfo gatewayInfo,
int videoState,
StatusHints statusHints,
Bundle extras,
Bundle intentExtras) {
mHandle = handle;
mHandlePresentation = handlePresentation;
mCallerDisplayName = callerDisplayName;
mCallerDisplayNamePresentation = callerDisplayNamePresentation;
mAccountHandle = accountHandle;
mCallCapabilities = capabilities;
mCallProperties = properties;
mDisconnectCause = disconnectCause;
mConnectTimeMillis = connectTimeMillis;
mGatewayInfo = gatewayInfo;
mVideoState = videoState;
mStatusHints = statusHints;
mExtras = extras;
mIntentExtras = intentExtras;
}
}
public static abstract class Callback {
/**
* Invoked when the state of this {@code Call} has changed. See {@link #getState()}.
*
* @param call The {@code Call} invoking this method.
* @param state The new state of the {@code Call}.
*/
public void onStateChanged(Call call, int state) {}
/**
* Invoked when the parent of this {@code Call} has changed. See {@link #getParent()}.
*
* @param call The {@code Call} invoking this method.
* @param parent The new parent of the {@code Call}.
*/
public void onParentChanged(Call call, Call parent) {}
/**
* Invoked when the children of this {@code Call} have changed. See {@link #getChildren()}.
*
* @param call The {@code Call} invoking this method.
* @param children The new children of the {@code Call}.
*/
public void onChildrenChanged(Call call, List