Home | History | Annotate | Download | only in telecom
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.telecom;
     18 
     19 import android.annotation.IntDef;
     20 import android.annotation.Nullable;
     21 import android.annotation.SystemApi;
     22 import android.net.Uri;
     23 import android.os.Bundle;
     24 import android.os.Handler;
     25 import android.os.ParcelFileDescriptor;
     26 
     27 import java.io.IOException;
     28 import java.io.InputStreamReader;
     29 import java.io.OutputStreamWriter;
     30 import java.lang.String;
     31 import java.lang.annotation.Retention;
     32 import java.lang.annotation.RetentionPolicy;
     33 import java.nio.charset.StandardCharsets;
     34 import java.util.ArrayList;
     35 import java.util.Arrays;
     36 import java.util.Collections;
     37 import java.util.List;
     38 import java.util.Map;
     39 import java.util.Objects;
     40 import java.util.concurrent.CopyOnWriteArrayList;
     41 
     42 /**
     43  * Represents an ongoing phone call that the in-call app should present to the user.
     44  */
     45 public final class Call {
     46     /**
     47      * The state of a {@code Call} when newly created.
     48      */
     49     public static final int STATE_NEW = 0;
     50 
     51     /**
     52      * The state of an outgoing {@code Call} when dialing the remote number, but not yet connected.
     53      */
     54     public static final int STATE_DIALING = 1;
     55 
     56     /**
     57      * The state of an incoming {@code Call} when ringing locally, but not yet connected.
     58      */
     59     public static final int STATE_RINGING = 2;
     60 
     61     /**
     62      * The state of a {@code Call} when in a holding state.
     63      */
     64     public static final int STATE_HOLDING = 3;
     65 
     66     /**
     67      * The state of a {@code Call} when actively supporting conversation.
     68      */
     69     public static final int STATE_ACTIVE = 4;
     70 
     71     /**
     72      * The state of a {@code Call} when no further voice or other communication is being
     73      * transmitted, the remote side has been or will inevitably be informed that the {@code Call}
     74      * is no longer active, and the local data transport has or inevitably will release resources
     75      * associated with this {@code Call}.
     76      */
     77     public static final int STATE_DISCONNECTED = 7;
     78 
     79     /**
     80      * The state of an outgoing {@code Call} when waiting on user to select a
     81      * {@link PhoneAccount} through which to place the call.
     82      */
     83     public static final int STATE_SELECT_PHONE_ACCOUNT = 8;
     84 
     85     /**
     86      * @hide
     87      * @deprecated use STATE_SELECT_PHONE_ACCOUNT.
     88      */
     89     @Deprecated
     90     @SystemApi
     91     public static final int STATE_PRE_DIAL_WAIT = STATE_SELECT_PHONE_ACCOUNT;
     92 
     93     /**
     94      * The initial state of an outgoing {@code Call}.
     95      * Common transitions are to {@link #STATE_DIALING} state for a successful call or
     96      * {@link #STATE_DISCONNECTED} if it failed.
     97      */
     98     public static final int STATE_CONNECTING = 9;
     99 
    100     /**
    101      * The state of a {@code Call} when the user has initiated a disconnection of the call, but the
    102      * call has not yet been disconnected by the underlying {@code ConnectionService}.  The next
    103      * state of the call is (potentially) {@link #STATE_DISCONNECTED}.
    104      */
    105     public static final int STATE_DISCONNECTING = 10;
    106 
    107     /**
    108      * The state of an external call which is in the process of being pulled from a remote device to
    109      * the local device.
    110      * <p>
    111      * A call can only be in this state if the {@link Details#PROPERTY_IS_EXTERNAL_CALL} property
    112      * and {@link Details#CAPABILITY_CAN_PULL_CALL} capability are set on the call.
    113      * <p>
    114      * An {@link InCallService} will only see this state if it has the
    115      * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true} in its
    116      * manifest.
    117      */
    118     public static final int STATE_PULLING_CALL = 11;
    119 
    120     /**
    121      * The key to retrieve the optional {@code PhoneAccount}s Telecom can bundle with its Call
    122      * extras. Used to pass the phone accounts to display on the front end to the user in order to
    123      * select phone accounts to (for example) place a call.
    124      */
    125     public static final String AVAILABLE_PHONE_ACCOUNTS = "selectPhoneAccountAccounts";
    126 
    127     /**
    128      * Extra key used to indicate the time (in milliseconds since midnight, January 1, 1970 UTC)
    129      * when the last outgoing emergency call was made.  This is used to identify potential emergency
    130      * callbacks.
    131      */
    132     public static final String EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS =
    133             "android.telecom.extra.LAST_EMERGENCY_CALLBACK_TIME_MILLIS";
    134 
    135     /**
    136      * Call event sent from a {@link Call} via {@link #sendCallEvent(String, Bundle)} to inform
    137      * Telecom that the user has requested that the current {@link Call} should be handed over
    138      * to another {@link ConnectionService}.
    139      * <p>
    140      * The caller must specify the {@link #EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE} to indicate to
    141      * Telecom which {@link PhoneAccountHandle} the {@link Call} should be handed over to.
    142      * @hide
    143      */
    144     public static final String EVENT_REQUEST_HANDOVER =
    145             "android.telecom.event.REQUEST_HANDOVER";
    146 
    147     /**
    148      * Extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event.  Specifies the
    149      * {@link PhoneAccountHandle} to which a call should be handed over to.
    150      * @hide
    151      */
    152     public static final String EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE =
    153             "android.telecom.extra.HANDOVER_PHONE_ACCOUNT_HANDLE";
    154 
    155     /**
    156      * Integer extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event.  Specifies the
    157      * video state of the call when it is handed over to the new {@link PhoneAccount}.
    158      * <p>
    159      * Valid values: {@link VideoProfile#STATE_AUDIO_ONLY},
    160      * {@link VideoProfile#STATE_BIDIRECTIONAL}, {@link VideoProfile#STATE_RX_ENABLED}, and
    161      * {@link VideoProfile#STATE_TX_ENABLED}.
    162      * @hide
    163      */
    164     public static final String EXTRA_HANDOVER_VIDEO_STATE =
    165             "android.telecom.extra.HANDOVER_VIDEO_STATE";
    166 
    167     /**
    168      * Extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event.  Used by the
    169      * {@link InCallService} initiating a handover to provide a {@link Bundle} with extra
    170      * information to the handover {@link ConnectionService} specified by
    171      * {@link #EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE}.
    172      * <p>
    173      * This {@link Bundle} is not interpreted by Telecom, but passed as-is to the
    174      * {@link ConnectionService} via the request extras when
    175      * {@link ConnectionService#onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}
    176      * is called to initate the handover.
    177      * @hide
    178      */
    179     public static final String EXTRA_HANDOVER_EXTRAS = "android.telecom.extra.HANDOVER_EXTRAS";
    180 
    181     /**
    182      * Call event sent from Telecom to the handover {@link ConnectionService} via
    183      * {@link Connection#onCallEvent(String, Bundle)} to inform a {@link Connection} that a handover
    184      * to the {@link ConnectionService} has completed successfully.
    185      * <p>
    186      * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
    187      * @hide
    188      */
    189     public static final String EVENT_HANDOVER_COMPLETE =
    190             "android.telecom.event.HANDOVER_COMPLETE";
    191 
    192     /**
    193      * Call event sent from Telecom to the handover destination {@link ConnectionService} via
    194      * {@link Connection#onCallEvent(String, Bundle)} to inform the handover destination that the
    195      * source connection has disconnected.  The {@link Bundle} parameter for the call event will be
    196      * {@code null}.
    197      * <p>
    198      * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
    199      * @hide
    200      */
    201     public static final String EVENT_HANDOVER_SOURCE_DISCONNECTED =
    202             "android.telecom.event.HANDOVER_SOURCE_DISCONNECTED";
    203 
    204     /**
    205      * Call event sent from Telecom to the handover {@link ConnectionService} via
    206      * {@link Connection#onCallEvent(String, Bundle)} to inform a {@link Connection} that a handover
    207      * to the {@link ConnectionService} has failed.
    208      * <p>
    209      * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
    210      * @hide
    211      */
    212     public static final String EVENT_HANDOVER_FAILED =
    213             "android.telecom.event.HANDOVER_FAILED";
    214 
    215     public static class Details {
    216 
    217         /** Call can currently be put on hold or unheld. */
    218         public static final int CAPABILITY_HOLD = 0x00000001;
    219 
    220         /** Call supports the hold feature. */
    221         public static final int CAPABILITY_SUPPORT_HOLD = 0x00000002;
    222 
    223         /**
    224          * Calls within a conference can be merged. A {@link ConnectionService} has the option to
    225          * add a {@link Conference} call before the child {@link Connection}s are merged. This is how
    226          * CDMA-based {@link Connection}s are implemented. For these unmerged {@link Conference}s, this
    227          * capability allows a merge button to be shown while the conference call is in the foreground
    228          * of the in-call UI.
    229          * <p>
    230          * This is only intended for use by a {@link Conference}.
    231          */
    232         public static final int CAPABILITY_MERGE_CONFERENCE = 0x00000004;
    233 
    234         /**
    235          * Calls within a conference can be swapped between foreground and background.
    236          * See {@link #CAPABILITY_MERGE_CONFERENCE} for additional information.
    237          * <p>
    238          * This is only intended for use by a {@link Conference}.
    239          */
    240         public static final int CAPABILITY_SWAP_CONFERENCE = 0x00000008;
    241 
    242         /**
    243          * @hide
    244          */
    245         public static final int CAPABILITY_UNUSED_1 = 0x00000010;
    246 
    247         /** Call supports responding via text option. */
    248         public static final int CAPABILITY_RESPOND_VIA_TEXT = 0x00000020;
    249 
    250         /** Call can be muted. */
    251         public static final int CAPABILITY_MUTE = 0x00000040;
    252 
    253         /**
    254          * Call supports conference call management. This capability only applies to {@link Conference}
    255          * calls which can have {@link Connection}s as children.
    256          */
    257         public static final int CAPABILITY_MANAGE_CONFERENCE = 0x00000080;
    258 
    259         /**
    260          * Local device supports receiving video.
    261          */
    262         public static final int CAPABILITY_SUPPORTS_VT_LOCAL_RX = 0x00000100;
    263 
    264         /**
    265          * Local device supports transmitting video.
    266          */
    267         public static final int CAPABILITY_SUPPORTS_VT_LOCAL_TX = 0x00000200;
    268 
    269         /**
    270          * Local device supports bidirectional video calling.
    271          */
    272         public static final int CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL =
    273                 CAPABILITY_SUPPORTS_VT_LOCAL_RX | CAPABILITY_SUPPORTS_VT_LOCAL_TX;
    274 
    275         /**
    276          * Remote device supports receiving video.
    277          */
    278         public static final int CAPABILITY_SUPPORTS_VT_REMOTE_RX = 0x00000400;
    279 
    280         /**
    281          * Remote device supports transmitting video.
    282          */
    283         public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 0x00000800;
    284 
    285         /**
    286          * Remote device supports bidirectional video calling.
    287          */
    288         public static final int CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL =
    289                 CAPABILITY_SUPPORTS_VT_REMOTE_RX | CAPABILITY_SUPPORTS_VT_REMOTE_TX;
    290 
    291         /**
    292          * Call is able to be separated from its parent {@code Conference}, if any.
    293          */
    294         public static final int CAPABILITY_SEPARATE_FROM_CONFERENCE = 0x00001000;
    295 
    296         /**
    297          * Call is able to be individually disconnected when in a {@code Conference}.
    298          */
    299         public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 0x00002000;
    300 
    301         /**
    302          * Speed up audio setup for MT call.
    303          * @hide
    304          */
    305         public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00040000;
    306 
    307         /**
    308          * Call can be upgraded to a video call.
    309          * @hide
    310          */
    311         public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 0x00080000;
    312 
    313         /**
    314          * For video calls, indicates whether the outgoing video for the call can be paused using
    315          * the {@link android.telecom.VideoProfile#STATE_PAUSED} VideoState.
    316          */
    317         public static final int CAPABILITY_CAN_PAUSE_VIDEO = 0x00100000;
    318 
    319         /**
    320          * Call sends responses through connection.
    321          * @hide
    322          */
    323         public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 0x00200000;
    324 
    325         /**
    326          * When set, prevents a video {@code Call} from being downgraded to an audio-only call.
    327          * <p>
    328          * Should be set when the VideoState has the {@link VideoProfile#STATE_TX_ENABLED} or
    329          * {@link VideoProfile#STATE_RX_ENABLED} bits set to indicate that the connection cannot be
    330          * downgraded from a video call back to a VideoState of
    331          * {@link VideoProfile#STATE_AUDIO_ONLY}.
    332          * <p>
    333          * Intuitively, a call which can be downgraded to audio should also have local and remote
    334          * video
    335          * capabilities (see {@link #CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL} and
    336          * {@link #CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL}).
    337          */
    338         public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 0x00400000;
    339 
    340         /**
    341          * When set for an external call, indicates that this {@code Call} can be pulled from a
    342          * remote device to the current device.
    343          * <p>
    344          * Should only be set on a {@code Call} where {@link #PROPERTY_IS_EXTERNAL_CALL} is set.
    345          * <p>
    346          * An {@link InCallService} will only see calls with this capability if it has the
    347          * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
    348          * in its manifest.
    349          * <p>
    350          * See {@link Connection#CAPABILITY_CAN_PULL_CALL} and
    351          * {@link Connection#PROPERTY_IS_EXTERNAL_CALL}.
    352          */
    353         public static final int CAPABILITY_CAN_PULL_CALL = 0x00800000;
    354 
    355         /** Call supports the deflect feature. */
    356         public static final int CAPABILITY_SUPPORT_DEFLECT = 0x01000000;
    357 
    358         //******************************************************************************************
    359         // Next CAPABILITY value: 0x02000000
    360         //******************************************************************************************
    361 
    362         /**
    363          * Whether the call is currently a conference.
    364          */
    365         public static final int PROPERTY_CONFERENCE = 0x00000001;
    366 
    367         /**
    368          * Whether the call is a generic conference, where we do not know the precise state of
    369          * participants in the conference (eg. on CDMA).
    370          */
    371         public static final int PROPERTY_GENERIC_CONFERENCE = 0x00000002;
    372 
    373         /**
    374          * Whether the call is made while the device is in emergency callback mode.
    375          */
    376         public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 0x00000004;
    377 
    378         /**
    379          * Connection is using WIFI.
    380          */
    381         public static final int PROPERTY_WIFI = 0x00000008;
    382 
    383         /**
    384          * Call is using high definition audio.
    385          */
    386         public static final int PROPERTY_HIGH_DEF_AUDIO = 0x00000010;
    387 
    388         /**
    389          * Whether the call is associated with the work profile.
    390          */
    391         public static final int PROPERTY_ENTERPRISE_CALL = 0x00000020;
    392 
    393         /**
    394          * When set, indicates that this {@code Call} does not actually exist locally for the
    395          * {@link ConnectionService}.
    396          * <p>
    397          * Consider, for example, a scenario where a user has two phones with the same phone number.
    398          * When a user places a call on one device, the telephony stack can represent that call on
    399          * the other device by adding it to the {@link ConnectionService} with the
    400          * {@link Connection#PROPERTY_IS_EXTERNAL_CALL} property set.
    401          * <p>
    402          * An {@link InCallService} will only see calls with this property if it has the
    403          * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
    404          * in its manifest.
    405          * <p>
    406          * See {@link Connection#PROPERTY_IS_EXTERNAL_CALL}.
    407          */
    408         public static final int PROPERTY_IS_EXTERNAL_CALL = 0x00000040;
    409 
    410         /**
    411          * Indicates that the call has CDMA Enhanced Voice Privacy enabled.
    412          */
    413         public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 0x00000080;
    414 
    415         /**
    416          * Indicates that the call is from a self-managed {@link ConnectionService}.
    417          * <p>
    418          * See also {@link Connection#PROPERTY_SELF_MANAGED}
    419          */
    420         public static final int PROPERTY_SELF_MANAGED = 0x00000100;
    421 
    422         /**
    423          * Indicates the call used Assisted Dialing.
    424          * See also {@link Connection#PROPERTY_ASSISTED_DIALING_USED}
    425          * @hide
    426          */
    427         public static final int PROPERTY_ASSISTED_DIALING_USED = 0x00000200;
    428 
    429         /**
    430          * Indicates that the call is an RTT call. Use {@link #getRttCall()} to get the
    431          * {@link RttCall} object that is used to send and receive text.
    432          */
    433         public static final int PROPERTY_RTT = 0x00000400;
    434 
    435         //******************************************************************************************
    436         // Next PROPERTY value: 0x00000800
    437         //******************************************************************************************
    438 
    439         private final String mTelecomCallId;
    440         private final Uri mHandle;
    441         private final int mHandlePresentation;
    442         private final String mCallerDisplayName;
    443         private final int mCallerDisplayNamePresentation;
    444         private final PhoneAccountHandle mAccountHandle;
    445         private final int mCallCapabilities;
    446         private final int mCallProperties;
    447         private final int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL;
    448         private final DisconnectCause mDisconnectCause;
    449         private final long mConnectTimeMillis;
    450         private final GatewayInfo mGatewayInfo;
    451         private final int mVideoState;
    452         private final StatusHints mStatusHints;
    453         private final Bundle mExtras;
    454         private final Bundle mIntentExtras;
    455         private final long mCreationTimeMillis;
    456 
    457         /**
    458          * Whether the supplied capabilities  supports the specified capability.
    459          *
    460          * @param capabilities A bit field of capabilities.
    461          * @param capability The capability to check capabilities for.
    462          * @return Whether the specified capability is supported.
    463          */
    464         public static boolean can(int capabilities, int capability) {
    465             return (capabilities & capability) == capability;
    466         }
    467 
    468         /**
    469          * Whether the capabilities of this {@code Details} supports the specified capability.
    470          *
    471          * @param capability The capability to check capabilities for.
    472          * @return Whether the specified capability is supported.
    473          */
    474         public boolean can(int capability) {
    475             return can(mCallCapabilities, capability);
    476         }
    477 
    478         /**
    479          * Render a set of capability bits ({@code CAPABILITY_*}) as a human readable string.
    480          *
    481          * @param capabilities A capability bit field.
    482          * @return A human readable string representation.
    483          */
    484         public static String capabilitiesToString(int capabilities) {
    485             StringBuilder builder = new StringBuilder();
    486             builder.append("[Capabilities:");
    487             if (can(capabilities, CAPABILITY_HOLD)) {
    488                 builder.append(" CAPABILITY_HOLD");
    489             }
    490             if (can(capabilities, CAPABILITY_SUPPORT_HOLD)) {
    491                 builder.append(" CAPABILITY_SUPPORT_HOLD");
    492             }
    493             if (can(capabilities, CAPABILITY_MERGE_CONFERENCE)) {
    494                 builder.append(" CAPABILITY_MERGE_CONFERENCE");
    495             }
    496             if (can(capabilities, CAPABILITY_SWAP_CONFERENCE)) {
    497                 builder.append(" CAPABILITY_SWAP_CONFERENCE");
    498             }
    499             if (can(capabilities, CAPABILITY_RESPOND_VIA_TEXT)) {
    500                 builder.append(" CAPABILITY_RESPOND_VIA_TEXT");
    501             }
    502             if (can(capabilities, CAPABILITY_MUTE)) {
    503                 builder.append(" CAPABILITY_MUTE");
    504             }
    505             if (can(capabilities, CAPABILITY_MANAGE_CONFERENCE)) {
    506                 builder.append(" CAPABILITY_MANAGE_CONFERENCE");
    507             }
    508             if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_RX)) {
    509                 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_RX");
    510             }
    511             if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_TX)) {
    512                 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_TX");
    513             }
    514             if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL)) {
    515                 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL");
    516             }
    517             if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_RX)) {
    518                 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_RX");
    519             }
    520             if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_TX)) {
    521                 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_TX");
    522             }
    523             if (can(capabilities, CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO)) {
    524                 builder.append(" CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO");
    525             }
    526             if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL)) {
    527                 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL");
    528             }
    529             if (can(capabilities, CAPABILITY_SPEED_UP_MT_AUDIO)) {
    530                 builder.append(" CAPABILITY_SPEED_UP_MT_AUDIO");
    531             }
    532             if (can(capabilities, CAPABILITY_CAN_UPGRADE_TO_VIDEO)) {
    533                 builder.append(" CAPABILITY_CAN_UPGRADE_TO_VIDEO");
    534             }
    535             if (can(capabilities, CAPABILITY_CAN_PAUSE_VIDEO)) {
    536                 builder.append(" CAPABILITY_CAN_PAUSE_VIDEO");
    537             }
    538             if (can(capabilities, CAPABILITY_CAN_PULL_CALL)) {
    539                 builder.append(" CAPABILITY_CAN_PULL_CALL");
    540             }
    541             if (can(capabilities, CAPABILITY_SUPPORT_DEFLECT)) {
    542                 builder.append(" CAPABILITY_SUPPORT_DEFLECT");
    543             }
    544             builder.append("]");
    545             return builder.toString();
    546         }
    547 
    548         /**
    549          * Whether the supplied properties includes the specified property.
    550          *
    551          * @param properties A bit field of properties.
    552          * @param property The property to check properties for.
    553          * @return Whether the specified property is supported.
    554          */
    555         public static boolean hasProperty(int properties, int property) {
    556             return (properties & property) == property;
    557         }
    558 
    559         /**
    560          * Whether the properties of this {@code Details} includes the specified property.
    561          *
    562          * @param property The property to check properties for.
    563          * @return Whether the specified property is supported.
    564          */
    565         public boolean hasProperty(int property) {
    566             return hasProperty(mCallProperties, property);
    567         }
    568 
    569         /**
    570          * Render a set of property bits ({@code PROPERTY_*}) as a human readable string.
    571          *
    572          * @param properties A property bit field.
    573          * @return A human readable string representation.
    574          */
    575         public static String propertiesToString(int properties) {
    576             StringBuilder builder = new StringBuilder();
    577             builder.append("[Properties:");
    578             if (hasProperty(properties, PROPERTY_CONFERENCE)) {
    579                 builder.append(" PROPERTY_CONFERENCE");
    580             }
    581             if (hasProperty(properties, PROPERTY_GENERIC_CONFERENCE)) {
    582                 builder.append(" PROPERTY_GENERIC_CONFERENCE");
    583             }
    584             if (hasProperty(properties, PROPERTY_WIFI)) {
    585                 builder.append(" PROPERTY_WIFI");
    586             }
    587             if (hasProperty(properties, PROPERTY_HIGH_DEF_AUDIO)) {
    588                 builder.append(" PROPERTY_HIGH_DEF_AUDIO");
    589             }
    590             if (hasProperty(properties, PROPERTY_EMERGENCY_CALLBACK_MODE)) {
    591                 builder.append(" PROPERTY_EMERGENCY_CALLBACK_MODE");
    592             }
    593             if (hasProperty(properties, PROPERTY_IS_EXTERNAL_CALL)) {
    594                 builder.append(" PROPERTY_IS_EXTERNAL_CALL");
    595             }
    596             if(hasProperty(properties, PROPERTY_HAS_CDMA_VOICE_PRIVACY)) {
    597                 builder.append(" PROPERTY_HAS_CDMA_VOICE_PRIVACY");
    598             }
    599             if(hasProperty(properties, PROPERTY_ASSISTED_DIALING_USED)) {
    600                 builder.append(" PROPERTY_ASSISTED_DIALING_USED");
    601             }
    602             builder.append("]");
    603             return builder.toString();
    604         }
    605 
    606         /** {@hide} */
    607         public String getTelecomCallId() {
    608             return mTelecomCallId;
    609         }
    610 
    611         /**
    612          * @return The handle (e.g., phone number) to which the {@code Call} is currently
    613          * connected.
    614          */
    615         public Uri getHandle() {
    616             return mHandle;
    617         }
    618 
    619         /**
    620          * @return The presentation requirements for the handle. See
    621          * {@link TelecomManager} for valid values.
    622          */
    623         public int getHandlePresentation() {
    624             return mHandlePresentation;
    625         }
    626 
    627         /**
    628          * @return The display name for the caller.
    629          */
    630         public String getCallerDisplayName() {
    631             return mCallerDisplayName;
    632         }
    633 
    634         /**
    635          * @return The presentation requirements for the caller display name. See
    636          * {@link TelecomManager} for valid values.
    637          */
    638         public int getCallerDisplayNamePresentation() {
    639             return mCallerDisplayNamePresentation;
    640         }
    641 
    642         /**
    643          * @return The {@code PhoneAccountHandle} whereby the {@code Call} is currently being
    644          * routed.
    645          */
    646         public PhoneAccountHandle getAccountHandle() {
    647             return mAccountHandle;
    648         }
    649 
    650         /**
    651          * @return A bitmask of the capabilities of the {@code Call}, as defined by the various
    652          *         {@code CAPABILITY_*} constants in this class.
    653          */
    654         public int getCallCapabilities() {
    655             return mCallCapabilities;
    656         }
    657 
    658         /**
    659          * @return A bitmask of the properties of the {@code Call}, as defined by the various
    660          *         {@code PROPERTY_*} constants in this class.
    661          */
    662         public int getCallProperties() {
    663             return mCallProperties;
    664         }
    665 
    666         /**
    667          * @return a bitmask of the audio routes available for the call.
    668          *
    669          * @hide
    670          */
    671         public int getSupportedAudioRoutes() {
    672             return mSupportedAudioRoutes;
    673         }
    674 
    675         /**
    676          * @return For a {@link #STATE_DISCONNECTED} {@code Call}, the disconnect cause expressed
    677          * by {@link android.telecom.DisconnectCause}.
    678          */
    679         public DisconnectCause getDisconnectCause() {
    680             return mDisconnectCause;
    681         }
    682 
    683         /**
    684          * Returns the time the {@link Call} connected (i.e. became active).  This information is
    685          * updated periodically, but user interfaces should not rely on this to display the "call
    686          * time clock".  For the time when the call was first added to Telecom, see
    687          * {@link #getCreationTimeMillis()}.
    688          *
    689          * @return The time the {@link Call} connected in milliseconds since the epoch.
    690          */
    691         public final long getConnectTimeMillis() {
    692             return mConnectTimeMillis;
    693         }
    694 
    695         /**
    696          * @return Information about any calling gateway the {@code Call} may be using.
    697          */
    698         public GatewayInfo getGatewayInfo() {
    699             return mGatewayInfo;
    700         }
    701 
    702         /**
    703          * @return The video state of the {@code Call}.
    704          */
    705         public int getVideoState() {
    706             return mVideoState;
    707         }
    708 
    709         /**
    710          * @return The current {@link android.telecom.StatusHints}, or {@code null} if none
    711          * have been set.
    712          */
    713         public StatusHints getStatusHints() {
    714             return mStatusHints;
    715         }
    716 
    717         /**
    718          * @return The extras associated with this call.
    719          */
    720         public Bundle getExtras() {
    721             return mExtras;
    722         }
    723 
    724         /**
    725          * @return The extras used with the original intent to place this call.
    726          */
    727         public Bundle getIntentExtras() {
    728             return mIntentExtras;
    729         }
    730 
    731         /**
    732          * Returns the time when the call was first created and added to Telecom.  This is the same
    733          * time that is logged as the start time in the Call Log (see
    734          * {@link android.provider.CallLog.Calls#DATE}).  To determine when the call was connected
    735          * (became active), see {@link #getConnectTimeMillis()}.
    736          *
    737          * @return The creation time of the call, in millis since the epoch.
    738          */
    739         public long getCreationTimeMillis() {
    740             return mCreationTimeMillis;
    741         }
    742 
    743         @Override
    744         public boolean equals(Object o) {
    745             if (o instanceof Details) {
    746                 Details d = (Details) o;
    747                 return
    748                         Objects.equals(mHandle, d.mHandle) &&
    749                         Objects.equals(mHandlePresentation, d.mHandlePresentation) &&
    750                         Objects.equals(mCallerDisplayName, d.mCallerDisplayName) &&
    751                         Objects.equals(mCallerDisplayNamePresentation,
    752                                 d.mCallerDisplayNamePresentation) &&
    753                         Objects.equals(mAccountHandle, d.mAccountHandle) &&
    754                         Objects.equals(mCallCapabilities, d.mCallCapabilities) &&
    755                         Objects.equals(mCallProperties, d.mCallProperties) &&
    756                         Objects.equals(mDisconnectCause, d.mDisconnectCause) &&
    757                         Objects.equals(mConnectTimeMillis, d.mConnectTimeMillis) &&
    758                         Objects.equals(mGatewayInfo, d.mGatewayInfo) &&
    759                         Objects.equals(mVideoState, d.mVideoState) &&
    760                         Objects.equals(mStatusHints, d.mStatusHints) &&
    761                         areBundlesEqual(mExtras, d.mExtras) &&
    762                         areBundlesEqual(mIntentExtras, d.mIntentExtras) &&
    763                         Objects.equals(mCreationTimeMillis, d.mCreationTimeMillis);
    764             }
    765             return false;
    766         }
    767 
    768         @Override
    769         public int hashCode() {
    770             return Objects.hash(mHandle,
    771                             mHandlePresentation,
    772                             mCallerDisplayName,
    773                             mCallerDisplayNamePresentation,
    774                             mAccountHandle,
    775                             mCallCapabilities,
    776                             mCallProperties,
    777                             mDisconnectCause,
    778                             mConnectTimeMillis,
    779                             mGatewayInfo,
    780                             mVideoState,
    781                             mStatusHints,
    782                             mExtras,
    783                             mIntentExtras,
    784                             mCreationTimeMillis);
    785         }
    786 
    787         /** {@hide} */
    788         public Details(
    789                 String telecomCallId,
    790                 Uri handle,
    791                 int handlePresentation,
    792                 String callerDisplayName,
    793                 int callerDisplayNamePresentation,
    794                 PhoneAccountHandle accountHandle,
    795                 int capabilities,
    796                 int properties,
    797                 DisconnectCause disconnectCause,
    798                 long connectTimeMillis,
    799                 GatewayInfo gatewayInfo,
    800                 int videoState,
    801                 StatusHints statusHints,
    802                 Bundle extras,
    803                 Bundle intentExtras,
    804                 long creationTimeMillis) {
    805             mTelecomCallId = telecomCallId;
    806             mHandle = handle;
    807             mHandlePresentation = handlePresentation;
    808             mCallerDisplayName = callerDisplayName;
    809             mCallerDisplayNamePresentation = callerDisplayNamePresentation;
    810             mAccountHandle = accountHandle;
    811             mCallCapabilities = capabilities;
    812             mCallProperties = properties;
    813             mDisconnectCause = disconnectCause;
    814             mConnectTimeMillis = connectTimeMillis;
    815             mGatewayInfo = gatewayInfo;
    816             mVideoState = videoState;
    817             mStatusHints = statusHints;
    818             mExtras = extras;
    819             mIntentExtras = intentExtras;
    820             mCreationTimeMillis = creationTimeMillis;
    821         }
    822 
    823         /** {@hide} */
    824         public static Details createFromParcelableCall(ParcelableCall parcelableCall) {
    825             return new Details(
    826                     parcelableCall.getId(),
    827                     parcelableCall.getHandle(),
    828                     parcelableCall.getHandlePresentation(),
    829                     parcelableCall.getCallerDisplayName(),
    830                     parcelableCall.getCallerDisplayNamePresentation(),
    831                     parcelableCall.getAccountHandle(),
    832                     parcelableCall.getCapabilities(),
    833                     parcelableCall.getProperties(),
    834                     parcelableCall.getDisconnectCause(),
    835                     parcelableCall.getConnectTimeMillis(),
    836                     parcelableCall.getGatewayInfo(),
    837                     parcelableCall.getVideoState(),
    838                     parcelableCall.getStatusHints(),
    839                     parcelableCall.getExtras(),
    840                     parcelableCall.getIntentExtras(),
    841                     parcelableCall.getCreationTimeMillis());
    842         }
    843 
    844         @Override
    845         public String toString() {
    846             StringBuilder sb = new StringBuilder();
    847             sb.append("[pa: ");
    848             sb.append(mAccountHandle);
    849             sb.append(", hdl: ");
    850             sb.append(Log.pii(mHandle));
    851             sb.append(", caps: ");
    852             sb.append(capabilitiesToString(mCallCapabilities));
    853             sb.append(", props: ");
    854             sb.append(propertiesToString(mCallProperties));
    855             sb.append("]");
    856             return sb.toString();
    857         }
    858     }
    859 
    860     /**
    861      * Defines callbacks which inform the {@link InCallService} of changes to a {@link Call}.
    862      * These callbacks can originate from the Telecom framework, or a {@link ConnectionService}
    863      * implementation.
    864      * <p>
    865      * You can handle these callbacks by extending the {@link Callback} class and overriding the
    866      * callbacks that your {@link InCallService} is interested in.  The callback methods include the
    867      * {@link Call} for which the callback applies, allowing reuse of a single instance of your
    868      * {@link Callback} implementation, if desired.
    869      * <p>
    870      * Use {@link Call#registerCallback(Callback)} to register your callback(s).  Ensure
    871      * {@link Call#unregisterCallback(Callback)} is called when you no longer require callbacks
    872      * (typically in {@link InCallService#onCallRemoved(Call)}).
    873      * Note: Callbacks which occur before you call {@link Call#registerCallback(Callback)} will not
    874      * reach your implementation of {@link Callback}, so it is important to register your callback
    875      * as soon as your {@link InCallService} is notified of a new call via
    876      * {@link InCallService#onCallAdded(Call)}.
    877      */
    878     public static abstract class Callback {
    879         /**
    880          * @hide
    881          */
    882         @IntDef(prefix = { "HANDOVER_" },
    883                 value = {HANDOVER_FAILURE_DEST_APP_REJECTED, HANDOVER_FAILURE_NOT_SUPPORTED,
    884                 HANDOVER_FAILURE_USER_REJECTED, HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL,
    885                 HANDOVER_FAILURE_UNKNOWN})
    886         @Retention(RetentionPolicy.SOURCE)
    887         public @interface HandoverFailureErrors {}
    888 
    889         /**
    890          * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the app
    891          * to handover the call to rejects the handover request.
    892          * <p>
    893          * Will be returned when {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} is called
    894          * and the destination {@link PhoneAccountHandle}'s {@link ConnectionService} returns a
    895          * {@code null} {@link Connection} from
    896          * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
    897          * ConnectionRequest)}.
    898          * <p>
    899          * For more information on call handovers, see
    900          * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
    901          */
    902         public static final int HANDOVER_FAILURE_DEST_APP_REJECTED = 1;
    903 
    904         /**
    905          * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
    906          * is initiated but the source or destination app does not support handover.
    907          * <p>
    908          * Will be returned when a handover is requested via
    909          * {@link #handoverTo(PhoneAccountHandle, int, Bundle)} and the destination
    910          * {@link PhoneAccountHandle} does not declare
    911          * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}.  May also be returned when a handover is
    912          * requested at the {@link PhoneAccountHandle} for the current call (i.e. the source call's
    913          * {@link Details#getAccountHandle()}) does not declare
    914          * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}.
    915          * <p>
    916          * For more information on call handovers, see
    917          * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
    918          */
    919         public static final int HANDOVER_FAILURE_NOT_SUPPORTED = 2;
    920 
    921         /**
    922          * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the remote
    923          * user rejects the handover request.
    924          * <p>
    925          * For more information on call handovers, see
    926          * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
    927          */
    928         public static final int HANDOVER_FAILURE_USER_REJECTED = 3;
    929 
    930         /**
    931          * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there
    932          * is ongoing emergency call.
    933          * <p>
    934          * This error code is returned when {@link #handoverTo(PhoneAccountHandle, int, Bundle)} is
    935          * called on an emergency call, or if any other call is an emergency call.
    936          * <p>
    937          * Handovers are not permitted while there are ongoing emergency calls.
    938          * <p>
    939          * For more information on call handovers, see
    940          * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
    941          */
    942         public static final int HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL = 4;
    943 
    944         /**
    945          * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
    946          * fails for an unknown reason.
    947          * <p>
    948          * For more information on call handovers, see
    949          * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
    950          */
    951         public static final int HANDOVER_FAILURE_UNKNOWN = 5;
    952 
    953         /**
    954          * Invoked when the state of this {@code Call} has changed. See {@link #getState()}.
    955          *
    956          * @param call The {@code Call} invoking this method.
    957          * @param state The new state of the {@code Call}.
    958          */
    959         public void onStateChanged(Call call, int state) {}
    960 
    961         /**
    962          * Invoked when the parent of this {@code Call} has changed. See {@link #getParent()}.
    963          *
    964          * @param call The {@code Call} invoking this method.
    965          * @param parent The new parent of the {@code Call}.
    966          */
    967         public void onParentChanged(Call call, Call parent) {}
    968 
    969         /**
    970          * Invoked when the children of this {@code Call} have changed. See {@link #getChildren()}.
    971          *
    972          * @param call The {@code Call} invoking this method.
    973          * @param children The new children of the {@code Call}.
    974          */
    975         public void onChildrenChanged(Call call, List<Call> children) {}
    976 
    977         /**
    978          * Invoked when the details of this {@code Call} have changed. See {@link #getDetails()}.
    979          *
    980          * @param call The {@code Call} invoking this method.
    981          * @param details A {@code Details} object describing the {@code Call}.
    982          */
    983         public void onDetailsChanged(Call call, Details details) {}
    984 
    985         /**
    986          * Invoked when the text messages that can be used as responses to the incoming
    987          * {@code Call} are loaded from the relevant database.
    988          * See {@link #getCannedTextResponses()}.
    989          *
    990          * @param call The {@code Call} invoking this method.
    991          * @param cannedTextResponses The text messages useable as responses.
    992          */
    993         public void onCannedTextResponsesLoaded(Call call, List<String> cannedTextResponses) {}
    994 
    995         /**
    996          * Invoked when the post-dial sequence in the outgoing {@code Call} has reached a pause
    997          * character. This causes the post-dial signals to stop pending user confirmation. An
    998          * implementation should present this choice to the user and invoke
    999          * {@link #postDialContinue(boolean)} when the user makes the choice.
   1000          *
   1001          * @param call The {@code Call} invoking this method.
   1002          * @param remainingPostDialSequence The post-dial characters that remain to be sent.
   1003          */
   1004         public void onPostDialWait(Call call, String remainingPostDialSequence) {}
   1005 
   1006         /**
   1007          * Invoked when the {@code Call.VideoCall} of the {@code Call} has changed.
   1008          *
   1009          * @param call The {@code Call} invoking this method.
   1010          * @param videoCall The {@code Call.VideoCall} associated with the {@code Call}.
   1011          */
   1012         public void onVideoCallChanged(Call call, InCallService.VideoCall videoCall) {}
   1013 
   1014         /**
   1015          * Invoked when the {@code Call} is destroyed. Clients should refrain from cleaning
   1016          * up their UI for the {@code Call} in response to state transitions. Specifically,
   1017          * clients should not assume that a {@link #onStateChanged(Call, int)} with a state of
   1018          * {@link #STATE_DISCONNECTED} is the final notification the {@code Call} will send. Rather,
   1019          * clients should wait for this method to be invoked.
   1020          *
   1021          * @param call The {@code Call} being destroyed.
   1022          */
   1023         public void onCallDestroyed(Call call) {}
   1024 
   1025         /**
   1026          * Invoked upon changes to the set of {@code Call}s with which this {@code Call} can be
   1027          * conferenced.
   1028          *
   1029          * @param call The {@code Call} being updated.
   1030          * @param conferenceableCalls The {@code Call}s with which this {@code Call} can be
   1031          *          conferenced.
   1032          */
   1033         public void onConferenceableCallsChanged(Call call, List<Call> conferenceableCalls) {}
   1034 
   1035         /**
   1036          * Invoked when a {@link Call} receives an event from its associated {@link Connection}.
   1037          * <p>
   1038          * Where possible, the Call should make an attempt to handle {@link Connection} events which
   1039          * are part of the {@code android.telecom.*} namespace.  The Call should ignore any events
   1040          * it does not wish to handle.  Unexpected events should be handled gracefully, as it is
   1041          * possible that a {@link ConnectionService} has defined its own Connection events which a
   1042          * Call is not aware of.
   1043          * <p>
   1044          * See {@link Connection#sendConnectionEvent(String, Bundle)}.
   1045          *
   1046          * @param call The {@code Call} receiving the event.
   1047          * @param event The event.
   1048          * @param extras Extras associated with the connection event.
   1049          */
   1050         public void onConnectionEvent(Call call, String event, Bundle extras) {}
   1051 
   1052         /**
   1053          * Invoked when the RTT mode changes for this call.
   1054          * @param call The call whose RTT mode has changed.
   1055          * @param mode the new RTT mode, one of
   1056          * {@link RttCall#RTT_MODE_FULL}, {@link RttCall#RTT_MODE_HCO},
   1057          *             or {@link RttCall#RTT_MODE_VCO}
   1058          */
   1059         public void onRttModeChanged(Call call, int mode) {}
   1060 
   1061         /**
   1062          * Invoked when the call's RTT status changes, either from off to on or from on to off.
   1063          * @param call The call whose RTT status has changed.
   1064          * @param enabled whether RTT is now enabled or disabled
   1065          * @param rttCall the {@link RttCall} object to use for reading and writing if RTT is now
   1066          *                on, null otherwise.
   1067          */
   1068         public void onRttStatusChanged(Call call, boolean enabled, RttCall rttCall) {}
   1069 
   1070         /**
   1071          * Invoked when the remote end of the connection has requested that an RTT communication
   1072          * channel be opened. A response to this should be sent via {@link #respondToRttRequest}
   1073          * with the same ID that this method is invoked with.
   1074          * @param call The call which the RTT request was placed on
   1075          * @param id The ID of the request.
   1076          */
   1077         public void onRttRequest(Call call, int id) {}
   1078 
   1079         /**
   1080          * Invoked when the RTT session failed to initiate for some reason, including rejection
   1081          * by the remote party.
   1082          * @param call The call which the RTT initiation failure occurred on.
   1083          * @param reason One of the status codes defined in
   1084          *               {@link android.telecom.Connection.RttModifyStatus}, with the exception of
   1085          *               {@link android.telecom.Connection.RttModifyStatus#SESSION_MODIFY_REQUEST_SUCCESS}.
   1086          */
   1087         public void onRttInitiationFailure(Call call, int reason) {}
   1088 
   1089         /**
   1090          * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
   1091          * has completed successfully.
   1092          * <p>
   1093          * For a full discussion of the handover process and the APIs involved, see
   1094          * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
   1095          *
   1096          * @param call The call which had initiated handover.
   1097          */
   1098         public void onHandoverComplete(Call call) {}
   1099 
   1100         /**
   1101          * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
   1102          * has failed.
   1103          * <p>
   1104          * For a full discussion of the handover process and the APIs involved, see
   1105          * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
   1106          *
   1107          * @param call The call which had initiated handover.
   1108          * @param failureReason Error reason for failure.
   1109          */
   1110         public void onHandoverFailed(Call call, @HandoverFailureErrors int failureReason) {}
   1111     }
   1112 
   1113     /**
   1114      * A class that holds the state that describes the state of the RTT channel to the remote
   1115      * party, if it is active.
   1116      */
   1117     public static final class RttCall {
   1118         /** @hide */
   1119         @Retention(RetentionPolicy.SOURCE)
   1120         @IntDef({RTT_MODE_INVALID, RTT_MODE_FULL, RTT_MODE_HCO, RTT_MODE_VCO})
   1121         public @interface RttAudioMode {}
   1122 
   1123         /**
   1124          * For metrics use. Default value in the proto.
   1125          * @hide
   1126          */
   1127         public static final int RTT_MODE_INVALID = 0;
   1128 
   1129         /**
   1130          * Indicates that there should be a bidirectional audio stream between the two parties
   1131          * on the call.
   1132          */
   1133         public static final int RTT_MODE_FULL = 1;
   1134 
   1135         /**
   1136          * Indicates that the local user should be able to hear the audio stream from the remote
   1137          * user, but not vice versa. Equivalent to muting the microphone.
   1138          */
   1139         public static final int RTT_MODE_HCO = 2;
   1140 
   1141         /**
   1142          * Indicates that the remote user should be able to hear the audio stream from the local
   1143          * user, but not vice versa. Equivalent to setting the volume to zero.
   1144          */
   1145         public static final int RTT_MODE_VCO = 3;
   1146 
   1147         private static final int READ_BUFFER_SIZE = 1000;
   1148 
   1149         private InputStreamReader mReceiveStream;
   1150         private OutputStreamWriter mTransmitStream;
   1151         private int mRttMode;
   1152         private final InCallAdapter mInCallAdapter;
   1153         private final String mTelecomCallId;
   1154         private char[] mReadBuffer = new char[READ_BUFFER_SIZE];
   1155 
   1156         /**
   1157          * @hide
   1158          */
   1159         public RttCall(String telecomCallId, InputStreamReader receiveStream,
   1160                 OutputStreamWriter transmitStream, int mode, InCallAdapter inCallAdapter) {
   1161             mTelecomCallId = telecomCallId;
   1162             mReceiveStream = receiveStream;
   1163             mTransmitStream = transmitStream;
   1164             mRttMode = mode;
   1165             mInCallAdapter = inCallAdapter;
   1166         }
   1167 
   1168         /**
   1169          * Returns the current RTT audio mode.
   1170          * @return Current RTT audio mode. One of {@link #RTT_MODE_FULL}, {@link #RTT_MODE_VCO}, or
   1171          * {@link #RTT_MODE_HCO}.
   1172          */
   1173         public int getRttAudioMode() {
   1174             return mRttMode;
   1175         }
   1176 
   1177         /**
   1178          * Sets the RTT audio mode. The requested mode change will be communicated through
   1179          * {@link Callback#onRttModeChanged(Call, int)}.
   1180          * @param mode The desired RTT audio mode, one of {@link #RTT_MODE_FULL},
   1181          * {@link #RTT_MODE_VCO}, or {@link #RTT_MODE_HCO}.
   1182          */
   1183         public void setRttMode(@RttAudioMode int mode) {
   1184             mInCallAdapter.setRttMode(mTelecomCallId, mode);
   1185         }
   1186 
   1187         /**
   1188          * Writes the string {@param input} into the outgoing text stream for this RTT call. Since
   1189          * RTT transmits text in real-time, this method should be called once for each character
   1190          * the user enters into the device.
   1191          *
   1192          * This method is not thread-safe -- calling it from multiple threads simultaneously may
   1193          * lead to interleaved text.
   1194          * @param input The message to send to the remote user.
   1195          */
   1196         public void write(String input) throws IOException {
   1197             mTransmitStream.write(input);
   1198             mTransmitStream.flush();
   1199         }
   1200 
   1201         /**
   1202          * Reads a string from the remote user, blocking if there is no data available. Returns
   1203          * {@code null} if the RTT conversation has been terminated and there is no further data
   1204          * to read.
   1205          *
   1206          * This method is not thread-safe -- calling it from multiple threads simultaneously may
   1207          * lead to interleaved text.
   1208          * @return A string containing text sent by the remote user, or {@code null} if the
   1209          * conversation has been terminated or if there was an error while reading.
   1210          */
   1211         public String read() {
   1212             try {
   1213                 int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE);
   1214                 if (numRead < 0) {
   1215                     return null;
   1216                 }
   1217                 return new String(mReadBuffer, 0, numRead);
   1218             } catch (IOException e) {
   1219                 Log.w(this, "Exception encountered when reading from InputStreamReader: %s", e);
   1220                 return null;
   1221             }
   1222         }
   1223 
   1224         /**
   1225          * Non-blocking version of {@link #read()}. Returns {@code null} if there is nothing to
   1226          * be read.
   1227          * @return A string containing text entered by the user, or {@code null} if the user has
   1228          * not entered any new text yet.
   1229          */
   1230         public String readImmediately() throws IOException {
   1231             if (mReceiveStream.ready()) {
   1232                 int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE);
   1233                 if (numRead < 0) {
   1234                     return null;
   1235                 }
   1236                 return new String(mReadBuffer, 0, numRead);
   1237             } else {
   1238                 return null;
   1239             }
   1240         }
   1241 
   1242         /**
   1243          * Closes the underlying file descriptors
   1244          * @hide
   1245          */
   1246         public void close() {
   1247             try {
   1248                 mReceiveStream.close();
   1249             } catch (IOException e) {
   1250                 // ignore
   1251             }
   1252             try {
   1253                 mTransmitStream.close();
   1254             } catch (IOException e) {
   1255                 // ignore
   1256             }
   1257         }
   1258     }
   1259 
   1260     /**
   1261      * @deprecated Use {@code Call.Callback} instead.
   1262      * @hide
   1263      */
   1264     @Deprecated
   1265     @SystemApi
   1266     public static abstract class Listener extends Callback { }
   1267 
   1268     private final Phone mPhone;
   1269     private final String mTelecomCallId;
   1270     private final InCallAdapter mInCallAdapter;
   1271     private final List<String> mChildrenIds = new ArrayList<>();
   1272     private final List<Call> mChildren = new ArrayList<>();
   1273     private final List<Call> mUnmodifiableChildren = Collections.unmodifiableList(mChildren);
   1274     private final List<CallbackRecord<Callback>> mCallbackRecords = new CopyOnWriteArrayList<>();
   1275     private final List<Call> mConferenceableCalls = new ArrayList<>();
   1276     private final List<Call> mUnmodifiableConferenceableCalls =
   1277             Collections.unmodifiableList(mConferenceableCalls);
   1278 
   1279     private boolean mChildrenCached;
   1280     private String mParentId = null;
   1281     private int mState;
   1282     private List<String> mCannedTextResponses = null;
   1283     private String mCallingPackage;
   1284     private int mTargetSdkVersion;
   1285     private String mRemainingPostDialSequence;
   1286     private VideoCallImpl mVideoCallImpl;
   1287     private RttCall mRttCall;
   1288     private Details mDetails;
   1289     private Bundle mExtras;
   1290 
   1291     /**
   1292      * Obtains the post-dial sequence remaining to be emitted by this {@code Call}, if any.
   1293      *
   1294      * @return The remaining post-dial sequence, or {@code null} if there is no post-dial sequence
   1295      * remaining or this {@code Call} is not in a post-dial state.
   1296      */
   1297     public String getRemainingPostDialSequence() {
   1298         return mRemainingPostDialSequence;
   1299     }
   1300 
   1301     /**
   1302      * Instructs this {@link #STATE_RINGING} {@code Call} to answer.
   1303      * @param videoState The video state in which to answer the call.
   1304      */
   1305     public void answer(@VideoProfile.VideoState int videoState) {
   1306         mInCallAdapter.answerCall(mTelecomCallId, videoState);
   1307     }
   1308 
   1309     /**
   1310      * Instructs this {@link #STATE_RINGING} {@code Call} to deflect.
   1311      *
   1312      * @param address The address to which the call will be deflected.
   1313      */
   1314     public void deflect(Uri address) {
   1315         mInCallAdapter.deflectCall(mTelecomCallId, address);
   1316     }
   1317 
   1318     /**
   1319      * Instructs this {@link #STATE_RINGING} {@code Call} to reject.
   1320      *
   1321      * @param rejectWithMessage Whether to reject with a text message.
   1322      * @param textMessage An optional text message with which to respond.
   1323      */
   1324     public void reject(boolean rejectWithMessage, String textMessage) {
   1325         mInCallAdapter.rejectCall(mTelecomCallId, rejectWithMessage, textMessage);
   1326     }
   1327 
   1328     /**
   1329      * Instructs this {@code Call} to disconnect.
   1330      */
   1331     public void disconnect() {
   1332         mInCallAdapter.disconnectCall(mTelecomCallId);
   1333     }
   1334 
   1335     /**
   1336      * Instructs this {@code Call} to go on hold.
   1337      */
   1338     public void hold() {
   1339         mInCallAdapter.holdCall(mTelecomCallId);
   1340     }
   1341 
   1342     /**
   1343      * Instructs this {@link #STATE_HOLDING} call to release from hold.
   1344      */
   1345     public void unhold() {
   1346         mInCallAdapter.unholdCall(mTelecomCallId);
   1347     }
   1348 
   1349     /**
   1350      * Instructs this {@code Call} to play a dual-tone multi-frequency signaling (DTMF) tone.
   1351      *
   1352      * Any other currently playing DTMF tone in the specified call is immediately stopped.
   1353      *
   1354      * @param digit A character representing the DTMF digit for which to play the tone. This
   1355      *         value must be one of {@code '0'} through {@code '9'}, {@code '*'} or {@code '#'}.
   1356      */
   1357     public void playDtmfTone(char digit) {
   1358         mInCallAdapter.playDtmfTone(mTelecomCallId, digit);
   1359     }
   1360 
   1361     /**
   1362      * Instructs this {@code Call} to stop any dual-tone multi-frequency signaling (DTMF) tone
   1363      * currently playing.
   1364      *
   1365      * DTMF tones are played by calling {@link #playDtmfTone(char)}. If no DTMF tone is
   1366      * currently playing, this method will do nothing.
   1367      */
   1368     public void stopDtmfTone() {
   1369         mInCallAdapter.stopDtmfTone(mTelecomCallId);
   1370     }
   1371 
   1372     /**
   1373      * Instructs this {@code Call} to continue playing a post-dial DTMF string.
   1374      *
   1375      * A post-dial DTMF string is a string of digits entered after a phone number, when dialed,
   1376      * that are immediately sent as DTMF tones to the recipient as soon as the connection is made.
   1377      *
   1378      * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_PAUSE} symbol, this
   1379      * {@code Call} will temporarily pause playing the tones for a pre-defined period of time.
   1380      *
   1381      * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_WAIT} symbol, this
   1382      * {@code Call} will pause playing the tones and notify callbacks via
   1383      * {@link Callback#onPostDialWait(Call, String)}. At this point, the in-call app
   1384      * should display to the user an indication of this state and an affordance to continue
   1385      * the postdial sequence. When the user decides to continue the postdial sequence, the in-call
   1386      * app should invoke the {@link #postDialContinue(boolean)} method.
   1387      *
   1388      * @param proceed Whether or not to continue with the post-dial sequence.
   1389      */
   1390     public void postDialContinue(boolean proceed) {
   1391         mInCallAdapter.postDialContinue(mTelecomCallId, proceed);
   1392     }
   1393 
   1394     /**
   1395      * Notifies this {@code Call} that an account has been selected and to proceed with placing
   1396      * an outgoing call. Optionally sets this account as the default account.
   1397      */
   1398     public void phoneAccountSelected(PhoneAccountHandle accountHandle, boolean setDefault) {
   1399         mInCallAdapter.phoneAccountSelected(mTelecomCallId, accountHandle, setDefault);
   1400 
   1401     }
   1402 
   1403     /**
   1404      * Instructs this {@code Call} to enter a conference.
   1405      *
   1406      * @param callToConferenceWith The other call with which to conference.
   1407      */
   1408     public void conference(Call callToConferenceWith) {
   1409         if (callToConferenceWith != null) {
   1410             mInCallAdapter.conference(mTelecomCallId, callToConferenceWith.mTelecomCallId);
   1411         }
   1412     }
   1413 
   1414     /**
   1415      * Instructs this {@code Call} to split from any conference call with which it may be
   1416      * connected.
   1417      */
   1418     public void splitFromConference() {
   1419         mInCallAdapter.splitFromConference(mTelecomCallId);
   1420     }
   1421 
   1422     /**
   1423      * Merges the calls within this conference. See {@link Details#CAPABILITY_MERGE_CONFERENCE}.
   1424      */
   1425     public void mergeConference() {
   1426         mInCallAdapter.mergeConference(mTelecomCallId);
   1427     }
   1428 
   1429     /**
   1430      * Swaps the calls within this conference. See {@link Details#CAPABILITY_SWAP_CONFERENCE}.
   1431      */
   1432     public void swapConference() {
   1433         mInCallAdapter.swapConference(mTelecomCallId);
   1434     }
   1435 
   1436     /**
   1437      * Initiates a request to the {@link ConnectionService} to pull an external call to the local
   1438      * device.
   1439      * <p>
   1440      * Calls to this method are ignored if the call does not have the
   1441      * {@link Call.Details#PROPERTY_IS_EXTERNAL_CALL} property set.
   1442      * <p>
   1443      * An {@link InCallService} will only see calls which support this method if it has the
   1444      * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
   1445      * in its manifest.
   1446      */
   1447     public void pullExternalCall() {
   1448         // If this isn't an external call, ignore the request.
   1449         if (!mDetails.hasProperty(Details.PROPERTY_IS_EXTERNAL_CALL)) {
   1450             return;
   1451         }
   1452 
   1453         mInCallAdapter.pullExternalCall(mTelecomCallId);
   1454     }
   1455 
   1456     /**
   1457      * Sends a {@code Call} event from this {@code Call} to the associated {@link Connection} in
   1458      * the {@link ConnectionService}.
   1459      * <p>
   1460      * Call events are used to communicate point in time information from an {@link InCallService}
   1461      * to a {@link ConnectionService}.  A {@link ConnectionService} implementation could define
   1462      * events which enable the {@link InCallService}, for example, toggle a unique feature of the
   1463      * {@link ConnectionService}.
   1464      * <p>
   1465      * A {@link ConnectionService} can communicate to the {@link InCallService} using
   1466      * {@link Connection#sendConnectionEvent(String, Bundle)}.
   1467      * <p>
   1468      * Events are exposed to {@link ConnectionService} implementations via
   1469      * {@link android.telecom.Connection#onCallEvent(String, Bundle)}.
   1470      * <p>
   1471      * No assumptions should be made as to how a {@link ConnectionService} will handle these events.
   1472      * The {@link InCallService} must assume that the {@link ConnectionService} could chose to
   1473      * ignore some events altogether.
   1474      * <p>
   1475      * Events should be fully qualified (e.g., {@code com.example.event.MY_EVENT}) to avoid
   1476      * conflicts between {@link InCallService} implementations.  Further, {@link InCallService}
   1477      * implementations shall not re-purpose events in the {@code android.*} namespace, nor shall
   1478      * they define their own event types in this namespace.  When defining a custom event type,
   1479      * ensure the contents of the extras {@link Bundle} is clearly defined.  Extra keys for this
   1480      * bundle should be named similar to the event type (e.g. {@code com.example.extra.MY_EXTRA}).
   1481      * <p>
   1482      * When defining events and the associated extras, it is important to keep their behavior
   1483      * consistent when the associated {@link InCallService} is updated.  Support for deprecated
   1484      * events/extras should me maintained to ensure backwards compatibility with older
   1485      * {@link ConnectionService} implementations which were built to support the older behavior.
   1486      *
   1487      * @param event The connection event.
   1488      * @param extras Bundle containing extra information associated with the event.
   1489      */
   1490     public void sendCallEvent(String event, Bundle extras) {
   1491         mInCallAdapter.sendCallEvent(mTelecomCallId, event, mTargetSdkVersion, extras);
   1492     }
   1493 
   1494     /**
   1495      * Sends an RTT upgrade request to the remote end of the connection. Success is not
   1496      * guaranteed, and notification of success will be via the
   1497      * {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
   1498      */
   1499     public void sendRttRequest() {
   1500         mInCallAdapter.sendRttRequest(mTelecomCallId);
   1501     }
   1502 
   1503     /**
   1504      * Responds to an RTT request received via the {@link Callback#onRttRequest(Call, int)} )}
   1505      * callback.
   1506      * The ID used here should be the same as the ID that was received via the callback.
   1507      * @param id The request ID received via {@link Callback#onRttRequest(Call, int)}
   1508      * @param accept {@code true} if the RTT request should be accepted, {@code false} otherwise.
   1509      */
   1510     public void respondToRttRequest(int id, boolean accept) {
   1511         mInCallAdapter.respondToRttRequest(mTelecomCallId, id, accept);
   1512     }
   1513 
   1514     /**
   1515      * Initiates a handover of this {@link Call} to the {@link ConnectionService} identified
   1516      * by {@code toHandle}.  The videoState specified indicates the desired video state after the
   1517      * handover.
   1518      * <p>
   1519      * A call handover is the process where an ongoing call is transferred from one app (i.e.
   1520      * {@link ConnectionService} to another app.  The user could, for example, choose to continue a
   1521      * mobile network call in a video calling app.  The mobile network call via the Telephony stack
   1522      * is referred to as the source of the handover, and the video calling app is referred to as the
   1523      * destination.
   1524      * <p>
   1525      * When considering a handover scenario the device this method is called on is considered the
   1526      * <em>initiating</em> device (since the user initiates the handover from this device), and the
   1527      * other device is considered the <em>receiving</em> device.
   1528      * <p>
   1529      * When this method is called on the <em>initiating</em> device, the Telecom framework will bind
   1530      * to the {@link ConnectionService} defined by the {@code toHandle} {@link PhoneAccountHandle}
   1531      * and invoke
   1532      * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
   1533      * ConnectionRequest)} to inform the destination app that a request has been made to handover a
   1534      * call to it.  The app returns an instance of {@link Connection} to represent the handover call
   1535      * At this point the app should display UI to indicate to the user that a call
   1536      * handover is in process.
   1537      * <p>
   1538      * The destination app is responsible for communicating the handover request from the
   1539      * <em>initiating</em> device to the <em>receiving</em> device.
   1540      * <p>
   1541      * When the app on the <em>receiving</em> device receives the handover request, it calls
   1542      * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)} to continue the handover
   1543      * process from the <em>initiating</em> device to the <em>receiving</em> device.  At this point
   1544      * the destination app on the <em>receiving</em> device should show UI to allow the user to
   1545      * choose whether they want to continue their call in the destination app.
   1546      * <p>
   1547      * When the destination app on the <em>receiving</em> device calls
   1548      * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)}, Telecom will bind to its
   1549      * {@link ConnectionService} and call
   1550      * {@link ConnectionService#onCreateIncomingHandoverConnection(PhoneAccountHandle,
   1551      * ConnectionRequest)} to inform it of the handover request.  The app returns an instance of
   1552      * {@link Connection} to represent the handover call.
   1553      * <p>
   1554      * If the user of the <em>receiving</em> device accepts the handover, the app calls
   1555      * {@link Connection#setActive()} to complete the handover process; Telecom will disconnect the
   1556      * original call.  If the user rejects the handover, the app calls
   1557      * {@link Connection#setDisconnected(DisconnectCause)} and specifies a {@link DisconnectCause}
   1558      * of {@link DisconnectCause#CANCELED} to indicate that the handover has been cancelled.
   1559      * <p>
   1560      * Telecom will only allow handovers from {@link PhoneAccount}s which declare
   1561      * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}.  Similarly, the {@link PhoneAccount}
   1562      * specified by {@code toHandle} must declare {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}.
   1563      * <p>
   1564      * Errors in the handover process are reported to the {@link InCallService} via
   1565      * {@link Callback#onHandoverFailed(Call, int)}.  Errors in the handover process are reported to
   1566      * the involved {@link ConnectionService}s via
   1567      * {@link ConnectionService#onHandoverFailed(ConnectionRequest, int)}.
   1568      *
   1569      * @param toHandle {@link PhoneAccountHandle} of the {@link ConnectionService} to handover
   1570      *                 this call to.
   1571      * @param videoState Indicates the video state desired after the handover (see the
   1572      *               {@code STATE_*} constants defined in {@link VideoProfile}).
   1573      * @param extras Bundle containing extra information to be passed to the
   1574      *               {@link ConnectionService}
   1575      */
   1576     public void handoverTo(PhoneAccountHandle toHandle, @VideoProfile.VideoState int videoState,
   1577             Bundle extras) {
   1578         mInCallAdapter.handoverTo(mTelecomCallId, toHandle, videoState, extras);
   1579     }
   1580 
   1581     /**
   1582      * Terminate the RTT session on this call. The resulting state change will be notified via
   1583      * the {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
   1584      */
   1585     public void stopRtt() {
   1586         mInCallAdapter.stopRtt(mTelecomCallId);
   1587     }
   1588 
   1589     /**
   1590      * Adds some extras to this {@link Call}.  Existing keys are replaced and new ones are
   1591      * added.
   1592      * <p>
   1593      * No assumptions should be made as to how an In-Call UI or service will handle these
   1594      * extras.  Keys should be fully qualified (e.g., com.example.MY_EXTRA) to avoid conflicts.
   1595      *
   1596      * @param extras The extras to add.
   1597      */
   1598     public final void putExtras(Bundle extras) {
   1599         if (extras == null) {
   1600             return;
   1601         }
   1602 
   1603         if (mExtras == null) {
   1604             mExtras = new Bundle();
   1605         }
   1606         mExtras.putAll(extras);
   1607         mInCallAdapter.putExtras(mTelecomCallId, extras);
   1608     }
   1609 
   1610     /**
   1611      * Adds a boolean extra to this {@link Call}.
   1612      *
   1613      * @param key The extra key.
   1614      * @param value The value.
   1615      * @hide
   1616      */
   1617     public final void putExtra(String key, boolean value) {
   1618         if (mExtras == null) {
   1619             mExtras = new Bundle();
   1620         }
   1621         mExtras.putBoolean(key, value);
   1622         mInCallAdapter.putExtra(mTelecomCallId, key, value);
   1623     }
   1624 
   1625     /**
   1626      * Adds an integer extra to this {@link Call}.
   1627      *
   1628      * @param key The extra key.
   1629      * @param value The value.
   1630      * @hide
   1631      */
   1632     public final void putExtra(String key, int value) {
   1633         if (mExtras == null) {
   1634             mExtras = new Bundle();
   1635         }
   1636         mExtras.putInt(key, value);
   1637         mInCallAdapter.putExtra(mTelecomCallId, key, value);
   1638     }
   1639 
   1640     /**
   1641      * Adds a string extra to this {@link Call}.
   1642      *
   1643      * @param key The extra key.
   1644      * @param value The value.
   1645      * @hide
   1646      */
   1647     public final void putExtra(String key, String value) {
   1648         if (mExtras == null) {
   1649             mExtras = new Bundle();
   1650         }
   1651         mExtras.putString(key, value);
   1652         mInCallAdapter.putExtra(mTelecomCallId, key, value);
   1653     }
   1654 
   1655     /**
   1656      * Removes extras from this {@link Call}.
   1657      *
   1658      * @param keys The keys of the extras to remove.
   1659      */
   1660     public final void removeExtras(List<String> keys) {
   1661         if (mExtras != null) {
   1662             for (String key : keys) {
   1663                 mExtras.remove(key);
   1664             }
   1665             if (mExtras.size() == 0) {
   1666                 mExtras = null;
   1667             }
   1668         }
   1669         mInCallAdapter.removeExtras(mTelecomCallId, keys);
   1670     }
   1671 
   1672     /**
   1673      * Removes extras from this {@link Call}.
   1674      *
   1675      * @param keys The keys of the extras to remove.
   1676      */
   1677     public final void removeExtras(String ... keys) {
   1678         removeExtras(Arrays.asList(keys));
   1679     }
   1680 
   1681     /**
   1682      * Obtains the parent of this {@code Call} in a conference, if any.
   1683      *
   1684      * @return The parent {@code Call}, or {@code null} if this {@code Call} is not a
   1685      * child of any conference {@code Call}s.
   1686      */
   1687     public Call getParent() {
   1688         if (mParentId != null) {
   1689             return mPhone.internalGetCallByTelecomId(mParentId);
   1690         }
   1691         return null;
   1692     }
   1693 
   1694     /**
   1695      * Obtains the children of this conference {@code Call}, if any.
   1696      *
   1697      * @return The children of this {@code Call} if this {@code Call} is a conference, or an empty
   1698      * {@code List} otherwise.
   1699      */
   1700     public List<Call> getChildren() {
   1701         if (!mChildrenCached) {
   1702             mChildrenCached = true;
   1703             mChildren.clear();
   1704 
   1705             for(String id : mChildrenIds) {
   1706                 Call call = mPhone.internalGetCallByTelecomId(id);
   1707                 if (call == null) {
   1708                     // At least one child was still not found, so do not save true for "cached"
   1709                     mChildrenCached = false;
   1710                 } else {
   1711                     mChildren.add(call);
   1712                 }
   1713             }
   1714         }
   1715 
   1716         return mUnmodifiableChildren;
   1717     }
   1718 
   1719     /**
   1720      * Returns the list of {@code Call}s with which this {@code Call} is allowed to conference.
   1721      *
   1722      * @return The list of conferenceable {@code Call}s.
   1723      */
   1724     public List<Call> getConferenceableCalls() {
   1725         return mUnmodifiableConferenceableCalls;
   1726     }
   1727 
   1728     /**
   1729      * Obtains the state of this {@code Call}.
   1730      *
   1731      * @return A state value, chosen from the {@code STATE_*} constants.
   1732      */
   1733     public int getState() {
   1734         return mState;
   1735     }
   1736 
   1737     /**
   1738      * Obtains a list of canned, pre-configured message responses to present to the user as
   1739      * ways of rejecting this {@code Call} using via a text message.
   1740      *
   1741      * @see #reject(boolean, String)
   1742      *
   1743      * @return A list of canned text message responses.
   1744      */
   1745     public List<String> getCannedTextResponses() {
   1746         return mCannedTextResponses;
   1747     }
   1748 
   1749     /**
   1750      * Obtains an object that can be used to display video from this {@code Call}.
   1751      *
   1752      * @return An {@code Call.VideoCall}.
   1753      */
   1754     public InCallService.VideoCall getVideoCall() {
   1755         return mVideoCallImpl;
   1756     }
   1757 
   1758     /**
   1759      * Obtains an object containing call details.
   1760      *
   1761      * @return A {@link Details} object. Depending on the state of the {@code Call}, the
   1762      * result may be {@code null}.
   1763      */
   1764     public Details getDetails() {
   1765         return mDetails;
   1766     }
   1767 
   1768     /**
   1769      * Returns this call's RttCall object. The {@link RttCall} instance is used to send and
   1770      * receive RTT text data, as well as to change the RTT mode.
   1771      * @return A {@link Call.RttCall}. {@code null} if there is no active RTT connection.
   1772      */
   1773     public @Nullable RttCall getRttCall() {
   1774         return mRttCall;
   1775     }
   1776 
   1777     /**
   1778      * Returns whether this call has an active RTT connection.
   1779      * @return true if there is a connection, false otherwise.
   1780      */
   1781     public boolean isRttActive() {
   1782         return mRttCall != null && mDetails.hasProperty(Details.PROPERTY_RTT);
   1783     }
   1784 
   1785     /**
   1786      * Registers a callback to this {@code Call}.
   1787      *
   1788      * @param callback A {@code Callback}.
   1789      */
   1790     public void registerCallback(Callback callback) {
   1791         registerCallback(callback, new Handler());
   1792     }
   1793 
   1794     /**
   1795      * Registers a callback to this {@code Call}.
   1796      *
   1797      * @param callback A {@code Callback}.
   1798      * @param handler A handler which command and status changes will be delivered to.
   1799      */
   1800     public void registerCallback(Callback callback, Handler handler) {
   1801         unregisterCallback(callback);
   1802         // Don't allow new callback registration if the call is already being destroyed.
   1803         if (callback != null && handler != null && mState != STATE_DISCONNECTED) {
   1804             mCallbackRecords.add(new CallbackRecord<Callback>(callback, handler));
   1805         }
   1806     }
   1807 
   1808     /**
   1809      * Unregisters a callback from this {@code Call}.
   1810      *
   1811      * @param callback A {@code Callback}.
   1812      */
   1813     public void unregisterCallback(Callback callback) {
   1814         // Don't allow callback deregistration if the call is already being destroyed.
   1815         if (callback != null && mState != STATE_DISCONNECTED) {
   1816             for (CallbackRecord<Callback> record : mCallbackRecords) {
   1817                 if (record.getCallback() == callback) {
   1818                     mCallbackRecords.remove(record);
   1819                     break;
   1820                 }
   1821             }
   1822         }
   1823     }
   1824 
   1825     @Override
   1826     public String toString() {
   1827         return new StringBuilder().
   1828                 append("Call [id: ").
   1829                 append(mTelecomCallId).
   1830                 append(", state: ").
   1831                 append(stateToString(mState)).
   1832                 append(", details: ").
   1833                 append(mDetails).
   1834                 append("]").toString();
   1835     }
   1836 
   1837     /**
   1838      * @param state An integer value of a {@code STATE_*} constant.
   1839      * @return A string representation of the value.
   1840      */
   1841     private static String stateToString(int state) {
   1842         switch (state) {
   1843             case STATE_NEW:
   1844                 return "NEW";
   1845             case STATE_RINGING:
   1846                 return "RINGING";
   1847             case STATE_DIALING:
   1848                 return "DIALING";
   1849             case STATE_ACTIVE:
   1850                 return "ACTIVE";
   1851             case STATE_HOLDING:
   1852                 return "HOLDING";
   1853             case STATE_DISCONNECTED:
   1854                 return "DISCONNECTED";
   1855             case STATE_CONNECTING:
   1856                 return "CONNECTING";
   1857             case STATE_DISCONNECTING:
   1858                 return "DISCONNECTING";
   1859             case STATE_SELECT_PHONE_ACCOUNT:
   1860                 return "SELECT_PHONE_ACCOUNT";
   1861             default:
   1862                 Log.w(Call.class, "Unknown state %d", state);
   1863                 return "UNKNOWN";
   1864         }
   1865     }
   1866 
   1867     /**
   1868      * Adds a listener to this {@code Call}.
   1869      *
   1870      * @param listener A {@code Listener}.
   1871      * @deprecated Use {@link #registerCallback} instead.
   1872      * @hide
   1873      */
   1874     @Deprecated
   1875     @SystemApi
   1876     public void addListener(Listener listener) {
   1877         registerCallback(listener);
   1878     }
   1879 
   1880     /**
   1881      * Removes a listener from this {@code Call}.
   1882      *
   1883      * @param listener A {@code Listener}.
   1884      * @deprecated Use {@link #unregisterCallback} instead.
   1885      * @hide
   1886      */
   1887     @Deprecated
   1888     @SystemApi
   1889     public void removeListener(Listener listener) {
   1890         unregisterCallback(listener);
   1891     }
   1892 
   1893     /** {@hide} */
   1894     Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, String callingPackage,
   1895          int targetSdkVersion) {
   1896         mPhone = phone;
   1897         mTelecomCallId = telecomCallId;
   1898         mInCallAdapter = inCallAdapter;
   1899         mState = STATE_NEW;
   1900         mCallingPackage = callingPackage;
   1901         mTargetSdkVersion = targetSdkVersion;
   1902     }
   1903 
   1904     /** {@hide} */
   1905     Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, int state,
   1906             String callingPackage, int targetSdkVersion) {
   1907         mPhone = phone;
   1908         mTelecomCallId = telecomCallId;
   1909         mInCallAdapter = inCallAdapter;
   1910         mState = state;
   1911         mCallingPackage = callingPackage;
   1912         mTargetSdkVersion = targetSdkVersion;
   1913     }
   1914 
   1915     /** {@hide} */
   1916     final String internalGetCallId() {
   1917         return mTelecomCallId;
   1918     }
   1919 
   1920     /** {@hide} */
   1921     final void internalUpdate(ParcelableCall parcelableCall, Map<String, Call> callIdMap) {
   1922 
   1923         // First, we update the internal state as far as possible before firing any updates.
   1924         Details details = Details.createFromParcelableCall(parcelableCall);
   1925         boolean detailsChanged = !Objects.equals(mDetails, details);
   1926         if (detailsChanged) {
   1927             mDetails = details;
   1928         }
   1929 
   1930         boolean cannedTextResponsesChanged = false;
   1931         if (mCannedTextResponses == null && parcelableCall.getCannedSmsResponses() != null
   1932                 && !parcelableCall.getCannedSmsResponses().isEmpty()) {
   1933             mCannedTextResponses =
   1934                     Collections.unmodifiableList(parcelableCall.getCannedSmsResponses());
   1935             cannedTextResponsesChanged = true;
   1936         }
   1937 
   1938         VideoCallImpl newVideoCallImpl = parcelableCall.getVideoCallImpl(mCallingPackage,
   1939                 mTargetSdkVersion);
   1940         boolean videoCallChanged = parcelableCall.isVideoCallProviderChanged() &&
   1941                 !Objects.equals(mVideoCallImpl, newVideoCallImpl);
   1942         if (videoCallChanged) {
   1943             mVideoCallImpl = newVideoCallImpl;
   1944         }
   1945         if (mVideoCallImpl != null) {
   1946             mVideoCallImpl.setVideoState(getDetails().getVideoState());
   1947         }
   1948 
   1949         int state = parcelableCall.getState();
   1950         boolean stateChanged = mState != state;
   1951         if (stateChanged) {
   1952             mState = state;
   1953         }
   1954 
   1955         String parentId = parcelableCall.getParentCallId();
   1956         boolean parentChanged = !Objects.equals(mParentId, parentId);
   1957         if (parentChanged) {
   1958             mParentId = parentId;
   1959         }
   1960 
   1961         List<String> childCallIds = parcelableCall.getChildCallIds();
   1962         boolean childrenChanged = !Objects.equals(childCallIds, mChildrenIds);
   1963         if (childrenChanged) {
   1964             mChildrenIds.clear();
   1965             mChildrenIds.addAll(parcelableCall.getChildCallIds());
   1966             mChildrenCached = false;
   1967         }
   1968 
   1969         List<String> conferenceableCallIds = parcelableCall.getConferenceableCallIds();
   1970         List<Call> conferenceableCalls = new ArrayList<Call>(conferenceableCallIds.size());
   1971         for (String otherId : conferenceableCallIds) {
   1972             if (callIdMap.containsKey(otherId)) {
   1973                 conferenceableCalls.add(callIdMap.get(otherId));
   1974             }
   1975         }
   1976 
   1977         if (!Objects.equals(mConferenceableCalls, conferenceableCalls)) {
   1978             mConferenceableCalls.clear();
   1979             mConferenceableCalls.addAll(conferenceableCalls);
   1980             fireConferenceableCallsChanged();
   1981         }
   1982 
   1983         boolean isRttChanged = false;
   1984         boolean rttModeChanged = false;
   1985         if (parcelableCall.getIsRttCallChanged()
   1986                 && mDetails.hasProperty(Details.PROPERTY_RTT)) {
   1987             ParcelableRttCall parcelableRttCall = parcelableCall.getParcelableRttCall();
   1988             InputStreamReader receiveStream = new InputStreamReader(
   1989                     new ParcelFileDescriptor.AutoCloseInputStream(
   1990                             parcelableRttCall.getReceiveStream()),
   1991                     StandardCharsets.UTF_8);
   1992             OutputStreamWriter transmitStream = new OutputStreamWriter(
   1993                     new ParcelFileDescriptor.AutoCloseOutputStream(
   1994                             parcelableRttCall.getTransmitStream()),
   1995                     StandardCharsets.UTF_8);
   1996             RttCall newRttCall = new Call.RttCall(mTelecomCallId,
   1997                     receiveStream, transmitStream, parcelableRttCall.getRttMode(), mInCallAdapter);
   1998             if (mRttCall == null) {
   1999                 isRttChanged = true;
   2000             } else if (mRttCall.getRttAudioMode() != newRttCall.getRttAudioMode()) {
   2001                 rttModeChanged = true;
   2002             }
   2003             mRttCall = newRttCall;
   2004         } else if (mRttCall != null && parcelableCall.getParcelableRttCall() == null
   2005                 && parcelableCall.getIsRttCallChanged()) {
   2006             isRttChanged = true;
   2007             mRttCall = null;
   2008         }
   2009 
   2010         // Now we fire updates, ensuring that any client who listens to any of these notifications
   2011         // gets the most up-to-date state.
   2012 
   2013         if (stateChanged) {
   2014             fireStateChanged(mState);
   2015         }
   2016         if (detailsChanged) {
   2017             fireDetailsChanged(mDetails);
   2018         }
   2019         if (cannedTextResponsesChanged) {
   2020             fireCannedTextResponsesLoaded(mCannedTextResponses);
   2021         }
   2022         if (videoCallChanged) {
   2023             fireVideoCallChanged(mVideoCallImpl);
   2024         }
   2025         if (parentChanged) {
   2026             fireParentChanged(getParent());
   2027         }
   2028         if (childrenChanged) {
   2029             fireChildrenChanged(getChildren());
   2030         }
   2031         if (isRttChanged) {
   2032             fireOnIsRttChanged(mRttCall != null, mRttCall);
   2033         }
   2034         if (rttModeChanged) {
   2035             fireOnRttModeChanged(mRttCall.getRttAudioMode());
   2036         }
   2037 
   2038         // If we have transitioned to DISCONNECTED, that means we need to notify clients and
   2039         // remove ourselves from the Phone. Note that we do this after completing all state updates
   2040         // so a client can cleanly transition all their UI to the state appropriate for a
   2041         // DISCONNECTED Call while still relying on the existence of that Call in the Phone's list.
   2042         if (mState == STATE_DISCONNECTED) {
   2043             fireCallDestroyed();
   2044         }
   2045     }
   2046 
   2047     /** {@hide} */
   2048     final void internalSetPostDialWait(String remaining) {
   2049         mRemainingPostDialSequence = remaining;
   2050         firePostDialWait(mRemainingPostDialSequence);
   2051     }
   2052 
   2053     /** {@hide} */
   2054     final void internalSetDisconnected() {
   2055         if (mState != Call.STATE_DISCONNECTED) {
   2056             mState = Call.STATE_DISCONNECTED;
   2057             fireStateChanged(mState);
   2058             fireCallDestroyed();
   2059         }
   2060     }
   2061 
   2062     /** {@hide} */
   2063     final void internalOnConnectionEvent(String event, Bundle extras) {
   2064         fireOnConnectionEvent(event, extras);
   2065     }
   2066 
   2067     /** {@hide} */
   2068     final void internalOnRttUpgradeRequest(final int requestId) {
   2069         for (CallbackRecord<Callback> record : mCallbackRecords) {
   2070             final Call call = this;
   2071             final Callback callback = record.getCallback();
   2072             record.getHandler().post(() -> callback.onRttRequest(call, requestId));
   2073         }
   2074     }
   2075 
   2076     /** @hide */
   2077     final void internalOnRttInitiationFailure(int reason) {
   2078         for (CallbackRecord<Callback> record : mCallbackRecords) {
   2079             final Call call = this;
   2080             final Callback callback = record.getCallback();
   2081             record.getHandler().post(() -> callback.onRttInitiationFailure(call, reason));
   2082         }
   2083     }
   2084 
   2085     /** {@hide} */
   2086     final void internalOnHandoverFailed(int error) {
   2087         for (CallbackRecord<Callback> record : mCallbackRecords) {
   2088             final Call call = this;
   2089             final Callback callback = record.getCallback();
   2090             record.getHandler().post(() -> callback.onHandoverFailed(call, error));
   2091         }
   2092     }
   2093 
   2094     /** {@hide} */
   2095     final void internalOnHandoverComplete() {
   2096         for (CallbackRecord<Callback> record : mCallbackRecords) {
   2097             final Call call = this;
   2098             final Callback callback = record.getCallback();
   2099             record.getHandler().post(() -> callback.onHandoverComplete(call));
   2100         }
   2101     }
   2102 
   2103     private void fireStateChanged(final int newState) {
   2104         for (CallbackRecord<Callback> record : mCallbackRecords) {
   2105             final Call call = this;
   2106             final Callback callback = record.getCallback();
   2107             record.getHandler().post(new Runnable() {
   2108                 @Override
   2109                 public void run() {
   2110                     callback.onStateChanged(call, newState);
   2111                 }
   2112             });
   2113         }
   2114     }
   2115 
   2116     private void fireParentChanged(final Call newParent) {
   2117         for (CallbackRecord<Callback> record : mCallbackRecords) {
   2118             final Call call = this;
   2119             final Callback callback = record.getCallback();
   2120             record.getHandler().post(new Runnable() {
   2121                 @Override
   2122                 public void run() {
   2123                     callback.onParentChanged(call, newParent);
   2124                 }
   2125             });
   2126         }
   2127     }
   2128 
   2129     private void fireChildrenChanged(final List<Call> children) {
   2130         for (CallbackRecord<Callback> record : mCallbackRecords) {
   2131             final Call call = this;
   2132             final Callback callback = record.getCallback();
   2133             record.getHandler().post(new Runnable() {
   2134                 @Override
   2135                 public void run() {
   2136                     callback.onChildrenChanged(call, children);
   2137                 }
   2138             });
   2139         }
   2140     }
   2141 
   2142     private void fireDetailsChanged(final Details details) {
   2143         for (CallbackRecord<Callback> record : mCallbackRecords) {
   2144             final Call call = this;
   2145             final Callback callback = record.getCallback();
   2146             record.getHandler().post(new Runnable() {
   2147                 @Override
   2148                 public void run() {
   2149                     callback.onDetailsChanged(call, details);
   2150                 }
   2151             });
   2152         }
   2153     }
   2154 
   2155     private void fireCannedTextResponsesLoaded(final List<String> cannedTextResponses) {
   2156         for (CallbackRecord<Callback> record : mCallbackRecords) {
   2157             final Call call = this;
   2158             final Callback callback = record.getCallback();
   2159             record.getHandler().post(new Runnable() {
   2160                 @Override
   2161                 public void run() {
   2162                     callback.onCannedTextResponsesLoaded(call, cannedTextResponses);
   2163                 }
   2164             });
   2165         }
   2166     }
   2167 
   2168     private void fireVideoCallChanged(final InCallService.VideoCall videoCall) {
   2169         for (CallbackRecord<Callback> record : mCallbackRecords) {
   2170             final Call call = this;
   2171             final Callback callback = record.getCallback();
   2172             record.getHandler().post(new Runnable() {
   2173                 @Override
   2174                 public void run() {
   2175                     callback.onVideoCallChanged(call, videoCall);
   2176                 }
   2177             });
   2178         }
   2179     }
   2180 
   2181     private void firePostDialWait(final String remainingPostDialSequence) {
   2182         for (CallbackRecord<Callback> record : mCallbackRecords) {
   2183             final Call call = this;
   2184             final Callback callback = record.getCallback();
   2185             record.getHandler().post(new Runnable() {
   2186                 @Override
   2187                 public void run() {
   2188                     callback.onPostDialWait(call, remainingPostDialSequence);
   2189                 }
   2190             });
   2191         }
   2192     }
   2193 
   2194     private void fireCallDestroyed() {
   2195         /**
   2196          * To preserve the ordering of the Call's onCallDestroyed callback and Phone's
   2197          * onCallRemoved callback, we remove this call from the Phone's record
   2198          * only once all of the registered onCallDestroyed callbacks are executed.
   2199          * All the callbacks get removed from our records as a part of this operation
   2200          * since onCallDestroyed is the final callback.
   2201          */
   2202         final Call call = this;
   2203         if (mCallbackRecords.isEmpty()) {
   2204             // No callbacks registered, remove the call from Phone's record.
   2205             mPhone.internalRemoveCall(call);
   2206         }
   2207         for (final CallbackRecord<Callback> record : mCallbackRecords) {
   2208             final Callback callback = record.getCallback();
   2209             record.getHandler().post(new Runnable() {
   2210                 @Override
   2211                 public void run() {
   2212                     boolean isFinalRemoval = false;
   2213                     RuntimeException toThrow = null;
   2214                     try {
   2215                         callback.onCallDestroyed(call);
   2216                     } catch (RuntimeException e) {
   2217                             toThrow = e;
   2218                     }
   2219                     synchronized(Call.this) {
   2220                         mCallbackRecords.remove(record);
   2221                         if (mCallbackRecords.isEmpty()) {
   2222                             isFinalRemoval = true;
   2223                         }
   2224                     }
   2225                     if (isFinalRemoval) {
   2226                         mPhone.internalRemoveCall(call);
   2227                     }
   2228                     if (toThrow != null) {
   2229                         throw toThrow;
   2230                     }
   2231                 }
   2232             });
   2233         }
   2234     }
   2235 
   2236     private void fireConferenceableCallsChanged() {
   2237         for (CallbackRecord<Callback> record : mCallbackRecords) {
   2238             final Call call = this;
   2239             final Callback callback = record.getCallback();
   2240             record.getHandler().post(new Runnable() {
   2241                 @Override
   2242                 public void run() {
   2243                     callback.onConferenceableCallsChanged(call, mUnmodifiableConferenceableCalls);
   2244                 }
   2245             });
   2246         }
   2247     }
   2248 
   2249     /**
   2250      * Notifies listeners of an incoming connection event.
   2251      * <p>
   2252      * Connection events are issued via {@link Connection#sendConnectionEvent(String, Bundle)}.
   2253      *
   2254      * @param event
   2255      * @param extras
   2256      */
   2257     private void fireOnConnectionEvent(final String event, final Bundle extras) {
   2258         for (CallbackRecord<Callback> record : mCallbackRecords) {
   2259             final Call call = this;
   2260             final Callback callback = record.getCallback();
   2261             record.getHandler().post(new Runnable() {
   2262                 @Override
   2263                 public void run() {
   2264                     callback.onConnectionEvent(call, event, extras);
   2265                 }
   2266             });
   2267         }
   2268     }
   2269 
   2270     /**
   2271      * Notifies listeners of an RTT on/off change
   2272      *
   2273      * @param enabled True if RTT is now enabled, false otherwise
   2274      */
   2275     private void fireOnIsRttChanged(final boolean enabled, final RttCall rttCall) {
   2276         for (CallbackRecord<Callback> record : mCallbackRecords) {
   2277             final Call call = this;
   2278             final Callback callback = record.getCallback();
   2279             record.getHandler().post(() -> callback.onRttStatusChanged(call, enabled, rttCall));
   2280         }
   2281     }
   2282 
   2283     /**
   2284      * Notifies listeners of a RTT mode change
   2285      *
   2286      * @param mode The new RTT mode
   2287      */
   2288     private void fireOnRttModeChanged(final int mode) {
   2289         for (CallbackRecord<Callback> record : mCallbackRecords) {
   2290             final Call call = this;
   2291             final Callback callback = record.getCallback();
   2292             record.getHandler().post(() -> callback.onRttModeChanged(call, mode));
   2293         }
   2294     }
   2295 
   2296     /**
   2297      * Determines if two bundles are equal.
   2298      *
   2299      * @param bundle The original bundle.
   2300      * @param newBundle The bundle to compare with.
   2301      * @retrun {@code true} if the bundles are equal, {@code false} otherwise.
   2302      */
   2303     private static boolean areBundlesEqual(Bundle bundle, Bundle newBundle) {
   2304         if (bundle == null || newBundle == null) {
   2305             return bundle == newBundle;
   2306         }
   2307 
   2308         if (bundle.size() != newBundle.size()) {
   2309             return false;
   2310         }
   2311 
   2312         for(String key : bundle.keySet()) {
   2313             if (key != null) {
   2314                 final Object value = bundle.get(key);
   2315                 final Object newValue = newBundle.get(key);
   2316                 if (!Objects.equals(value, newValue)) {
   2317                     return false;
   2318                 }
   2319             }
   2320         }
   2321         return true;
   2322     }
   2323 }
   2324