2918 lines
		
	
	
		
			119 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			2918 lines
		
	
	
		
			119 KiB
		
	
	
	
		
			Java
		
	
	
	
| /*
 | |
|  * 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.IntDef;
 | |
| import android.annotation.NonNull;
 | |
| import android.annotation.Nullable;
 | |
| import android.annotation.SystemApi;
 | |
| import android.annotation.TestApi;
 | |
| import android.compat.annotation.UnsupportedAppUsage;
 | |
| import android.content.pm.ServiceInfo;
 | |
| import android.net.Uri;
 | |
| import android.os.Build;
 | |
| import android.os.Bundle;
 | |
| import android.os.Handler;
 | |
| import android.os.ParcelFileDescriptor;
 | |
| 
 | |
| import com.android.internal.telecom.IVideoProvider;
 | |
| 
 | |
| import java.io.IOException;
 | |
| import java.io.InputStreamReader;
 | |
| import java.io.OutputStreamWriter;
 | |
| import java.lang.annotation.Retention;
 | |
| import java.lang.annotation.RetentionPolicy;
 | |
| import java.nio.charset.StandardCharsets;
 | |
| import java.util.ArrayList;
 | |
| import java.util.Arrays;
 | |
| import java.util.Collections;
 | |
| 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 state of an external call which is in the process of being pulled from a remote device to
 | |
|      * the local device.
 | |
|      * <p>
 | |
|      * A call can only be in this state if the {@link Details#PROPERTY_IS_EXTERNAL_CALL} property
 | |
|      * and {@link Details#CAPABILITY_CAN_PULL_CALL} capability are set on the call.
 | |
|      * <p>
 | |
|      * An {@link InCallService} will only see this state if it has the
 | |
|      * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true} in its
 | |
|      * manifest.
 | |
|      */
 | |
|     public static final int STATE_PULLING_CALL = 11;
 | |
| 
 | |
|     /**
 | |
|      * The state of a call that is active with the network, but the audio from the call is
 | |
|      * being intercepted by an app on the local device. Telecom does not hold audio focus in this
 | |
|      * state, and the call will be invisible to the user except for a persistent notification.
 | |
|      */
 | |
|     public static final int STATE_AUDIO_PROCESSING = 12;
 | |
| 
 | |
|     /**
 | |
|      * The state of a call that is being presented to the user after being in
 | |
|      * {@link #STATE_AUDIO_PROCESSING}. The call is still active with the network in this case, and
 | |
|      * Telecom will hold audio focus and play a ringtone if appropriate.
 | |
|      */
 | |
|     public static final int STATE_SIMULATED_RINGING = 13;
 | |
| 
 | |
|     /**
 | |
|      * @hide
 | |
|      */
 | |
|     @IntDef(prefix = { "STATE_" },
 | |
|             value = {
 | |
|                     STATE_NEW,
 | |
|                     STATE_DIALING,
 | |
|                     STATE_RINGING,
 | |
|                     STATE_HOLDING,
 | |
|                     STATE_ACTIVE,
 | |
|                     STATE_DISCONNECTED,
 | |
|                     STATE_SELECT_PHONE_ACCOUNT,
 | |
|                     STATE_CONNECTING,
 | |
|                     STATE_DISCONNECTING,
 | |
|                     STATE_PULLING_CALL,
 | |
|                     STATE_AUDIO_PROCESSING,
 | |
|                     STATE_SIMULATED_RINGING
 | |
|             })
 | |
|     @Retention(RetentionPolicy.SOURCE)
 | |
|     public @interface CallState {};
 | |
| 
 | |
|     /**
 | |
|      * 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.
 | |
|      * @deprecated Use the list from {@link #EXTRA_SUGGESTED_PHONE_ACCOUNTS} instead.
 | |
|      */
 | |
|     @Deprecated
 | |
|     public static final String AVAILABLE_PHONE_ACCOUNTS = "selectPhoneAccountAccounts";
 | |
| 
 | |
|     /**
 | |
|      * Key for extra used to pass along a list of {@link PhoneAccountSuggestion}s to the in-call
 | |
|      * UI when a call enters the {@link #STATE_SELECT_PHONE_ACCOUNT} state. The list included here
 | |
|      * will have the same length and be in the same order as the list passed with
 | |
|      * {@link #AVAILABLE_PHONE_ACCOUNTS}.
 | |
|      */
 | |
|     public static final String EXTRA_SUGGESTED_PHONE_ACCOUNTS =
 | |
|             "android.telecom.extra.SUGGESTED_PHONE_ACCOUNTS";
 | |
| 
 | |
|     /**
 | |
|      * Extra key used to indicate the time (in milliseconds since midnight, January 1, 1970 UTC)
 | |
|      * when the last outgoing emergency call was made.  This is used to identify potential emergency
 | |
|      * callbacks.
 | |
|      */
 | |
|     public static final String EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS =
 | |
|             "android.telecom.extra.LAST_EMERGENCY_CALLBACK_TIME_MILLIS";
 | |
| 
 | |
| 
 | |
|     /**
 | |
|      * Extra key used to indicate whether a {@link CallScreeningService} has requested to silence
 | |
|      * the ringtone for a call.  If the {@link InCallService} declares
 | |
|      * {@link TelecomManager#METADATA_IN_CALL_SERVICE_RINGING} in its manifest, it should not
 | |
|      * play a ringtone for an incoming call with this extra key set.
 | |
|      */
 | |
|     public static final String EXTRA_SILENT_RINGING_REQUESTED =
 | |
|             "android.telecom.extra.SILENT_RINGING_REQUESTED";
 | |
| 
 | |
|     /**
 | |
|      * Call event sent from a {@link Call} via {@link #sendCallEvent(String, Bundle)} to inform
 | |
|      * Telecom that the user has requested that the current {@link Call} should be handed over
 | |
|      * to another {@link ConnectionService}.
 | |
|      * <p>
 | |
|      * The caller must specify the {@link #EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE} to indicate to
 | |
|      * Telecom which {@link PhoneAccountHandle} the {@link Call} should be handed over to.
 | |
|      * @hide
 | |
|      * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
 | |
|      * APIs instead.
 | |
|      */
 | |
|     public static final String EVENT_REQUEST_HANDOVER =
 | |
|             "android.telecom.event.REQUEST_HANDOVER";
 | |
| 
 | |
|     /**
 | |
|      * Extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event.  Specifies the
 | |
|      * {@link PhoneAccountHandle} to which a call should be handed over to.
 | |
|      * @hide
 | |
|      * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
 | |
|      * APIs instead.
 | |
|      */
 | |
|     public static final String EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE =
 | |
|             "android.telecom.extra.HANDOVER_PHONE_ACCOUNT_HANDLE";
 | |
| 
 | |
|     /**
 | |
|      * Integer extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event.  Specifies the
 | |
|      * video state of the call when it is handed over to the new {@link PhoneAccount}.
 | |
|      * <p>
 | |
|      * Valid values: {@link VideoProfile#STATE_AUDIO_ONLY},
 | |
|      * {@link VideoProfile#STATE_BIDIRECTIONAL}, {@link VideoProfile#STATE_RX_ENABLED}, and
 | |
|      * {@link VideoProfile#STATE_TX_ENABLED}.
 | |
|      * @hide
 | |
|      * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
 | |
|      * APIs instead.
 | |
|      */
 | |
|     public static final String EXTRA_HANDOVER_VIDEO_STATE =
 | |
|             "android.telecom.extra.HANDOVER_VIDEO_STATE";
 | |
| 
 | |
|     /**
 | |
|      * Extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event.  Used by the
 | |
|      * {@link InCallService} initiating a handover to provide a {@link Bundle} with extra
 | |
|      * information to the handover {@link ConnectionService} specified by
 | |
|      * {@link #EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE}.
 | |
|      * <p>
 | |
|      * This {@link Bundle} is not interpreted by Telecom, but passed as-is to the
 | |
|      * {@link ConnectionService} via the request extras when
 | |
|      * {@link ConnectionService#onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}
 | |
|      * is called to initate the handover.
 | |
|      * @hide
 | |
|      * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
 | |
|      * APIs instead.
 | |
|      */
 | |
|     public static final String EXTRA_HANDOVER_EXTRAS = "android.telecom.extra.HANDOVER_EXTRAS";
 | |
| 
 | |
|     /**
 | |
|      * Call event sent from Telecom to the handover {@link ConnectionService} via
 | |
|      * {@link Connection#onCallEvent(String, Bundle)} to inform a {@link Connection} that a handover
 | |
|      * to the {@link ConnectionService} has completed successfully.
 | |
|      * <p>
 | |
|      * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
 | |
|      * @hide
 | |
|      * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
 | |
|      * APIs instead.
 | |
|      */
 | |
|     public static final String EVENT_HANDOVER_COMPLETE =
 | |
|             "android.telecom.event.HANDOVER_COMPLETE";
 | |
| 
 | |
|     /**
 | |
|      * Call event sent from Telecom to the handover destination {@link ConnectionService} via
 | |
|      * {@link Connection#onCallEvent(String, Bundle)} to inform the handover destination that the
 | |
|      * source connection has disconnected.  The {@link Bundle} parameter for the call event will be
 | |
|      * {@code null}.
 | |
|      * <p>
 | |
|      * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
 | |
|      * @hide
 | |
|      * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
 | |
|      * APIs instead.
 | |
|      */
 | |
|     public static final String EVENT_HANDOVER_SOURCE_DISCONNECTED =
 | |
|             "android.telecom.event.HANDOVER_SOURCE_DISCONNECTED";
 | |
| 
 | |
|     /**
 | |
|      * Call event sent from Telecom to the handover {@link ConnectionService} via
 | |
|      * {@link Connection#onCallEvent(String, Bundle)} to inform a {@link Connection} that a handover
 | |
|      * to the {@link ConnectionService} has failed.
 | |
|      * <p>
 | |
|      * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
 | |
|      * @hide
 | |
|      * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
 | |
|      * APIs instead.
 | |
|      */
 | |
|     public static final String EVENT_HANDOVER_FAILED =
 | |
|             "android.telecom.event.HANDOVER_FAILED";
 | |
| 
 | |
|     /**
 | |
|      * Event reported from the Telecom stack to report an in-call diagnostic message which the
 | |
|      * dialer app may opt to display to the user.  A diagnostic message is used to communicate
 | |
|      * scenarios the device has detected which may impact the quality of the ongoing call.
 | |
|      * <p>
 | |
|      * For example a problem with a bluetooth headset may generate a recommendation for the user to
 | |
|      * try using the speakerphone instead, or if the device detects it has entered a poor service
 | |
|      * area, the user might be warned so that they can finish their call prior to it dropping.
 | |
|      * <p>
 | |
|      * A diagnostic message is considered persistent in nature.  When the user enters a poor service
 | |
|      * area, for example, the accompanying diagnostic message persists until they leave the area
 | |
|      * of poor service.  Each message is accompanied with a {@link #EXTRA_DIAGNOSTIC_MESSAGE_ID}
 | |
|      * which uniquely identifies the diagnostic condition being reported.  The framework raises a
 | |
|      * call event of type {@link #EVENT_CLEAR_DIAGNOSTIC_MESSAGE} when the condition reported has
 | |
|      * been cleared.  The dialer app should display the diagnostic message until it is cleared.
 | |
|      * If multiple diagnostic messages are sent with different IDs (which have not yet been cleared)
 | |
|      * the dialer app should prioritize the most recently received message, but still provide the
 | |
|      * user with a means to review past messages.
 | |
|      * <p>
 | |
|      * The text of the message is found in {@link #EXTRA_DIAGNOSTIC_MESSAGE} in the form of a human
 | |
|      * readable {@link CharSequence} which is intended for display in the call UX.
 | |
|      * <p>
 | |
|      * The telecom framework audibly notifies the user of the presence of a diagnostic message, so
 | |
|      * the dialer app needs only to concern itself with visually displaying the message.
 | |
|      * <p>
 | |
|      * The dialer app receives this event via
 | |
|      * {@link Call.Callback#onConnectionEvent(Call, String, Bundle)}.
 | |
|      */
 | |
|     public static final String EVENT_DISPLAY_DIAGNOSTIC_MESSAGE =
 | |
|             "android.telecom.event.DISPLAY_DIAGNOSTIC_MESSAGE";
 | |
| 
 | |
|     /**
 | |
|      * Event reported from the telecom framework when a diagnostic message previously raised with
 | |
|      * {@link #EVENT_DISPLAY_DIAGNOSTIC_MESSAGE} has cleared and is no longer pertinent.
 | |
|      * <p>
 | |
|      * The {@link #EXTRA_DIAGNOSTIC_MESSAGE_ID} indicates the diagnostic message which has been
 | |
|      * cleared.
 | |
|      * <p>
 | |
|      * The dialer app receives this event via
 | |
|      * {@link Call.Callback#onConnectionEvent(Call, String, Bundle)}.
 | |
|      */
 | |
|     public static final String EVENT_CLEAR_DIAGNOSTIC_MESSAGE =
 | |
|             "android.telecom.event.CLEAR_DIAGNOSTIC_MESSAGE";
 | |
| 
 | |
|     /**
 | |
|      * Integer extra representing a message ID for a message posted via
 | |
|      * {@link #EVENT_DISPLAY_DIAGNOSTIC_MESSAGE}.  Used to ensure that the dialer app knows when
 | |
|      * the message in question has cleared via {@link #EVENT_CLEAR_DIAGNOSTIC_MESSAGE}.
 | |
|      */
 | |
|     public static final String EXTRA_DIAGNOSTIC_MESSAGE_ID =
 | |
|             "android.telecom.extra.DIAGNOSTIC_MESSAGE_ID";
 | |
| 
 | |
|     /**
 | |
|      * {@link CharSequence} extra used with {@link #EVENT_DISPLAY_DIAGNOSTIC_MESSAGE}.  This is the
 | |
|      * diagnostic message the dialer app should display.
 | |
|      */
 | |
|     public static final String EXTRA_DIAGNOSTIC_MESSAGE =
 | |
|             "android.telecom.extra.DIAGNOSTIC_MESSAGE";
 | |
| 
 | |
|     /**
 | |
|      * Reject reason used with {@link #reject(int)} to indicate that the user is rejecting this
 | |
|      * call because they have declined to answer it.  This typically means that they are unable
 | |
|      * to answer the call at this time and would prefer it be sent to voicemail.
 | |
|      */
 | |
|     public static final int REJECT_REASON_DECLINED = 1;
 | |
| 
 | |
|     /**
 | |
|      * Reject reason used with {@link #reject(int)} to indicate that the user is rejecting this
 | |
|      * call because it is an unwanted call.  This allows the user to indicate that they are
 | |
|      * rejecting a call because it is likely a nuisance call.
 | |
|      */
 | |
|     public static final int REJECT_REASON_UNWANTED = 2;
 | |
| 
 | |
|     /**
 | |
|      * @hide
 | |
|      */
 | |
|     @IntDef(prefix = { "REJECT_REASON_" },
 | |
|             value = {REJECT_REASON_DECLINED, REJECT_REASON_UNWANTED})
 | |
|     @Retention(RetentionPolicy.SOURCE)
 | |
|     public @interface RejectReason {};
 | |
| 
 | |
|     public static class Details {
 | |
|         /** @hide */
 | |
|         @Retention(RetentionPolicy.SOURCE)
 | |
|         @IntDef(
 | |
|                 prefix = { "DIRECTION_" },
 | |
|                 value = {DIRECTION_UNKNOWN, DIRECTION_INCOMING, DIRECTION_OUTGOING})
 | |
|         public @interface CallDirection {}
 | |
| 
 | |
|         /**
 | |
|          * Indicates that the call is neither and incoming nor an outgoing call.  This can be the
 | |
|          * case for calls reported directly by a {@link ConnectionService} in special cases such as
 | |
|          * call handovers.
 | |
|          */
 | |
|         public static final int DIRECTION_UNKNOWN = -1;
 | |
| 
 | |
|         /**
 | |
|          * Indicates that the call is an incoming call.
 | |
|          */
 | |
|         public static final int DIRECTION_INCOMING = 0;
 | |
| 
 | |
|         /**
 | |
|          * Indicates that the call is an outgoing call.
 | |
|          */
 | |
|         public static final int DIRECTION_OUTGOING = 1;
 | |
| 
 | |
|         /** 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.
 | |
|          * <p>
 | |
|          * 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.
 | |
|          * <p>
 | |
|          * 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
 | |
|          * @deprecated Use {@link #CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL} and
 | |
|          * {@link #CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL} to indicate for a call
 | |
|          * whether or not video calling is supported.
 | |
|          */
 | |
|         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 119305590)
 | |
|         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;
 | |
| 
 | |
|         /**
 | |
|          * Call sends responses through connection.
 | |
|          * @hide
 | |
|          */
 | |
|         public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 0x00200000;
 | |
| 
 | |
|         /**
 | |
|          * When set, prevents a video {@code Call} from being downgraded to an audio-only call.
 | |
|          * <p>
 | |
|          * Should be set when the VideoState has the {@link VideoProfile#STATE_TX_ENABLED} or
 | |
|          * {@link VideoProfile#STATE_RX_ENABLED} bits set to indicate that the connection cannot be
 | |
|          * downgraded from a video call back to a VideoState of
 | |
|          * {@link VideoProfile#STATE_AUDIO_ONLY}.
 | |
|          * <p>
 | |
|          * Intuitively, a call which can be downgraded to audio should also have local and remote
 | |
|          * video
 | |
|          * capabilities (see {@link #CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL} and
 | |
|          * {@link #CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL}).
 | |
|          */
 | |
|         public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 0x00400000;
 | |
| 
 | |
|         /**
 | |
|          * When set for an external call, indicates that this {@code Call} can be pulled from a
 | |
|          * remote device to the current device.
 | |
|          * <p>
 | |
|          * Should only be set on a {@code Call} where {@link #PROPERTY_IS_EXTERNAL_CALL} is set.
 | |
|          * <p>
 | |
|          * An {@link InCallService} will only see calls with this capability if it has the
 | |
|          * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
 | |
|          * in its manifest.
 | |
|          * <p>
 | |
|          * See {@link Connection#CAPABILITY_CAN_PULL_CALL} and
 | |
|          * {@link Connection#PROPERTY_IS_EXTERNAL_CALL}.
 | |
|          */
 | |
|         public static final int CAPABILITY_CAN_PULL_CALL = 0x00800000;
 | |
| 
 | |
|         /** Call supports the deflect feature. */
 | |
|         public static final int CAPABILITY_SUPPORT_DEFLECT = 0x01000000;
 | |
| 
 | |
|         /**
 | |
|          * Call supports adding participants to the call via
 | |
|          * {@link #addConferenceParticipants(List)}. Once participants are added, the call becomes
 | |
|          * an adhoc conference call ({@link #PROPERTY_IS_ADHOC_CONFERENCE}).
 | |
|          */
 | |
|         public static final int CAPABILITY_ADD_PARTICIPANT = 0x02000000;
 | |
| 
 | |
|         /**
 | |
|          * When set for a call, indicates that this {@code Call} can be transferred to another
 | |
|          * number.
 | |
|          * Call supports the confirmed and unconfirmed call transfer feature.
 | |
|          *
 | |
|          * @hide
 | |
|          */
 | |
|         public static final int CAPABILITY_TRANSFER = 0x04000000;
 | |
| 
 | |
|         /**
 | |
|          * When set for a call, indicates that this {@code Call} can be transferred to another
 | |
|          * ongoing call.
 | |
|          * Call supports the consultative call transfer feature.
 | |
|          *
 | |
|          * @hide
 | |
|          */
 | |
|         public static final int CAPABILITY_TRANSFER_CONSULTATIVE = 0x08000000;
 | |
| 
 | |
|         /**
 | |
|          * Indicates whether the remote party supports RTT or not to the UI.
 | |
|          */
 | |
| 
 | |
|         public static final int CAPABILITY_REMOTE_PARTY_SUPPORTS_RTT = 0x10000000;
 | |
| 
 | |
|         //******************************************************************************************
 | |
|         // Next CAPABILITY value: 0x20000000
 | |
|         //******************************************************************************************
 | |
| 
 | |
|         /**
 | |
|          * 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;
 | |
| 
 | |
|         /**
 | |
|          * When set, the UI should indicate to the user that a call is using high definition
 | |
|          * audio.
 | |
|          * <p>
 | |
|          * The underlying {@link ConnectionService} is responsible for reporting this
 | |
|          * property.  It is important to note that this property is not intended to report the
 | |
|          * actual audio codec being used for a Call, but whether the call should be indicated
 | |
|          * to the user as high definition.
 | |
|          * <p>
 | |
|          * The Android Telephony stack reports this property for calls based on a number
 | |
|          * of factors, including which audio codec is used and whether a call is using an HD
 | |
|          * codec end-to-end.  Some mobile operators choose to suppress display of an HD indication,
 | |
|          * and in these cases this property will not be set for a call even if the underlying audio
 | |
|          * codec is in fact "high definition".
 | |
|          */
 | |
|         public static final int PROPERTY_HIGH_DEF_AUDIO = 0x00000010;
 | |
| 
 | |
|         /**
 | |
|          * Whether the call is associated with the work profile.
 | |
|          */
 | |
|         public static final int PROPERTY_ENTERPRISE_CALL = 0x00000020;
 | |
| 
 | |
|         /**
 | |
|          * When set, indicates that this {@code Call} does not actually exist locally for the
 | |
|          * {@link ConnectionService}.
 | |
|          * <p>
 | |
|          * Consider, for example, a scenario where a user has two phones with the same phone number.
 | |
|          * When a user places a call on one device, the telephony stack can represent that call on
 | |
|          * the other device by adding it to the {@link ConnectionService} with the
 | |
|          * {@link Connection#PROPERTY_IS_EXTERNAL_CALL} property set.
 | |
|          * <p>
 | |
|          * An {@link InCallService} will only see calls with this property if it has the
 | |
|          * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
 | |
|          * in its manifest.
 | |
|          * <p>
 | |
|          * See {@link Connection#PROPERTY_IS_EXTERNAL_CALL}.
 | |
|          */
 | |
|         public static final int PROPERTY_IS_EXTERNAL_CALL = 0x00000040;
 | |
| 
 | |
|         /**
 | |
|          * Indicates that the call has CDMA Enhanced Voice Privacy enabled.
 | |
|          */
 | |
|         public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 0x00000080;
 | |
| 
 | |
|         /**
 | |
|          * Indicates that the call is from a self-managed {@link ConnectionService}.
 | |
|          * <p>
 | |
|          * See also {@link Connection#PROPERTY_SELF_MANAGED}
 | |
|          */
 | |
|         public static final int PROPERTY_SELF_MANAGED = 0x00000100;
 | |
| 
 | |
|         /**
 | |
|          * Indicates the call used Assisted Dialing.
 | |
|          *
 | |
|          * @see TelecomManager#EXTRA_USE_ASSISTED_DIALING
 | |
|          */
 | |
|         public static final int PROPERTY_ASSISTED_DIALING = 0x00000200;
 | |
| 
 | |
|         /**
 | |
|          * Indicates that the call is an RTT call. Use {@link #getRttCall()} to get the
 | |
|          * {@link RttCall} object that is used to send and receive text.
 | |
|          */
 | |
|         public static final int PROPERTY_RTT = 0x00000400;
 | |
| 
 | |
|         /**
 | |
|          * Indicates that the call has been identified as the network as an emergency call. This
 | |
|          * property may be set for both incoming and outgoing calls which the network identifies as
 | |
|          * emergency calls.
 | |
|          */
 | |
|         public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 0x00000800;
 | |
| 
 | |
|         /**
 | |
|          * Indicates that the call is using VoIP audio mode.
 | |
|          * <p>
 | |
|          * When this property is set, the {@link android.media.AudioManager} audio mode for this
 | |
|          * call will be {@link android.media.AudioManager#MODE_IN_COMMUNICATION}.  When this
 | |
|          * property is not set, the audio mode for this call will be
 | |
|          * {@link android.media.AudioManager#MODE_IN_CALL}.
 | |
|          * <p>
 | |
|          * This property reflects changes made using {@link Connection#setAudioModeIsVoip(boolean)}.
 | |
|          * <p>
 | |
|          * You can use this property to determine whether an un-answered incoming call or a held
 | |
|          * call will use VoIP audio mode (if the call does not currently have focus, the system
 | |
|          * audio mode may not reflect the mode the call will use).
 | |
|          */
 | |
|         public static final int PROPERTY_VOIP_AUDIO_MODE = 0x00001000;
 | |
| 
 | |
|         /**
 | |
|          * Indicates that the call is an adhoc conference call. This property can be set for both
 | |
|          * incoming and outgoing calls. An adhoc conference call is formed using
 | |
|          * {@link #addConferenceParticipants(List)},
 | |
|          * {@link TelecomManager#addNewIncomingConference(PhoneAccountHandle, Bundle)}, or
 | |
|          * {@link TelecomManager#startConference(List, Bundle)}, rather than by merging existing
 | |
|          * call using {@link #conference(Call)}.
 | |
|          */
 | |
|         public static final int PROPERTY_IS_ADHOC_CONFERENCE = 0x00002000;
 | |
| 
 | |
|         /**
 | |
|          * Connection is using cross sim technology.
 | |
|          * <p>
 | |
|          * Indicates that the {@link Connection} is using a cross sim technology which would
 | |
|          * register IMS over internet APN of default data subscription.
 | |
|          * <p>
 | |
|          */
 | |
|         public static final int PROPERTY_CROSS_SIM = 0x00004000;
 | |
| 
 | |
|         //******************************************************************************************
 | |
|         // Next PROPERTY value: 0x00004000
 | |
|         //******************************************************************************************
 | |
| 
 | |
|         private final @CallState int mState;
 | |
|         private final String mTelecomCallId;
 | |
|         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 int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL;
 | |
|         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;
 | |
|         private final long mCreationTimeMillis;
 | |
|         private final String mContactDisplayName;
 | |
|         private final @CallDirection int mCallDirection;
 | |
|         private final @Connection.VerificationStatus int mCallerNumberVerificationStatus;
 | |
| 
 | |
|         /**
 | |
|          * 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) == capability;
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * 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_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO)) {
 | |
|                 builder.append(" CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO");
 | |
|             }
 | |
|             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");
 | |
|             }
 | |
|             if (can(capabilities, CAPABILITY_CAN_PULL_CALL)) {
 | |
|                 builder.append(" CAPABILITY_CAN_PULL_CALL");
 | |
|             }
 | |
|             if (can(capabilities, CAPABILITY_SUPPORT_DEFLECT)) {
 | |
|                 builder.append(" CAPABILITY_SUPPORT_DEFLECT");
 | |
|             }
 | |
|             if (can(capabilities, CAPABILITY_ADD_PARTICIPANT)) {
 | |
|                 builder.append(" CAPABILITY_ADD_PARTICIPANT");
 | |
|             }
 | |
|             if (can(capabilities, CAPABILITY_TRANSFER)) {
 | |
|                 builder.append(" CAPABILITY_TRANSFER");
 | |
|             }
 | |
|             if (can(capabilities, CAPABILITY_TRANSFER_CONSULTATIVE)) {
 | |
|                 builder.append(" CAPABILITY_TRANSFER_CONSULTATIVE");
 | |
|             }
 | |
|             if (can(capabilities, CAPABILITY_REMOTE_PARTY_SUPPORTS_RTT)) {
 | |
|                 builder.append(" CAPABILITY_REMOTE_PARTY_SUPPORTS_RTT");
 | |
|             }
 | |
|             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) == property;
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * 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");
 | |
|             }
 | |
|             if (hasProperty(properties, PROPERTY_IS_EXTERNAL_CALL)) {
 | |
|                 builder.append(" PROPERTY_IS_EXTERNAL_CALL");
 | |
|             }
 | |
|             if (hasProperty(properties, PROPERTY_HAS_CDMA_VOICE_PRIVACY)) {
 | |
|                 builder.append(" PROPERTY_HAS_CDMA_VOICE_PRIVACY");
 | |
|             }
 | |
|             if (hasProperty(properties, PROPERTY_ASSISTED_DIALING)) {
 | |
|                 builder.append(" PROPERTY_ASSISTED_DIALING_USED");
 | |
|             }
 | |
|             if (hasProperty(properties, PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL)) {
 | |
|                 builder.append(" PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL");
 | |
|             }
 | |
|             if (hasProperty(properties, PROPERTY_RTT)) {
 | |
|                 builder.append(" PROPERTY_RTT");
 | |
|             }
 | |
|             if (hasProperty(properties, PROPERTY_VOIP_AUDIO_MODE)) {
 | |
|                 builder.append(" PROPERTY_VOIP_AUDIO_MODE");
 | |
|             }
 | |
|             if (hasProperty(properties, PROPERTY_IS_ADHOC_CONFERENCE)) {
 | |
|                 builder.append(" PROPERTY_IS_ADHOC_CONFERENCE");
 | |
|             }
 | |
|             if (hasProperty(properties, PROPERTY_CROSS_SIM)) {
 | |
|                 builder.append(" PROPERTY_CROSS_SIM");
 | |
|             }
 | |
|             builder.append("]");
 | |
|             return builder.toString();
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * @return the state of the {@link Call} represented by this {@link Call.Details}.
 | |
|          */
 | |
|         public final @CallState int getState() {
 | |
|             return mState;
 | |
|         }
 | |
| 
 | |
|         /** {@hide} */
 | |
|         @TestApi
 | |
|         public String getTelecomCallId() {
 | |
|             return mTelecomCallId;
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * @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;
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * The display name for the caller.
 | |
|          * <p>
 | |
|          * This is the name as reported by the {@link ConnectionService} associated with this call.
 | |
|          *
 | |
|          * @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 a bitmask of the audio routes available for the call.
 | |
|          *
 | |
|          * @hide
 | |
|          */
 | |
|         public int getSupportedAudioRoutes() {
 | |
|             return mSupportedAudioRoutes;
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * @return For a {@link #STATE_DISCONNECTED} {@code Call}, the disconnect cause expressed
 | |
|          * by {@link android.telecom.DisconnectCause}.
 | |
|          */
 | |
|         public DisconnectCause getDisconnectCause() {
 | |
|             return mDisconnectCause;
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Returns the time the {@link Call} connected (i.e. became active).  This information is
 | |
|          * updated periodically, but user interfaces should not rely on this to display the "call
 | |
|          * time clock".  For the time when the call was first added to Telecom, see
 | |
|          * {@link #getCreationTimeMillis()}.
 | |
|          *
 | |
|          * @return The time the {@link Call} connected in milliseconds since the epoch.
 | |
|          */
 | |
|         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;
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Returns the time when the call was first created and added to Telecom.  This is the same
 | |
|          * time that is logged as the start time in the Call Log (see
 | |
|          * {@link android.provider.CallLog.Calls#DATE}).  To determine when the call was connected
 | |
|          * (became active), see {@link #getConnectTimeMillis()}.
 | |
|          *
 | |
|          * @return The creation time of the call, in millis since the epoch.
 | |
|          */
 | |
|         public long getCreationTimeMillis() {
 | |
|             return mCreationTimeMillis;
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Returns the name of the caller on the remote end, as derived from a
 | |
|          * {@link android.provider.ContactsContract} lookup of the call's handle.
 | |
|          * @return The name of the caller, or {@code null} if the lookup is not yet complete, if
 | |
|          *         there's no contacts entry for the caller, or if the {@link InCallService} does
 | |
|          *         not hold the {@link android.Manifest.permission#READ_CONTACTS} permission.
 | |
|          */
 | |
|         public @Nullable String getContactDisplayName() {
 | |
|             return mContactDisplayName;
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Indicates whether the call is an incoming or outgoing call.
 | |
|          * @return The call's direction.
 | |
|          */
 | |
|         public @CallDirection int getCallDirection() {
 | |
|             return mCallDirection;
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Gets the verification status for the phone number of an incoming call as identified in
 | |
|          * ATIS-1000082.
 | |
|          * <p>
 | |
|          * For incoming calls, the number verification status indicates whether the device was
 | |
|          * able to verify the authenticity of the calling number using the STIR process outlined
 | |
|          * in ATIS-1000082.  {@link Connection#VERIFICATION_STATUS_NOT_VERIFIED} indicates that
 | |
|          * the network was not able to use STIR to verify the caller's number (i.e. nothing is
 | |
|          * known regarding the authenticity of the number.
 | |
|          * {@link Connection#VERIFICATION_STATUS_PASSED} indicates that the network was able to
 | |
|          * use STIR to verify the caller's number.  This indicates that the network has a high
 | |
|          * degree of confidence that the incoming call actually originated from the indicated
 | |
|          * number.  {@link Connection#VERIFICATION_STATUS_FAILED} indicates that the network's
 | |
|          * STIR verification did not pass.  This indicates that the incoming call may not
 | |
|          * actually be from the indicated number.  This could occur if, for example, the caller
 | |
|          * is using an impersonated phone number.
 | |
|          * <p>
 | |
|          * A {@link CallScreeningService} can use this information to help determine if an
 | |
|          * incoming call is potentially an unwanted call.  A verification status of
 | |
|          * {@link Connection#VERIFICATION_STATUS_FAILED} indicates that an incoming call may not
 | |
|          * actually be from the number indicated on the call (i.e. impersonated number) and that it
 | |
|          * should potentially be blocked.  Likewise,
 | |
|          * {@link Connection#VERIFICATION_STATUS_PASSED} can be used as a positive signal to
 | |
|          * help clarify that the incoming call is originating from the indicated number and it
 | |
|          * is less likely to be an undesirable call.
 | |
|          * <p>
 | |
|          * An {@link InCallService} can use this information to provide a visual indicator to the
 | |
|          * user regarding the verification status of a call and to help identify calls from
 | |
|          * potentially impersonated numbers.
 | |
|          * @return the verification status.
 | |
|          */
 | |
|         public @Connection.VerificationStatus int getCallerNumberVerificationStatus() {
 | |
|             return mCallerNumberVerificationStatus;
 | |
|         }
 | |
| 
 | |
|         @Override
 | |
|         public boolean equals(Object o) {
 | |
|             if (o instanceof Details) {
 | |
|                 Details d = (Details) o;
 | |
|                 return
 | |
|                         Objects.equals(mState, d.mState) &&
 | |
|                         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) &&
 | |
|                         areBundlesEqual(mExtras, d.mExtras) &&
 | |
|                         areBundlesEqual(mIntentExtras, d.mIntentExtras) &&
 | |
|                         Objects.equals(mCreationTimeMillis, d.mCreationTimeMillis) &&
 | |
|                         Objects.equals(mContactDisplayName, d.mContactDisplayName) &&
 | |
|                         Objects.equals(mCallDirection, d.mCallDirection) &&
 | |
|                         Objects.equals(mCallerNumberVerificationStatus,
 | |
|                                 d.mCallerNumberVerificationStatus);
 | |
|             }
 | |
|             return false;
 | |
|         }
 | |
| 
 | |
|         @Override
 | |
|         public int hashCode() {
 | |
|             return Objects.hash(mState,
 | |
|                             mHandle,
 | |
|                             mHandlePresentation,
 | |
|                             mCallerDisplayName,
 | |
|                             mCallerDisplayNamePresentation,
 | |
|                             mAccountHandle,
 | |
|                             mCallCapabilities,
 | |
|                             mCallProperties,
 | |
|                             mDisconnectCause,
 | |
|                             mConnectTimeMillis,
 | |
|                             mGatewayInfo,
 | |
|                             mVideoState,
 | |
|                             mStatusHints,
 | |
|                             mExtras,
 | |
|                             mIntentExtras,
 | |
|                             mCreationTimeMillis,
 | |
|                             mContactDisplayName,
 | |
|                             mCallDirection,
 | |
|                             mCallerNumberVerificationStatus);
 | |
|         }
 | |
| 
 | |
|         /** {@hide} */
 | |
|         public Details(
 | |
|                 @CallState int state,
 | |
|                 String telecomCallId,
 | |
|                 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,
 | |
|                 long creationTimeMillis,
 | |
|                 String contactDisplayName,
 | |
|                 int callDirection,
 | |
|                 int callerNumberVerificationStatus) {
 | |
|             mState = state;
 | |
|             mTelecomCallId = telecomCallId;
 | |
|             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;
 | |
|             mCreationTimeMillis = creationTimeMillis;
 | |
|             mContactDisplayName = contactDisplayName;
 | |
|             mCallDirection = callDirection;
 | |
|             mCallerNumberVerificationStatus = callerNumberVerificationStatus;
 | |
|         }
 | |
| 
 | |
|         /** {@hide} */
 | |
|         public static Details createFromParcelableCall(ParcelableCall parcelableCall) {
 | |
|             return new Details(
 | |
|                     parcelableCall.getState(),
 | |
|                     parcelableCall.getId(),
 | |
|                     parcelableCall.getHandle(),
 | |
|                     parcelableCall.getHandlePresentation(),
 | |
|                     parcelableCall.getCallerDisplayName(),
 | |
|                     parcelableCall.getCallerDisplayNamePresentation(),
 | |
|                     parcelableCall.getAccountHandle(),
 | |
|                     parcelableCall.getCapabilities(),
 | |
|                     parcelableCall.getProperties(),
 | |
|                     parcelableCall.getDisconnectCause(),
 | |
|                     parcelableCall.getConnectTimeMillis(),
 | |
|                     parcelableCall.getGatewayInfo(),
 | |
|                     parcelableCall.getVideoState(),
 | |
|                     parcelableCall.getStatusHints(),
 | |
|                     parcelableCall.getExtras(),
 | |
|                     parcelableCall.getIntentExtras(),
 | |
|                     parcelableCall.getCreationTimeMillis(),
 | |
|                     parcelableCall.getContactDisplayName(),
 | |
|                     parcelableCall.getCallDirection(),
 | |
|                     parcelableCall.getCallerNumberVerificationStatus());
 | |
|         }
 | |
| 
 | |
|         @Override
 | |
|         public String toString() {
 | |
|             StringBuilder sb = new StringBuilder();
 | |
|             sb.append("[id: ");
 | |
|             sb.append(mTelecomCallId);
 | |
|             sb.append(", state: ");
 | |
|             sb.append(Call.stateToString(mState));
 | |
|             sb.append(", pa: ");
 | |
|             sb.append(mAccountHandle);
 | |
|             sb.append(", hdl: ");
 | |
|             sb.append(Log.piiHandle(mHandle));
 | |
|             sb.append(", hdlPres: ");
 | |
|             sb.append(mHandlePresentation);
 | |
|             sb.append(", videoState: ");
 | |
|             sb.append(VideoProfile.videoStateToString(mVideoState));
 | |
|             sb.append(", caps: ");
 | |
|             sb.append(capabilitiesToString(mCallCapabilities));
 | |
|             sb.append(", props: ");
 | |
|             sb.append(propertiesToString(mCallProperties));
 | |
|             sb.append("]");
 | |
|             return sb.toString();
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Defines callbacks which inform the {@link InCallService} of changes to a {@link Call}.
 | |
|      * These callbacks can originate from the Telecom framework, or a {@link ConnectionService}
 | |
|      * implementation.
 | |
|      * <p>
 | |
|      * You can handle these callbacks by extending the {@link Callback} class and overriding the
 | |
|      * callbacks that your {@link InCallService} is interested in.  The callback methods include the
 | |
|      * {@link Call} for which the callback applies, allowing reuse of a single instance of your
 | |
|      * {@link Callback} implementation, if desired.
 | |
|      * <p>
 | |
|      * Use {@link Call#registerCallback(Callback)} to register your callback(s).  Ensure
 | |
|      * {@link Call#unregisterCallback(Callback)} is called when you no longer require callbacks
 | |
|      * (typically in {@link InCallService#onCallRemoved(Call)}).
 | |
|      * Note: Callbacks which occur before you call {@link Call#registerCallback(Callback)} will not
 | |
|      * reach your implementation of {@link Callback}, so it is important to register your callback
 | |
|      * as soon as your {@link InCallService} is notified of a new call via
 | |
|      * {@link InCallService#onCallAdded(Call)}.
 | |
|      */
 | |
|     public static abstract class Callback {
 | |
|         /**
 | |
|          * @hide
 | |
|          */
 | |
|         @IntDef(prefix = { "HANDOVER_" },
 | |
|                 value = {HANDOVER_FAILURE_DEST_APP_REJECTED, HANDOVER_FAILURE_NOT_SUPPORTED,
 | |
|                 HANDOVER_FAILURE_USER_REJECTED, HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL,
 | |
|                 HANDOVER_FAILURE_UNKNOWN})
 | |
|         @Retention(RetentionPolicy.SOURCE)
 | |
|         public @interface HandoverFailureErrors {}
 | |
| 
 | |
|         /**
 | |
|          * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the app
 | |
|          * to handover the call to rejects the handover request.
 | |
|          * <p>
 | |
|          * Will be returned when {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} is called
 | |
|          * and the destination {@link PhoneAccountHandle}'s {@link ConnectionService} returns a
 | |
|          * {@code null} {@link Connection} from
 | |
|          * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
 | |
|          * ConnectionRequest)}.
 | |
|          * <p>
 | |
|          * For more information on call handovers, see
 | |
|          * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
 | |
|          */
 | |
|         public static final int HANDOVER_FAILURE_DEST_APP_REJECTED = 1;
 | |
| 
 | |
|         /**
 | |
|          * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
 | |
|          * is initiated but the source or destination app does not support handover.
 | |
|          * <p>
 | |
|          * Will be returned when a handover is requested via
 | |
|          * {@link #handoverTo(PhoneAccountHandle, int, Bundle)} and the destination
 | |
|          * {@link PhoneAccountHandle} does not declare
 | |
|          * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}.  May also be returned when a handover is
 | |
|          * requested at the {@link PhoneAccountHandle} for the current call (i.e. the source call's
 | |
|          * {@link Details#getAccountHandle()}) does not declare
 | |
|          * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}.
 | |
|          * <p>
 | |
|          * For more information on call handovers, see
 | |
|          * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
 | |
|          */
 | |
|         public static final int HANDOVER_FAILURE_NOT_SUPPORTED = 2;
 | |
| 
 | |
|         /**
 | |
|          * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the remote
 | |
|          * user rejects the handover request.
 | |
|          * <p>
 | |
|          * For more information on call handovers, see
 | |
|          * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
 | |
|          */
 | |
|         public static final int HANDOVER_FAILURE_USER_REJECTED = 3;
 | |
| 
 | |
|         /**
 | |
|          * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there
 | |
|          * is ongoing emergency call.
 | |
|          * <p>
 | |
|          * This error code is returned when {@link #handoverTo(PhoneAccountHandle, int, Bundle)} is
 | |
|          * called on an emergency call, or if any other call is an emergency call.
 | |
|          * <p>
 | |
|          * Handovers are not permitted while there are ongoing emergency calls.
 | |
|          * <p>
 | |
|          * For more information on call handovers, see
 | |
|          * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
 | |
|          */
 | |
|         public static final int HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL = 4;
 | |
| 
 | |
|         /**
 | |
|          * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
 | |
|          * fails for an unknown reason.
 | |
|          * <p>
 | |
|          * For more information on call handovers, see
 | |
|          * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
 | |
|          */
 | |
|         public static final int HANDOVER_FAILURE_UNKNOWN = 5;
 | |
| 
 | |
|         /**
 | |
|          * 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, @CallState 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<Call> children) {}
 | |
| 
 | |
|         /**
 | |
|          * Invoked when the details of this {@code Call} have changed. See {@link #getDetails()}.
 | |
|          *
 | |
|          * @param call The {@code Call} invoking this method.
 | |
|          * @param details A {@code Details} object describing the {@code Call}.
 | |
|          */
 | |
|         public void onDetailsChanged(Call call, Details details) {}
 | |
| 
 | |
|         /**
 | |
|          * Invoked when the text messages that can be used as responses to the incoming
 | |
|          * {@code Call} are loaded from the relevant database.
 | |
|          * See {@link #getCannedTextResponses()}.
 | |
|          *
 | |
|          * @param call The {@code Call} invoking this method.
 | |
|          * @param cannedTextResponses The text messages useable as responses.
 | |
|          */
 | |
|         public void onCannedTextResponsesLoaded(Call call, List<String> cannedTextResponses) {}
 | |
| 
 | |
|         /**
 | |
|          * Invoked when the post-dial sequence in the outgoing {@code Call} has reached a pause
 | |
|          * character. This causes the post-dial signals to stop pending user confirmation. An
 | |
|          * implementation should present this choice to the user and invoke
 | |
|          * {@link #postDialContinue(boolean)} when the user makes the choice.
 | |
|          *
 | |
|          * @param call The {@code Call} invoking this method.
 | |
|          * @param remainingPostDialSequence The post-dial characters that remain to be sent.
 | |
|          */
 | |
|         public void onPostDialWait(Call call, String remainingPostDialSequence) {}
 | |
| 
 | |
|         /**
 | |
|          * Invoked when the {@code Call.VideoCall} of the {@code Call} has changed.
 | |
|          *
 | |
|          * @param call The {@code Call} invoking this method.
 | |
|          * @param videoCall The {@code Call.VideoCall} associated with the {@code Call}.
 | |
|          */
 | |
|         public void onVideoCallChanged(Call call, InCallService.VideoCall videoCall) {}
 | |
| 
 | |
|         /**
 | |
|          * Invoked when the {@code Call} is destroyed. Clients should refrain from cleaning
 | |
|          * up their UI for the {@code Call} in response to state transitions. Specifically,
 | |
|          * clients should not assume that a {@link #onStateChanged(Call, int)} with a state of
 | |
|          * {@link #STATE_DISCONNECTED} is the final notification the {@code Call} will send. Rather,
 | |
|          * clients should wait for this method to be invoked.
 | |
|          *
 | |
|          * @param call The {@code Call} being destroyed.
 | |
|          */
 | |
|         public void onCallDestroyed(Call call) {}
 | |
| 
 | |
|         /**
 | |
|          * Invoked upon changes to the set of {@code Call}s with which this {@code Call} can be
 | |
|          * conferenced.
 | |
|          *
 | |
|          * @param call The {@code Call} being updated.
 | |
|          * @param conferenceableCalls The {@code Call}s with which this {@code Call} can be
 | |
|          *          conferenced.
 | |
|          */
 | |
|         public void onConferenceableCallsChanged(Call call, List<Call> conferenceableCalls) {}
 | |
| 
 | |
|         /**
 | |
|          * Invoked when a {@link Call} receives an event from its associated {@link Connection} or
 | |
|          * {@link Conference}.
 | |
|          * <p>
 | |
|          * Where possible, the Call should make an attempt to handle {@link Connection} events which
 | |
|          * are part of the {@code android.telecom.*} namespace.  The Call should ignore any events
 | |
|          * it does not wish to handle.  Unexpected events should be handled gracefully, as it is
 | |
|          * possible that a {@link ConnectionService} has defined its own Connection events which a
 | |
|          * Call is not aware of.
 | |
|          * <p>
 | |
|          * See {@link Connection#sendConnectionEvent(String, Bundle)},
 | |
|          * {@link Conference#sendConferenceEvent(String, Bundle)}.
 | |
|          *
 | |
|          * @param call The {@code Call} receiving the event.
 | |
|          * @param event The event.
 | |
|          * @param extras Extras associated with the connection event.
 | |
|          */
 | |
|         public void onConnectionEvent(Call call, String event, Bundle extras) {}
 | |
| 
 | |
|         /**
 | |
|          * Invoked when the RTT mode changes for this call.
 | |
|          * @param call The call whose RTT mode has changed.
 | |
|          * @param mode the new RTT mode, one of
 | |
|          * {@link RttCall#RTT_MODE_FULL}, {@link RttCall#RTT_MODE_HCO},
 | |
|          *             or {@link RttCall#RTT_MODE_VCO}
 | |
|          */
 | |
|         public void onRttModeChanged(Call call, int mode) {}
 | |
| 
 | |
|         /**
 | |
|          * Invoked when the call's RTT status changes, either from off to on or from on to off.
 | |
|          * @param call The call whose RTT status has changed.
 | |
|          * @param enabled whether RTT is now enabled or disabled
 | |
|          * @param rttCall the {@link RttCall} object to use for reading and writing if RTT is now
 | |
|          *                on, null otherwise.
 | |
|          */
 | |
|         public void onRttStatusChanged(Call call, boolean enabled, RttCall rttCall) {}
 | |
| 
 | |
|         /**
 | |
|          * Invoked when the remote end of the connection has requested that an RTT communication
 | |
|          * channel be opened. A response to this should be sent via {@link #respondToRttRequest}
 | |
|          * with the same ID that this method is invoked with.
 | |
|          * @param call The call which the RTT request was placed on
 | |
|          * @param id The ID of the request.
 | |
|          */
 | |
|         public void onRttRequest(Call call, int id) {}
 | |
| 
 | |
|         /**
 | |
|          * Invoked when the RTT session failed to initiate for some reason, including rejection
 | |
|          * by the remote party.
 | |
|          * <p>
 | |
|          * This callback will ONLY be invoked to report a failure related to a user initiated
 | |
|          * session modification request (i.e. {@link Call#sendRttRequest()}).
 | |
|          * <p>
 | |
|          * If a call is initiated with {@link TelecomManager#EXTRA_START_CALL_WITH_RTT} specified,
 | |
|          * the availability of RTT can be determined by checking {@link Details#PROPERTY_RTT}
 | |
|          * once the call enters state {@link Details#STATE_ACTIVE}.
 | |
|          *
 | |
|          * @param call The call which the RTT initiation failure occurred on.
 | |
|          * @param reason One of the status codes defined in
 | |
|          *      {@link android.telecom.Connection.RttModifyStatus}, with the exception of
 | |
|          *      {@link android.telecom.Connection.RttModifyStatus#SESSION_MODIFY_REQUEST_SUCCESS}.
 | |
|          */
 | |
|         public void onRttInitiationFailure(Call call,
 | |
|                 @android.telecom.Connection.RttModifyStatus.RttSessionModifyStatus int reason) {}
 | |
| 
 | |
|         /**
 | |
|          * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
 | |
|          * has completed successfully.
 | |
|          * <p>
 | |
|          * For a full discussion of the handover process and the APIs involved, see
 | |
|          * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
 | |
|          *
 | |
|          * @param call The call which had initiated handover.
 | |
|          */
 | |
|         public void onHandoverComplete(Call call) {}
 | |
| 
 | |
|         /**
 | |
|          * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
 | |
|          * has failed.
 | |
|          * <p>
 | |
|          * For a full discussion of the handover process and the APIs involved, see
 | |
|          * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
 | |
|          *
 | |
|          * @param call The call which had initiated handover.
 | |
|          * @param failureReason Error reason for failure.
 | |
|          */
 | |
|         public void onHandoverFailed(Call call, @HandoverFailureErrors int failureReason) {}
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * A class that holds the state that describes the state of the RTT channel to the remote
 | |
|      * party, if it is active.
 | |
|      */
 | |
|     public static final class RttCall {
 | |
|         /** @hide */
 | |
|         @Retention(RetentionPolicy.SOURCE)
 | |
|         @IntDef({RTT_MODE_INVALID, RTT_MODE_FULL, RTT_MODE_HCO, RTT_MODE_VCO})
 | |
|         public @interface RttAudioMode {}
 | |
| 
 | |
|         /**
 | |
|          * For metrics use. Default value in the proto.
 | |
|          * @hide
 | |
|          */
 | |
|         public static final int RTT_MODE_INVALID = 0;
 | |
| 
 | |
|         /**
 | |
|          * Indicates that there should be a bidirectional audio stream between the two parties
 | |
|          * on the call.
 | |
|          */
 | |
|         public static final int RTT_MODE_FULL = 1;
 | |
| 
 | |
|         /**
 | |
|          * Indicates that the local user should be able to hear the audio stream from the remote
 | |
|          * user, but not vice versa. Equivalent to muting the microphone.
 | |
|          */
 | |
|         public static final int RTT_MODE_HCO = 2;
 | |
| 
 | |
|         /**
 | |
|          * Indicates that the remote user should be able to hear the audio stream from the local
 | |
|          * user, but not vice versa. Equivalent to setting the volume to zero.
 | |
|          */
 | |
|         public static final int RTT_MODE_VCO = 3;
 | |
| 
 | |
|         private static final int READ_BUFFER_SIZE = 1000;
 | |
| 
 | |
|         private InputStreamReader mReceiveStream;
 | |
|         private OutputStreamWriter mTransmitStream;
 | |
|         private int mRttMode;
 | |
|         private final InCallAdapter mInCallAdapter;
 | |
|         private final String mTelecomCallId;
 | |
|         private char[] mReadBuffer = new char[READ_BUFFER_SIZE];
 | |
| 
 | |
|         /**
 | |
|          * @hide
 | |
|          */
 | |
|         public RttCall(String telecomCallId, InputStreamReader receiveStream,
 | |
|                 OutputStreamWriter transmitStream, int mode, InCallAdapter inCallAdapter) {
 | |
|             mTelecomCallId = telecomCallId;
 | |
|             mReceiveStream = receiveStream;
 | |
|             mTransmitStream = transmitStream;
 | |
|             mRttMode = mode;
 | |
|             mInCallAdapter = inCallAdapter;
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Returns the current RTT audio mode.
 | |
|          * @return Current RTT audio mode. One of {@link #RTT_MODE_FULL}, {@link #RTT_MODE_VCO}, or
 | |
|          * {@link #RTT_MODE_HCO}.
 | |
|          */
 | |
|         public int getRttAudioMode() {
 | |
|             return mRttMode;
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Sets the RTT audio mode. The requested mode change will be communicated through
 | |
|          * {@link Callback#onRttModeChanged(Call, int)}.
 | |
|          * @param mode The desired RTT audio mode, one of {@link #RTT_MODE_FULL},
 | |
|          * {@link #RTT_MODE_VCO}, or {@link #RTT_MODE_HCO}.
 | |
|          */
 | |
|         public void setRttMode(@RttAudioMode int mode) {
 | |
|             mInCallAdapter.setRttMode(mTelecomCallId, mode);
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Writes the string {@param input} into the outgoing text stream for this RTT call. Since
 | |
|          * RTT transmits text in real-time, this method should be called once for each user action.
 | |
|          * For example, when the user enters text as discrete characters using the keyboard, this
 | |
|          * method should be called once for each character. However, if the user enters text by
 | |
|          * pasting or autocomplete, the entire contents of the pasted or autocompleted text should
 | |
|          * be sent in one call to this method.
 | |
|          *
 | |
|          * This method is not thread-safe -- calling it from multiple threads simultaneously may
 | |
|          * lead to interleaved text.
 | |
|          * @param input The message to send to the remote user.
 | |
|          */
 | |
|         public void write(String input) throws IOException {
 | |
|             mTransmitStream.write(input);
 | |
|             mTransmitStream.flush();
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Reads a string from the remote user, blocking if there is no data available. Returns
 | |
|          * {@code null} if the RTT conversation has been terminated and there is no further data
 | |
|          * to read.
 | |
|          *
 | |
|          * This method is not thread-safe -- calling it from multiple threads simultaneously may
 | |
|          * lead to interleaved text.
 | |
|          * @return A string containing text sent by the remote user, or {@code null} if the
 | |
|          * conversation has been terminated or if there was an error while reading.
 | |
|          */
 | |
|         public String read() {
 | |
|             try {
 | |
|                 int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE);
 | |
|                 if (numRead < 0) {
 | |
|                     return null;
 | |
|                 }
 | |
|                 return new String(mReadBuffer, 0, numRead);
 | |
|             } catch (IOException e) {
 | |
|                 Log.w(this, "Exception encountered when reading from InputStreamReader: %s", e);
 | |
|                 return null;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Non-blocking version of {@link #read()}. Returns {@code null} if there is nothing to
 | |
|          * be read.
 | |
|          * @return A string containing text entered by the user, or {@code null} if the user has
 | |
|          * not entered any new text yet.
 | |
|          */
 | |
|         public String readImmediately() throws IOException {
 | |
|             if (mReceiveStream.ready()) {
 | |
|                 int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE);
 | |
|                 if (numRead < 0) {
 | |
|                     return null;
 | |
|                 }
 | |
|                 return new String(mReadBuffer, 0, numRead);
 | |
|             } else {
 | |
|                 return null;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Closes the underlying file descriptors
 | |
|          * @hide
 | |
|          */
 | |
|         public void close() {
 | |
|             try {
 | |
|                 mReceiveStream.close();
 | |
|             } catch (IOException e) {
 | |
|                 // ignore
 | |
|             }
 | |
|             try {
 | |
|                 mTransmitStream.close();
 | |
|             } catch (IOException e) {
 | |
|                 // ignore
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @deprecated Use {@code Call.Callback} instead.
 | |
|      * @hide
 | |
|      */
 | |
|     @Deprecated
 | |
|     @SystemApi
 | |
|     public static abstract class Listener extends Callback { }
 | |
| 
 | |
|     private final Phone mPhone;
 | |
|     private final String mTelecomCallId;
 | |
|     private final InCallAdapter mInCallAdapter;
 | |
|     private final List<String> mChildrenIds = new ArrayList<>();
 | |
|     private final List<Call> mChildren = new ArrayList<>();
 | |
|     private final List<Call> mUnmodifiableChildren = Collections.unmodifiableList(mChildren);
 | |
|     private final List<CallbackRecord<Callback>> mCallbackRecords = new CopyOnWriteArrayList<>();
 | |
|     private final List<Call> mConferenceableCalls = new ArrayList<>();
 | |
|     private final List<Call> mUnmodifiableConferenceableCalls =
 | |
|             Collections.unmodifiableList(mConferenceableCalls);
 | |
| 
 | |
|     private boolean mChildrenCached;
 | |
|     private String mParentId = null;
 | |
|     private String mActiveGenericConferenceChild = null;
 | |
|     private int mState;
 | |
|     private List<String> mCannedTextResponses = null;
 | |
|     private String mCallingPackage;
 | |
|     private int mTargetSdkVersion;
 | |
|     private String mRemainingPostDialSequence;
 | |
|     private VideoCallImpl mVideoCallImpl;
 | |
|     private RttCall mRttCall;
 | |
|     private Details mDetails;
 | |
|     private Bundle mExtras;
 | |
| 
 | |
|     /**
 | |
|      * Obtains the post-dial sequence remaining to be emitted by this {@code Call}, if any.
 | |
|      *
 | |
|      * @return The remaining post-dial sequence, or {@code null} if there is no post-dial sequence
 | |
|      * remaining or this {@code Call} is not in a post-dial state.
 | |
|      */
 | |
|     public String getRemainingPostDialSequence() {
 | |
|         return mRemainingPostDialSequence;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Instructs this {@link #STATE_RINGING} {@code Call} to answer.
 | |
|      * @param videoState The video state in which to answer the call.
 | |
|      */
 | |
|     public void answer(@VideoProfile.VideoState int videoState) {
 | |
|         mInCallAdapter.answerCall(mTelecomCallId, videoState);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Instructs this {@link #STATE_RINGING} {@code Call} to deflect.
 | |
|      *
 | |
|      * @param address The address to which the call will be deflected.
 | |
|      */
 | |
|     public void deflect(Uri address) {
 | |
|         mInCallAdapter.deflectCall(mTelecomCallId, address);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Instructs this {@link #STATE_RINGING} {@code Call} to reject.
 | |
|      *
 | |
|      * @param rejectWithMessage Whether to reject with a text message.
 | |
|      * @param textMessage An optional text message with which to respond.
 | |
|      */
 | |
|     public void reject(boolean rejectWithMessage, String textMessage) {
 | |
|         mInCallAdapter.rejectCall(mTelecomCallId, rejectWithMessage, textMessage);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Instructs the {@link ConnectionService} providing this {@link #STATE_RINGING} call that the
 | |
|      * user has chosen to reject the call and has indicated a reason why the call is being rejected.
 | |
|      *
 | |
|      * @param rejectReason the reason the call is being rejected.
 | |
|      */
 | |
|     public void reject(@RejectReason int rejectReason) {
 | |
|         mInCallAdapter.rejectCall(mTelecomCallId, rejectReason);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Instructs this {@code Call} to be transferred to another number.
 | |
|      *
 | |
|      * @param targetNumber The address to which the call will be transferred.
 | |
|      * @param isConfirmationRequired if {@code true} it will initiate a confirmed transfer,
 | |
|      * if {@code false}, it will initiate an unconfirmed transfer.
 | |
|      *
 | |
|      * @hide
 | |
|      */
 | |
|     public void transfer(@NonNull Uri targetNumber, boolean isConfirmationRequired) {
 | |
|         mInCallAdapter.transferCall(mTelecomCallId, targetNumber, isConfirmationRequired);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Instructs this {@code Call} to be transferred to another ongoing call.
 | |
|      * This will initiate CONSULTATIVE transfer.
 | |
|      * @param toCall The other ongoing {@code Call} to which this call will be transferred.
 | |
|      *
 | |
|      * @hide
 | |
|      */
 | |
|     public void transfer(@NonNull android.telecom.Call toCall) {
 | |
|         mInCallAdapter.transferCall(mTelecomCallId, toCall.mTelecomCallId);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Instructs this {@code Call} to disconnect.
 | |
|      */
 | |
|     public void disconnect() {
 | |
|         mInCallAdapter.disconnectCall(mTelecomCallId);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Instructs this {@code Call} to go on hold.
 | |
|      */
 | |
|     public void hold() {
 | |
|         mInCallAdapter.holdCall(mTelecomCallId);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Instructs this {@link #STATE_HOLDING} call to release from hold.
 | |
|      */
 | |
|     public void unhold() {
 | |
|         mInCallAdapter.unholdCall(mTelecomCallId);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Instructs Telecom to put the call into the background audio processing state.
 | |
|      * <p>
 | |
|      * This method can be called either when the call is in {@link #STATE_RINGING} or
 | |
|      * {@link #STATE_ACTIVE}. After Telecom acknowledges the request by setting the call's state to
 | |
|      * {@link #STATE_AUDIO_PROCESSING}, your app may setup the audio paths with the audio stack in
 | |
|      * order to capture and play audio on the call stream.
 | |
|      * <p>
 | |
|      * This method can only be called by the default dialer app.
 | |
|      * <p>
 | |
|      * Apps built with SDK version {@link android.os.Build.VERSION_CODES#R} or later which are using
 | |
|      * the microphone as part of audio processing should specify the foreground service type using
 | |
|      * the attribute {@link android.R.attr#foregroundServiceType} in the {@link InCallService}
 | |
|      * service element of the app's manifest file.
 | |
|      * The {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_MICROPHONE} attribute should be specified.
 | |
|      * @see <a href="https://developer.android.com/preview/privacy/foreground-service-types">
 | |
|      * the Android Developer Site</a> for more information.
 | |
|      * @hide
 | |
|      */
 | |
|     @SystemApi
 | |
|     public void enterBackgroundAudioProcessing() {
 | |
|         if (mState != STATE_ACTIVE && mState != STATE_RINGING) {
 | |
|             throw new IllegalStateException("Call must be active or ringing");
 | |
|         }
 | |
|         mInCallAdapter.enterBackgroundAudioProcessing(mTelecomCallId);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Instructs Telecom to come out of the background audio processing state requested by
 | |
|      * {@link #enterBackgroundAudioProcessing()} or from the call screening service.
 | |
|      *
 | |
|      * This method can only be called when the call is in {@link #STATE_AUDIO_PROCESSING}.
 | |
|      *
 | |
|      * @param shouldRing If true, Telecom will put the call into the
 | |
|      *                   {@link #STATE_SIMULATED_RINGING} state and notify other apps that there is
 | |
|      *                   a ringing call. Otherwise, the call will go into {@link #STATE_ACTIVE}
 | |
|      *                   immediately.
 | |
|      * @hide
 | |
|      */
 | |
|     @SystemApi
 | |
|     public void exitBackgroundAudioProcessing(boolean shouldRing) {
 | |
|         if (mState != STATE_AUDIO_PROCESSING) {
 | |
|             throw new IllegalStateException("Call must in the audio processing state");
 | |
|         }
 | |
|         mInCallAdapter.exitBackgroundAudioProcessing(mTelecomCallId, shouldRing);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Instructs this {@code Call} to play a dual-tone multi-frequency signaling (DTMF) tone.
 | |
|      *
 | |
|      * Any other currently playing DTMF tone in the specified call is immediately stopped.
 | |
|      *
 | |
|      * @param digit A character representing the DTMF digit for which to play the tone. This
 | |
|      *         value must be one of {@code '0'} through {@code '9'}, {@code '*'} or {@code '#'}.
 | |
|      */
 | |
|     public void playDtmfTone(char digit) {
 | |
|         mInCallAdapter.playDtmfTone(mTelecomCallId, digit);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Instructs this {@code Call} to stop any dual-tone multi-frequency signaling (DTMF) tone
 | |
|      * currently playing.
 | |
|      *
 | |
|      * DTMF tones are played by calling {@link #playDtmfTone(char)}. If no DTMF tone is
 | |
|      * currently playing, this method will do nothing.
 | |
|      */
 | |
|     public void stopDtmfTone() {
 | |
|         mInCallAdapter.stopDtmfTone(mTelecomCallId);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Instructs this {@code Call} to continue playing a post-dial DTMF string.
 | |
|      *
 | |
|      * A post-dial DTMF string is a string of digits entered after a phone number, when dialed,
 | |
|      * that are immediately sent as DTMF tones to the recipient as soon as the connection is made.
 | |
|      *
 | |
|      * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_PAUSE} symbol, this
 | |
|      * {@code Call} will temporarily pause playing the tones for a pre-defined period of time.
 | |
|      *
 | |
|      * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_WAIT} symbol, this
 | |
|      * {@code Call} will pause playing the tones and notify callbacks via
 | |
|      * {@link Callback#onPostDialWait(Call, String)}. At this point, the in-call app
 | |
|      * should display to the user an indication of this state and an affordance to continue
 | |
|      * the postdial sequence. When the user decides to continue the postdial sequence, the in-call
 | |
|      * app should invoke the {@link #postDialContinue(boolean)} method.
 | |
|      *
 | |
|      * @param proceed Whether or not to continue with the post-dial sequence.
 | |
|      */
 | |
|     public void postDialContinue(boolean proceed) {
 | |
|         mInCallAdapter.postDialContinue(mTelecomCallId, proceed);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Notifies this {@code Call} that an account has been selected and to proceed with placing
 | |
|      * an outgoing call. Optionally sets this account as the default account.
 | |
|      */
 | |
|     public void phoneAccountSelected(PhoneAccountHandle accountHandle, boolean setDefault) {
 | |
|         mInCallAdapter.phoneAccountSelected(mTelecomCallId, accountHandle, setDefault);
 | |
| 
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Instructs this {@code Call} to enter a conference.
 | |
|      *
 | |
|      * @param callToConferenceWith The other call with which to conference.
 | |
|      */
 | |
|     public void conference(Call callToConferenceWith) {
 | |
|         if (callToConferenceWith != null) {
 | |
|             mInCallAdapter.conference(mTelecomCallId, callToConferenceWith.mTelecomCallId);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Instructs this {@code Call} to split from any conference call with which it may be
 | |
|      * connected.
 | |
|      */
 | |
|     public void splitFromConference() {
 | |
|         mInCallAdapter.splitFromConference(mTelecomCallId);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Merges the calls within this conference. See {@link Details#CAPABILITY_MERGE_CONFERENCE}.
 | |
|      */
 | |
|     public void mergeConference() {
 | |
|         mInCallAdapter.mergeConference(mTelecomCallId);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Swaps the calls within this conference. See {@link Details#CAPABILITY_SWAP_CONFERENCE}.
 | |
|      */
 | |
|     public void swapConference() {
 | |
|         mInCallAdapter.swapConference(mTelecomCallId);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Pulls participants to existing call by forming a conference call.
 | |
|      * See {@link Details#CAPABILITY_ADD_PARTICIPANT}.
 | |
|      *
 | |
|      * @param participants participants to be pulled to existing call.
 | |
|      */
 | |
|     public void addConferenceParticipants(@NonNull List<Uri> participants) {
 | |
|         mInCallAdapter.addConferenceParticipants(mTelecomCallId, participants);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Initiates a request to the {@link ConnectionService} to pull an external call to the local
 | |
|      * device.
 | |
|      * <p>
 | |
|      * Calls to this method are ignored if the call does not have the
 | |
|      * {@link Call.Details#PROPERTY_IS_EXTERNAL_CALL} property set.
 | |
|      * <p>
 | |
|      * An {@link InCallService} will only see calls which support this method if it has the
 | |
|      * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
 | |
|      * in its manifest.
 | |
|      */
 | |
|     public void pullExternalCall() {
 | |
|         // If this isn't an external call, ignore the request.
 | |
|         if (!mDetails.hasProperty(Details.PROPERTY_IS_EXTERNAL_CALL)) {
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         mInCallAdapter.pullExternalCall(mTelecomCallId);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Sends a {@code Call} event from this {@code Call} to the associated {@link Connection} in
 | |
|      * the {@link ConnectionService}.
 | |
|      * <p>
 | |
|      * Call events are used to communicate point in time information from an {@link InCallService}
 | |
|      * to a {@link ConnectionService}.  A {@link ConnectionService} implementation could define
 | |
|      * events which enable the {@link InCallService}, for example, toggle a unique feature of the
 | |
|      * {@link ConnectionService}.
 | |
|      * <p>
 | |
|      * A {@link ConnectionService} can communicate to the {@link InCallService} using
 | |
|      * {@link Connection#sendConnectionEvent(String, Bundle)}.
 | |
|      * <p>
 | |
|      * Events are exposed to {@link ConnectionService} implementations via
 | |
|      * {@link android.telecom.Connection#onCallEvent(String, Bundle)}.
 | |
|      * <p>
 | |
|      * No assumptions should be made as to how a {@link ConnectionService} will handle these events.
 | |
|      * The {@link InCallService} must assume that the {@link ConnectionService} could 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 InCallService} implementations.  Further, {@link InCallService}
 | |
|      * implementations shall not re-purpose events in the {@code android.*} namespace, nor shall
 | |
|      * they define their own 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 InCallService} is updated.  Support for deprecated
 | |
|      * events/extras should me maintained to ensure backwards compatibility with older
 | |
|      * {@link ConnectionService} implementations which were built to support the older behavior.
 | |
|      *
 | |
|      * @param event The connection event.
 | |
|      * @param extras Bundle containing extra information associated with the event.
 | |
|      */
 | |
|     public void sendCallEvent(String event, Bundle extras) {
 | |
|         mInCallAdapter.sendCallEvent(mTelecomCallId, event, mTargetSdkVersion, extras);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Sends an RTT upgrade request to the remote end of the connection. Success is not
 | |
|      * guaranteed, and notification of success will be via the
 | |
|      * {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
 | |
|      */
 | |
|     public void sendRttRequest() {
 | |
|         mInCallAdapter.sendRttRequest(mTelecomCallId);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Responds to an RTT request received via the {@link Callback#onRttRequest(Call, int)} )}
 | |
|      * callback.
 | |
|      * The ID used here should be the same as the ID that was received via the callback.
 | |
|      * @param id The request ID received via {@link Callback#onRttRequest(Call, int)}
 | |
|      * @param accept {@code true} if the RTT request should be accepted, {@code false} otherwise.
 | |
|      */
 | |
|     public void respondToRttRequest(int id, boolean accept) {
 | |
|         mInCallAdapter.respondToRttRequest(mTelecomCallId, id, accept);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Initiates a handover of this {@link Call} to the {@link ConnectionService} identified
 | |
|      * by {@code toHandle}.  The videoState specified indicates the desired video state after the
 | |
|      * handover.
 | |
|      * <p>
 | |
|      * A call handover is the process where an ongoing call is transferred from one app (i.e.
 | |
|      * {@link ConnectionService} to another app.  The user could, for example, choose to continue a
 | |
|      * mobile network call in a video calling app.  The mobile network call via the Telephony stack
 | |
|      * is referred to as the source of the handover, and the video calling app is referred to as the
 | |
|      * destination.
 | |
|      * <p>
 | |
|      * When considering a handover scenario the device this method is called on is considered the
 | |
|      * <em>initiating</em> device (since the user initiates the handover from this device), and the
 | |
|      * other device is considered the <em>receiving</em> device.
 | |
|      * <p>
 | |
|      * When this method is called on the <em>initiating</em> device, the Telecom framework will bind
 | |
|      * to the {@link ConnectionService} defined by the {@code toHandle} {@link PhoneAccountHandle}
 | |
|      * and invoke
 | |
|      * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
 | |
|      * ConnectionRequest)} to inform the destination app that a request has been made to handover a
 | |
|      * call to it.  The app returns an instance of {@link Connection} to represent the handover call
 | |
|      * At this point the app should display UI to indicate to the user that a call
 | |
|      * handover is in process.
 | |
|      * <p>
 | |
|      * The destination app is responsible for communicating the handover request from the
 | |
|      * <em>initiating</em> device to the <em>receiving</em> device.
 | |
|      * <p>
 | |
|      * When the app on the <em>receiving</em> device receives the handover request, it calls
 | |
|      * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)} to continue the handover
 | |
|      * process from the <em>initiating</em> device to the <em>receiving</em> device.  At this point
 | |
|      * the destination app on the <em>receiving</em> device should show UI to allow the user to
 | |
|      * choose whether they want to continue their call in the destination app.
 | |
|      * <p>
 | |
|      * When the destination app on the <em>receiving</em> device calls
 | |
|      * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)}, Telecom will bind to its
 | |
|      * {@link ConnectionService} and call
 | |
|      * {@link ConnectionService#onCreateIncomingHandoverConnection(PhoneAccountHandle,
 | |
|      * ConnectionRequest)} to inform it of the handover request.  The app returns an instance of
 | |
|      * {@link Connection} to represent the handover call.
 | |
|      * <p>
 | |
|      * If the user of the <em>receiving</em> device accepts the handover, the app calls
 | |
|      * {@link Connection#setActive()} to complete the handover process; Telecom will disconnect the
 | |
|      * original call.  If the user rejects the handover, the app calls
 | |
|      * {@link Connection#setDisconnected(DisconnectCause)} and specifies a {@link DisconnectCause}
 | |
|      * of {@link DisconnectCause#CANCELED} to indicate that the handover has been cancelled.
 | |
|      * <p>
 | |
|      * Telecom will only allow handovers from {@link PhoneAccount}s which declare
 | |
|      * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}.  Similarly, the {@link PhoneAccount}
 | |
|      * specified by {@code toHandle} must declare {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}.
 | |
|      * <p>
 | |
|      * Errors in the handover process are reported to the {@link InCallService} via
 | |
|      * {@link Callback#onHandoverFailed(Call, int)}.  Errors in the handover process are reported to
 | |
|      * the involved {@link ConnectionService}s via
 | |
|      * {@link ConnectionService#onHandoverFailed(ConnectionRequest, int)}.
 | |
|      *
 | |
|      * @param toHandle {@link PhoneAccountHandle} of the {@link ConnectionService} to handover
 | |
|      *                 this call to.
 | |
|      * @param videoState Indicates the video state desired after the handover (see the
 | |
|      *               {@code STATE_*} constants defined in {@link VideoProfile}).
 | |
|      * @param extras Bundle containing extra information to be passed to the
 | |
|      *               {@link ConnectionService}
 | |
|      */
 | |
|     public void handoverTo(PhoneAccountHandle toHandle, @VideoProfile.VideoState int videoState,
 | |
|             Bundle extras) {
 | |
|         mInCallAdapter.handoverTo(mTelecomCallId, toHandle, videoState, extras);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Terminate the RTT session on this call. The resulting state change will be notified via
 | |
|      * the {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
 | |
|      */
 | |
|     public void stopRtt() {
 | |
|         mInCallAdapter.stopRtt(mTelecomCallId);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Adds some extras to this {@link Call}.  Existing keys are replaced and new ones are
 | |
|      * added.
 | |
|      * <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.
 | |
|      *
 | |
|      * @param extras The extras to add.
 | |
|      */
 | |
|     public final void putExtras(Bundle extras) {
 | |
|         if (extras == null) {
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         if (mExtras == null) {
 | |
|             mExtras = new Bundle();
 | |
|         }
 | |
|         mExtras.putAll(extras);
 | |
|         mInCallAdapter.putExtras(mTelecomCallId, extras);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Adds a boolean extra to this {@link Call}.
 | |
|      *
 | |
|      * @param key The extra key.
 | |
|      * @param value The value.
 | |
|      * @hide
 | |
|      */
 | |
|     public final void putExtra(String key, boolean value) {
 | |
|         if (mExtras == null) {
 | |
|             mExtras = new Bundle();
 | |
|         }
 | |
|         mExtras.putBoolean(key, value);
 | |
|         mInCallAdapter.putExtra(mTelecomCallId, key, value);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Adds an integer extra to this {@link Call}.
 | |
|      *
 | |
|      * @param key The extra key.
 | |
|      * @param value The value.
 | |
|      * @hide
 | |
|      */
 | |
|     public final void putExtra(String key, int value) {
 | |
|         if (mExtras == null) {
 | |
|             mExtras = new Bundle();
 | |
|         }
 | |
|         mExtras.putInt(key, value);
 | |
|         mInCallAdapter.putExtra(mTelecomCallId, key, value);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Adds a string extra to this {@link Call}.
 | |
|      *
 | |
|      * @param key The extra key.
 | |
|      * @param value The value.
 | |
|      * @hide
 | |
|      */
 | |
|     public final void putExtra(String key, String value) {
 | |
|         if (mExtras == null) {
 | |
|             mExtras = new Bundle();
 | |
|         }
 | |
|         mExtras.putString(key, value);
 | |
|         mInCallAdapter.putExtra(mTelecomCallId, key, value);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Removes extras from this {@link Call}.
 | |
|      *
 | |
|      * @param keys The keys of the extras to remove.
 | |
|      */
 | |
|     public final void removeExtras(List<String> keys) {
 | |
|         if (mExtras != null) {
 | |
|             for (String key : keys) {
 | |
|                 mExtras.remove(key);
 | |
|             }
 | |
|             if (mExtras.size() == 0) {
 | |
|                 mExtras = null;
 | |
|             }
 | |
|         }
 | |
|         mInCallAdapter.removeExtras(mTelecomCallId, keys);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Removes extras from this {@link Call}.
 | |
|      *
 | |
|      * @param keys The keys of the extras to remove.
 | |
|      */
 | |
|     public final void removeExtras(String ... keys) {
 | |
|         removeExtras(Arrays.asList(keys));
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Obtains the parent of this {@code Call} in a conference, if any.
 | |
|      *
 | |
|      * @return The parent {@code Call}, or {@code null} if this {@code Call} is not a
 | |
|      * child of any conference {@code Call}s.
 | |
|      */
 | |
|     public Call getParent() {
 | |
|         if (mParentId != null) {
 | |
|             return mPhone.internalGetCallByTelecomId(mParentId);
 | |
|         }
 | |
|         return null;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Obtains the children of this conference {@code Call}, if any.
 | |
|      *
 | |
|      * @return The children of this {@code Call} if this {@code Call} is a conference, or an empty
 | |
|      * {@code List} otherwise.
 | |
|      */
 | |
|     public List<Call> getChildren() {
 | |
|         if (!mChildrenCached) {
 | |
|             mChildrenCached = true;
 | |
|             mChildren.clear();
 | |
| 
 | |
|             for(String id : mChildrenIds) {
 | |
|                 Call call = mPhone.internalGetCallByTelecomId(id);
 | |
|                 if (call == null) {
 | |
|                     // At least one child was still not found, so do not save true for "cached"
 | |
|                     mChildrenCached = false;
 | |
|                 } else {
 | |
|                     mChildren.add(call);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         return mUnmodifiableChildren;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns the list of {@code Call}s with which this {@code Call} is allowed to conference.
 | |
|      *
 | |
|      * @return The list of conferenceable {@code Call}s.
 | |
|      */
 | |
|     public List<Call> getConferenceableCalls() {
 | |
|         return mUnmodifiableConferenceableCalls;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Obtains the state of this {@code Call}.
 | |
|      *
 | |
|      * @return The call state.
 | |
|      * @deprecated The call state is available via {@link Call.Details#getState()}.
 | |
|      */
 | |
|     @Deprecated
 | |
|     public @CallState int getState() {
 | |
|         return mState;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns the child {@link Call} in a generic conference that is currently active.
 | |
|      *
 | |
|      * A "generic conference" is the mechanism used to support two simultaneous calls on a device
 | |
|      * in CDMA networks. It is effectively equivalent to having one call active and one call on hold
 | |
|      * in GSM or IMS calls. This method returns the currently active call.
 | |
|      *
 | |
|      * In a generic conference, the network exposes the conference to us as a single call, and we
 | |
|      * switch between talking to the two participants using a CDMA flash command. Since the network
 | |
|      * exposes no additional information about the call, the only way we know which caller we're
 | |
|      * currently talking to is by keeping track of the flash commands that we've sent to the
 | |
|      * network.
 | |
|      *
 | |
|      * For calls that are not generic conferences, or when the generic conference has more than
 | |
|      * 2 children, returns {@code null}.
 | |
|      * @see Details#PROPERTY_GENERIC_CONFERENCE
 | |
|      * @return The active child call.
 | |
|      */
 | |
|     public @Nullable Call getGenericConferenceActiveChildCall() {
 | |
|         if (mActiveGenericConferenceChild != null) {
 | |
|             return mPhone.internalGetCallByTelecomId(mActiveGenericConferenceChild);
 | |
|         }
 | |
|         return null;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Obtains a list of canned, pre-configured message responses to present to the user as
 | |
|      * ways of rejecting an incoming {@code Call} using via a text message.
 | |
|      * <p>
 | |
|      * <em>Note:</em> Since canned responses may be loaded from the file system, they are not
 | |
|      * guaranteed to be present when this {@link Call} is first added to the {@link InCallService}
 | |
|      * via {@link InCallService#onCallAdded(Call)}.  The callback
 | |
|      * {@link Call.Callback#onCannedTextResponsesLoaded(Call, List)} will be called when/if canned
 | |
|      * responses for the call become available.
 | |
|      *
 | |
|      * @see #reject(boolean, String)
 | |
|      *
 | |
|      * @return A list of canned text message responses.
 | |
|      */
 | |
|     public List<String> getCannedTextResponses() {
 | |
|         return mCannedTextResponses;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Obtains an object that can be used to display video from this {@code Call}.
 | |
|      *
 | |
|      * @return An {@code Call.VideoCall}.
 | |
|      */
 | |
|     public InCallService.VideoCall getVideoCall() {
 | |
|         return mVideoCallImpl;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Obtains an object containing call details.
 | |
|      *
 | |
|      * @return A {@link Details} object. Depending on the state of the {@code Call}, the
 | |
|      * result may be {@code null}.
 | |
|      */
 | |
|     public Details getDetails() {
 | |
|         return mDetails;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns this call's RttCall object. The {@link RttCall} instance is used to send and
 | |
|      * receive RTT text data, as well as to change the RTT mode.
 | |
|      * @return A {@link Call.RttCall}. {@code null} if there is no active RTT connection.
 | |
|      */
 | |
|     public @Nullable RttCall getRttCall() {
 | |
|         return mRttCall;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns whether this call has an active RTT connection.
 | |
|      * @return true if there is a connection, false otherwise.
 | |
|      */
 | |
|     public boolean isRttActive() {
 | |
|         return mRttCall != null && mDetails.hasProperty(Details.PROPERTY_RTT);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Registers a callback to this {@code Call}.
 | |
|      *
 | |
|      * @param callback A {@code Callback}.
 | |
|      */
 | |
|     public void registerCallback(Callback callback) {
 | |
|         registerCallback(callback, new Handler());
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Registers a callback to this {@code Call}.
 | |
|      *
 | |
|      * @param callback A {@code Callback}.
 | |
|      * @param handler A handler which command and status changes will be delivered to.
 | |
|      */
 | |
|     public void registerCallback(Callback callback, Handler handler) {
 | |
|         unregisterCallback(callback);
 | |
|         // Don't allow new callback registration if the call is already being destroyed.
 | |
|         if (callback != null && handler != null && mState != STATE_DISCONNECTED) {
 | |
|             mCallbackRecords.add(new CallbackRecord<Callback>(callback, handler));
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Unregisters a callback from this {@code Call}.
 | |
|      *
 | |
|      * @param callback A {@code Callback}.
 | |
|      */
 | |
|     public void unregisterCallback(Callback callback) {
 | |
|         // Don't allow callback deregistration if the call is already being destroyed.
 | |
|         if (callback != null && mState != STATE_DISCONNECTED) {
 | |
|             for (CallbackRecord<Callback> record : mCallbackRecords) {
 | |
|                 if (record.getCallback() == callback) {
 | |
|                     mCallbackRecords.remove(record);
 | |
|                     break;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public String toString() {
 | |
|         return new StringBuilder().
 | |
|                 append("Call [id: ").
 | |
|                 append(mTelecomCallId).
 | |
|                 append(", state: ").
 | |
|                 append(stateToString(mState)).
 | |
|                 append(", details: ").
 | |
|                 append(mDetails).
 | |
|                 append("]").toString();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @param state An integer value of a {@code STATE_*} constant.
 | |
|      * @return A string representation of the value.
 | |
|      */
 | |
|     private static String stateToString(int state) {
 | |
|         switch (state) {
 | |
|             case STATE_NEW:
 | |
|                 return "NEW";
 | |
|             case STATE_RINGING:
 | |
|                 return "RINGING";
 | |
|             case STATE_DIALING:
 | |
|                 return "DIALING";
 | |
|             case STATE_ACTIVE:
 | |
|                 return "ACTIVE";
 | |
|             case STATE_HOLDING:
 | |
|                 return "HOLDING";
 | |
|             case STATE_DISCONNECTED:
 | |
|                 return "DISCONNECTED";
 | |
|             case STATE_CONNECTING:
 | |
|                 return "CONNECTING";
 | |
|             case STATE_DISCONNECTING:
 | |
|                 return "DISCONNECTING";
 | |
|             case STATE_SELECT_PHONE_ACCOUNT:
 | |
|                 return "SELECT_PHONE_ACCOUNT";
 | |
|             case STATE_SIMULATED_RINGING:
 | |
|                 return "SIMULATED_RINGING";
 | |
|             case STATE_AUDIO_PROCESSING:
 | |
|                 return "AUDIO_PROCESSING";
 | |
|             default:
 | |
|                 Log.w(Call.class, "Unknown state %d", state);
 | |
|                 return "UNKNOWN";
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Adds a listener to this {@code Call}.
 | |
|      *
 | |
|      * @param listener A {@code Listener}.
 | |
|      * @deprecated Use {@link #registerCallback} instead.
 | |
|      * @hide
 | |
|      */
 | |
|     @Deprecated
 | |
|     @SystemApi
 | |
|     public void addListener(Listener listener) {
 | |
|         registerCallback(listener);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Removes a listener from this {@code Call}.
 | |
|      *
 | |
|      * @param listener A {@code Listener}.
 | |
|      * @deprecated Use {@link #unregisterCallback} instead.
 | |
|      * @hide
 | |
|      */
 | |
|     @Deprecated
 | |
|     @SystemApi
 | |
|     public void removeListener(Listener listener) {
 | |
|         unregisterCallback(listener);
 | |
|     }
 | |
| 
 | |
|     /** {@hide} */
 | |
|     Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, String callingPackage,
 | |
|          int targetSdkVersion) {
 | |
|         mPhone = phone;
 | |
|         mTelecomCallId = telecomCallId;
 | |
|         mInCallAdapter = inCallAdapter;
 | |
|         mState = STATE_NEW;
 | |
|         mCallingPackage = callingPackage;
 | |
|         mTargetSdkVersion = targetSdkVersion;
 | |
|     }
 | |
| 
 | |
|     /** {@hide} */
 | |
|     Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, int state,
 | |
|             String callingPackage, int targetSdkVersion) {
 | |
|         mPhone = phone;
 | |
|         mTelecomCallId = telecomCallId;
 | |
|         mInCallAdapter = inCallAdapter;
 | |
|         mState = state;
 | |
|         mCallingPackage = callingPackage;
 | |
|         mTargetSdkVersion = targetSdkVersion;
 | |
|     }
 | |
| 
 | |
|     /** {@hide} */
 | |
|     final String internalGetCallId() {
 | |
|         return mTelecomCallId;
 | |
|     }
 | |
| 
 | |
|     /** {@hide} */
 | |
|     final void internalUpdate(ParcelableCall parcelableCall, Map<String, Call> callIdMap) {
 | |
| 
 | |
|         // First, we update the internal state as far as possible before firing any updates.
 | |
|         Details details = Details.createFromParcelableCall(parcelableCall);
 | |
|         boolean detailsChanged = !Objects.equals(mDetails, details);
 | |
|         if (detailsChanged) {
 | |
|             mDetails = details;
 | |
|         }
 | |
| 
 | |
|         boolean cannedTextResponsesChanged = false;
 | |
|         if (mCannedTextResponses == null && parcelableCall.getCannedSmsResponses() != null
 | |
|                 && !parcelableCall.getCannedSmsResponses().isEmpty()) {
 | |
|             mCannedTextResponses =
 | |
|                     Collections.unmodifiableList(parcelableCall.getCannedSmsResponses());
 | |
|             cannedTextResponsesChanged = true;
 | |
|         }
 | |
| 
 | |
|         IVideoProvider previousVideoProvider = mVideoCallImpl == null ? null :
 | |
|                 mVideoCallImpl.getVideoProvider();
 | |
|         IVideoProvider newVideoProvider = parcelableCall.getVideoProvider();
 | |
| 
 | |
|         // parcelableCall.isVideoCallProviderChanged is only true when we have a video provider
 | |
|         // specified; so we should check if the actual IVideoProvider changes as well.
 | |
|         boolean videoCallChanged = parcelableCall.isVideoCallProviderChanged()
 | |
|                 && !Objects.equals(previousVideoProvider, newVideoProvider);
 | |
|         if (videoCallChanged) {
 | |
|             if (mVideoCallImpl != null) {
 | |
|                 mVideoCallImpl.destroy();
 | |
|             }
 | |
|             mVideoCallImpl = parcelableCall.isVideoCallProviderChanged() ?
 | |
|                     parcelableCall.getVideoCallImpl(mCallingPackage, mTargetSdkVersion) : null;
 | |
|         }
 | |
| 
 | |
|         if (mVideoCallImpl != null) {
 | |
|             mVideoCallImpl.setVideoState(getDetails().getVideoState());
 | |
|         }
 | |
| 
 | |
|         int state = parcelableCall.getState();
 | |
|         if (mTargetSdkVersion < Phone.SDK_VERSION_R && state == Call.STATE_SIMULATED_RINGING) {
 | |
|             state = Call.STATE_RINGING;
 | |
|         }
 | |
|         boolean stateChanged = mState != state;
 | |
|         if (stateChanged) {
 | |
|             mState = state;
 | |
|         }
 | |
| 
 | |
|         String parentId = parcelableCall.getParentCallId();
 | |
|         boolean parentChanged = !Objects.equals(mParentId, parentId);
 | |
|         if (parentChanged) {
 | |
|             mParentId = parentId;
 | |
|         }
 | |
| 
 | |
|         List<String> childCallIds = parcelableCall.getChildCallIds();
 | |
|         boolean childrenChanged = !Objects.equals(childCallIds, mChildrenIds);
 | |
|         if (childrenChanged) {
 | |
|             mChildrenIds.clear();
 | |
|             mChildrenIds.addAll(parcelableCall.getChildCallIds());
 | |
|             mChildrenCached = false;
 | |
|         }
 | |
| 
 | |
|         String activeChildCallId = parcelableCall.getActiveChildCallId();
 | |
|         boolean activeChildChanged = !Objects.equals(activeChildCallId,
 | |
|                 mActiveGenericConferenceChild);
 | |
|         if (activeChildChanged) {
 | |
|             mActiveGenericConferenceChild = activeChildCallId;
 | |
|         }
 | |
| 
 | |
|         List<String> conferenceableCallIds = parcelableCall.getConferenceableCallIds();
 | |
|         List<Call> conferenceableCalls = new ArrayList<Call>(conferenceableCallIds.size());
 | |
|         for (String otherId : conferenceableCallIds) {
 | |
|             if (callIdMap.containsKey(otherId)) {
 | |
|                 conferenceableCalls.add(callIdMap.get(otherId));
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if (!Objects.equals(mConferenceableCalls, conferenceableCalls)) {
 | |
|             mConferenceableCalls.clear();
 | |
|             mConferenceableCalls.addAll(conferenceableCalls);
 | |
|             fireConferenceableCallsChanged();
 | |
|         }
 | |
| 
 | |
|         boolean isRttChanged = false;
 | |
|         boolean rttModeChanged = false;
 | |
|         if (parcelableCall.getIsRttCallChanged()
 | |
|                 && mDetails.hasProperty(Details.PROPERTY_RTT)) {
 | |
|             ParcelableRttCall parcelableRttCall = parcelableCall.getParcelableRttCall();
 | |
|             InputStreamReader receiveStream = new InputStreamReader(
 | |
|                     new ParcelFileDescriptor.AutoCloseInputStream(
 | |
|                             parcelableRttCall.getReceiveStream()),
 | |
|                     StandardCharsets.UTF_8);
 | |
|             OutputStreamWriter transmitStream = new OutputStreamWriter(
 | |
|                     new ParcelFileDescriptor.AutoCloseOutputStream(
 | |
|                             parcelableRttCall.getTransmitStream()),
 | |
|                     StandardCharsets.UTF_8);
 | |
|             RttCall newRttCall = new Call.RttCall(mTelecomCallId,
 | |
|                     receiveStream, transmitStream, parcelableRttCall.getRttMode(), mInCallAdapter);
 | |
|             if (mRttCall == null) {
 | |
|                 isRttChanged = true;
 | |
|             } else if (mRttCall.getRttAudioMode() != newRttCall.getRttAudioMode()) {
 | |
|                 rttModeChanged = true;
 | |
|             }
 | |
|             mRttCall = newRttCall;
 | |
|         } else if (mRttCall != null && parcelableCall.getParcelableRttCall() == null
 | |
|                 && parcelableCall.getIsRttCallChanged()) {
 | |
|             isRttChanged = true;
 | |
|             mRttCall.close();
 | |
|             mRttCall = null;
 | |
|         }
 | |
| 
 | |
|         // Now we fire updates, ensuring that any client who listens to any of these notifications
 | |
|         // gets the most up-to-date state.
 | |
| 
 | |
|         if (stateChanged) {
 | |
|             fireStateChanged(mState);
 | |
|         }
 | |
|         if (detailsChanged) {
 | |
|             fireDetailsChanged(mDetails);
 | |
|         }
 | |
|         if (cannedTextResponsesChanged) {
 | |
|             fireCannedTextResponsesLoaded(mCannedTextResponses);
 | |
|         }
 | |
|         if (videoCallChanged) {
 | |
|             fireVideoCallChanged(mVideoCallImpl);
 | |
|         }
 | |
|         if (parentChanged) {
 | |
|             fireParentChanged(getParent());
 | |
|         }
 | |
|         if (childrenChanged || activeChildChanged) {
 | |
|             fireChildrenChanged(getChildren());
 | |
|         }
 | |
|         if (isRttChanged) {
 | |
|             fireOnIsRttChanged(mRttCall != null, mRttCall);
 | |
|         }
 | |
|         if (rttModeChanged) {
 | |
|             fireOnRttModeChanged(mRttCall.getRttAudioMode());
 | |
|         }
 | |
| 
 | |
|         // If we have transitioned to DISCONNECTED, that means we need to notify clients and
 | |
|         // remove ourselves from the Phone. Note that we do this after completing all state updates
 | |
|         // so a client can cleanly transition all their UI to the state appropriate for a
 | |
|         // DISCONNECTED Call while still relying on the existence of that Call in the Phone's list.
 | |
|         if (mState == STATE_DISCONNECTED) {
 | |
|             fireCallDestroyed();
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /** {@hide} */
 | |
|     final void internalSetPostDialWait(String remaining) {
 | |
|         mRemainingPostDialSequence = remaining;
 | |
|         firePostDialWait(mRemainingPostDialSequence);
 | |
|     }
 | |
| 
 | |
|     /** {@hide} */
 | |
|     final void internalSetDisconnected() {
 | |
|         if (mState != Call.STATE_DISCONNECTED) {
 | |
|             mState = Call.STATE_DISCONNECTED;
 | |
|             if (mDetails != null) {
 | |
|                 mDetails = new Details(mState,
 | |
|                         mDetails.getTelecomCallId(),
 | |
|                         mDetails.getHandle(),
 | |
|                         mDetails.getHandlePresentation(),
 | |
|                         mDetails.getCallerDisplayName(),
 | |
|                         mDetails.getCallerDisplayNamePresentation(),
 | |
|                         mDetails.getAccountHandle(),
 | |
|                         mDetails.getCallCapabilities(),
 | |
|                         mDetails.getCallProperties(),
 | |
|                         mDetails.getDisconnectCause(),
 | |
|                         mDetails.getConnectTimeMillis(),
 | |
|                         mDetails.getGatewayInfo(),
 | |
|                         mDetails.getVideoState(),
 | |
|                         mDetails.getStatusHints(),
 | |
|                         mDetails.getExtras(),
 | |
|                         mDetails.getIntentExtras(),
 | |
|                         mDetails.getCreationTimeMillis(),
 | |
|                         mDetails.getContactDisplayName(),
 | |
|                         mDetails.getCallDirection(),
 | |
|                         mDetails.getCallerNumberVerificationStatus()
 | |
|                         );
 | |
|                 fireDetailsChanged(mDetails);
 | |
|             }
 | |
|             fireStateChanged(mState);
 | |
|             fireCallDestroyed();
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /** {@hide} */
 | |
|     final void internalOnConnectionEvent(String event, Bundle extras) {
 | |
|         fireOnConnectionEvent(event, extras);
 | |
|     }
 | |
| 
 | |
|     /** {@hide} */
 | |
|     final void internalOnRttUpgradeRequest(final int requestId) {
 | |
|         for (CallbackRecord<Callback> record : mCallbackRecords) {
 | |
|             final Call call = this;
 | |
|             final Callback callback = record.getCallback();
 | |
|             record.getHandler().post(() -> callback.onRttRequest(call, requestId));
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /** @hide */
 | |
|     final void internalOnRttInitiationFailure(int reason) {
 | |
|         for (CallbackRecord<Callback> record : mCallbackRecords) {
 | |
|             final Call call = this;
 | |
|             final Callback callback = record.getCallback();
 | |
|             record.getHandler().post(() -> callback.onRttInitiationFailure(call, reason));
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /** {@hide} */
 | |
|     final void internalOnHandoverFailed(int error) {
 | |
|         for (CallbackRecord<Callback> record : mCallbackRecords) {
 | |
|             final Call call = this;
 | |
|             final Callback callback = record.getCallback();
 | |
|             record.getHandler().post(() -> callback.onHandoverFailed(call, error));
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /** {@hide} */
 | |
|     final void internalOnHandoverComplete() {
 | |
|         for (CallbackRecord<Callback> record : mCallbackRecords) {
 | |
|             final Call call = this;
 | |
|             final Callback callback = record.getCallback();
 | |
|             record.getHandler().post(() -> callback.onHandoverComplete(call));
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     private void fireStateChanged(final int newState) {
 | |
|         for (CallbackRecord<Callback> record : mCallbackRecords) {
 | |
|             final Call call = this;
 | |
|             final Callback callback = record.getCallback();
 | |
|             record.getHandler().post(new Runnable() {
 | |
|                 @Override
 | |
|                 public void run() {
 | |
|                     callback.onStateChanged(call, newState);
 | |
|                 }
 | |
|             });
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     private void fireParentChanged(final Call newParent) {
 | |
|         for (CallbackRecord<Callback> record : mCallbackRecords) {
 | |
|             final Call call = this;
 | |
|             final Callback callback = record.getCallback();
 | |
|             record.getHandler().post(new Runnable() {
 | |
|                 @Override
 | |
|                 public void run() {
 | |
|                     callback.onParentChanged(call, newParent);
 | |
|                 }
 | |
|             });
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     private void fireChildrenChanged(final List<Call> children) {
 | |
|         for (CallbackRecord<Callback> record : mCallbackRecords) {
 | |
|             final Call call = this;
 | |
|             final Callback callback = record.getCallback();
 | |
|             record.getHandler().post(new Runnable() {
 | |
|                 @Override
 | |
|                 public void run() {
 | |
|                     callback.onChildrenChanged(call, children);
 | |
|                 }
 | |
|             });
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     private void fireDetailsChanged(final Details details) {
 | |
|         for (CallbackRecord<Callback> record : mCallbackRecords) {
 | |
|             final Call call = this;
 | |
|             final Callback callback = record.getCallback();
 | |
|             record.getHandler().post(new Runnable() {
 | |
|                 @Override
 | |
|                 public void run() {
 | |
|                     callback.onDetailsChanged(call, details);
 | |
|                 }
 | |
|             });
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     private void fireCannedTextResponsesLoaded(final List<String> cannedTextResponses) {
 | |
|         for (CallbackRecord<Callback> record : mCallbackRecords) {
 | |
|             final Call call = this;
 | |
|             final Callback callback = record.getCallback();
 | |
|             record.getHandler().post(new Runnable() {
 | |
|                 @Override
 | |
|                 public void run() {
 | |
|                     callback.onCannedTextResponsesLoaded(call, cannedTextResponses);
 | |
|                 }
 | |
|             });
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     private void fireVideoCallChanged(final InCallService.VideoCall videoCall) {
 | |
|         for (CallbackRecord<Callback> record : mCallbackRecords) {
 | |
|             final Call call = this;
 | |
|             final Callback callback = record.getCallback();
 | |
|             record.getHandler().post(new Runnable() {
 | |
|                 @Override
 | |
|                 public void run() {
 | |
|                     callback.onVideoCallChanged(call, videoCall);
 | |
|                 }
 | |
|             });
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     private void firePostDialWait(final String remainingPostDialSequence) {
 | |
|         for (CallbackRecord<Callback> record : mCallbackRecords) {
 | |
|             final Call call = this;
 | |
|             final Callback callback = record.getCallback();
 | |
|             record.getHandler().post(new Runnable() {
 | |
|                 @Override
 | |
|                 public void run() {
 | |
|                     callback.onPostDialWait(call, remainingPostDialSequence);
 | |
|                 }
 | |
|             });
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     private void fireCallDestroyed() {
 | |
|         /**
 | |
|          * To preserve the ordering of the Call's onCallDestroyed callback and Phone's
 | |
|          * onCallRemoved callback, we remove this call from the Phone's record
 | |
|          * only once all of the registered onCallDestroyed callbacks are executed.
 | |
|          * All the callbacks get removed from our records as a part of this operation
 | |
|          * since onCallDestroyed is the final callback.
 | |
|          */
 | |
|         final Call call = this;
 | |
|         if (mCallbackRecords.isEmpty()) {
 | |
|             // No callbacks registered, remove the call from Phone's record.
 | |
|             mPhone.internalRemoveCall(call);
 | |
|         }
 | |
|         for (final CallbackRecord<Callback> record : mCallbackRecords) {
 | |
|             final Callback callback = record.getCallback();
 | |
|             record.getHandler().post(new Runnable() {
 | |
|                 @Override
 | |
|                 public void run() {
 | |
|                     boolean isFinalRemoval = false;
 | |
|                     RuntimeException toThrow = null;
 | |
|                     try {
 | |
|                         callback.onCallDestroyed(call);
 | |
|                     } catch (RuntimeException e) {
 | |
|                             toThrow = e;
 | |
|                     }
 | |
|                     synchronized(Call.this) {
 | |
|                         mCallbackRecords.remove(record);
 | |
|                         if (mCallbackRecords.isEmpty()) {
 | |
|                             isFinalRemoval = true;
 | |
|                         }
 | |
|                     }
 | |
|                     if (isFinalRemoval) {
 | |
|                         mPhone.internalRemoveCall(call);
 | |
|                     }
 | |
|                     if (toThrow != null) {
 | |
|                         throw toThrow;
 | |
|                     }
 | |
|                 }
 | |
|             });
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     private void fireConferenceableCallsChanged() {
 | |
|         for (CallbackRecord<Callback> record : mCallbackRecords) {
 | |
|             final Call call = this;
 | |
|             final Callback callback = record.getCallback();
 | |
|             record.getHandler().post(new Runnable() {
 | |
|                 @Override
 | |
|                 public void run() {
 | |
|                     callback.onConferenceableCallsChanged(call, mUnmodifiableConferenceableCalls);
 | |
|                 }
 | |
|             });
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Notifies listeners of an incoming connection event.
 | |
|      * <p>
 | |
|      * Connection events are issued via {@link Connection#sendConnectionEvent(String, Bundle)}.
 | |
|      *
 | |
|      * @param event
 | |
|      * @param extras
 | |
|      */
 | |
|     private void fireOnConnectionEvent(final String event, final Bundle extras) {
 | |
|         for (CallbackRecord<Callback> record : mCallbackRecords) {
 | |
|             final Call call = this;
 | |
|             final Callback callback = record.getCallback();
 | |
|             record.getHandler().post(new Runnable() {
 | |
|                 @Override
 | |
|                 public void run() {
 | |
|                     callback.onConnectionEvent(call, event, extras);
 | |
|                 }
 | |
|             });
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Notifies listeners of an RTT on/off change
 | |
|      *
 | |
|      * @param enabled True if RTT is now enabled, false otherwise
 | |
|      */
 | |
|     private void fireOnIsRttChanged(final boolean enabled, final RttCall rttCall) {
 | |
|         for (CallbackRecord<Callback> record : mCallbackRecords) {
 | |
|             final Call call = this;
 | |
|             final Callback callback = record.getCallback();
 | |
|             record.getHandler().post(() -> callback.onRttStatusChanged(call, enabled, rttCall));
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Notifies listeners of a RTT mode change
 | |
|      *
 | |
|      * @param mode The new RTT mode
 | |
|      */
 | |
|     private void fireOnRttModeChanged(final int mode) {
 | |
|         for (CallbackRecord<Callback> record : mCallbackRecords) {
 | |
|             final Call call = this;
 | |
|             final Callback callback = record.getCallback();
 | |
|             record.getHandler().post(() -> callback.onRttModeChanged(call, mode));
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Determines if two bundles are equal.
 | |
|      *
 | |
|      * @param bundle The original bundle.
 | |
|      * @param newBundle The bundle to compare with.
 | |
|      * @retrun {@code true} if the bundles are equal, {@code false} otherwise.
 | |
|      */
 | |
|     private static boolean areBundlesEqual(Bundle bundle, Bundle newBundle) {
 | |
|         if (bundle == null || newBundle == null) {
 | |
|             return bundle == newBundle;
 | |
|         }
 | |
| 
 | |
|         if (bundle.size() != newBundle.size()) {
 | |
|             return false;
 | |
|         }
 | |
| 
 | |
|         for(String key : bundle.keySet()) {
 | |
|             if (key != null) {
 | |
|                 final Object value = bundle.get(key);
 | |
|                 final Object newValue = newBundle.get(key);
 | |
|                 if (!newBundle.containsKey(key)) {
 | |
|                     return false;
 | |
|                 }
 | |
|                 if (value instanceof Bundle && newValue instanceof Bundle) {
 | |
|                     if (!areBundlesEqual((Bundle) value, (Bundle) newValue)) {
 | |
|                         return false;
 | |
|                     }
 | |
|                 }
 | |
|                 if (value instanceof byte[] && newValue instanceof byte[]) {
 | |
|                     if (!Arrays.equals((byte[]) value, (byte[]) newValue)) {
 | |
|                         return false;
 | |
|                     }
 | |
|                 } else if (!Objects.equals(value, newValue)) {
 | |
|                     return false;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         return true;
 | |
|     }
 | |
| }
 |