Call.java revision e19cc005ddbff5313d6f7288587630b2410d005c
10407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad/* 20407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad * Copyright (C) 2014 The Android Open Source Project 30407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad * 40407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad * Licensed under the Apache License, Version 2.0 (the "License"); 50407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad * you may not use this file except in compliance with the License. 60407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad * You may obtain a copy of the License at 70407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad * 80407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad * http://www.apache.org/licenses/LICENSE-2.0 90407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad * 100407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad * Unless required by applicable law or agreed to in writing, software 110407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad * distributed under the License is distributed on an "AS IS" BASIS, 120407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad * See the License for the specific language governing permissions and 140407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad * limitations under the License. 150407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad */ 160407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad 179f2bed31374a56487f370be01224baf6ce97e8adBen Giladpackage com.android.telecomm; 189f2bed31374a56487f370be01224baf6ce97e8adBen Gilad 1999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordonimport android.content.ContentUris; 2099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordonimport android.graphics.Bitmap; 2199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordonimport android.graphics.drawable.Drawable; 22ce704b9a5d9cf7db30a8c865975c70e5cbc0dc5cSailesh Nepalimport android.net.Uri; 2384fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepalimport android.os.Bundle; 24fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordonimport android.os.Handler; 2599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordonimport android.provider.ContactsContract.Contacts; 260b03b4b143234302f098ea18de3c32658b455ecaSantos Cordonimport android.telecomm.CallInfo; 2784fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepalimport android.telecomm.CallServiceDescriptor; 280b03b4b143234302f098ea18de3c32658b455ecaSantos Cordonimport android.telecomm.CallState; 2933501635c2cd21f40793041eff3b8ce3a5710d49Yorke Leeimport android.telecomm.GatewayInfo; 30ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awadimport android.telecomm.Response; 3177d2d0e90bc2a67d526743b8e32f920a0d755fbaNancy Chenimport android.telecomm.Subscription; 32766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordonimport android.telecomm.TelecommConstants; 3379ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordonimport android.telephony.DisconnectCause; 346aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepalimport android.telephony.PhoneNumberUtils; 35fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordonimport android.text.TextUtils; 360b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon 37a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chenimport com.android.internal.telecomm.ICallVideoProvider; 38fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordonimport com.android.internal.telephony.CallerInfo; 39fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordonimport com.android.internal.telephony.CallerInfoAsyncQuery; 40fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordonimport com.android.internal.telephony.CallerInfoAsyncQuery.OnQueryCompleteListener; 41ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awadimport com.android.internal.telephony.SmsApplication; 4299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordonimport com.android.telecomm.ContactsAsyncHelper.OnImageLoadCompleteListener; 4361d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordonimport com.google.common.base.Preconditions; 44ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awadimport com.google.common.collect.Sets; 4561d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon 46ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awadimport java.util.Collections; 47a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordonimport java.util.LinkedList; 48a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordonimport java.util.List; 499199078322aea6df26f0d304a28a9a6d040f0717Sailesh Nepalimport java.util.Locale; 506192561b1f56d7c4e6c650e178e07ba61ad02667Ben Giladimport java.util.Set; 510407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad 522495d57b5b91f3a39529d8844a49d1be5f18b137Ben Gilad/** 532495d57b5b91f3a39529d8844a49d1be5f18b137Ben Gilad * Encapsulates all aspects of a given phone call throughout its lifecycle, starting 542495d57b5b91f3a39529d8844a49d1be5f18b137Ben Gilad * from the time the call intent was received by Telecomm (vs. the time the call was 552495d57b5b91f3a39529d8844a49d1be5f18b137Ben Gilad * connected etc). 562495d57b5b91f3a39529d8844a49d1be5f18b137Ben Gilad */ 575a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepalfinal class Call implements OutgoingCallResponse { 58766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon 59766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon /** 60766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon * Listener for events on the call. 61766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon */ 62766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon interface Listener { 63766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon void onSuccessfulOutgoingCall(Call call); 645a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal void onFailedOutgoingCall(Call call, int errorCode, String errorMsg); 655a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal void onCancelledOutgoingCall(Call call); 66766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon void onSuccessfulIncomingCall(Call call, CallInfo callInfo); 67766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon void onFailedIncomingCall(Call call); 68cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad void onRequestingRingback(Call call, boolean requestingRingback); 69352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton void onPostDialWait(Call call, String remaining); 70a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon void onIsConferenceCapableChanged(Call call, boolean isConferenceCapable); 71a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon void onExpiredConferenceCall(Call call); 72a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon void onConfirmedConferenceCall(Call call); 73a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon void onParentChanged(Call call); 74a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon void onChildrenChanged(Call call); 75ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad void onCannedSmsResponsesLoaded(Call call); 76a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen void onCallVideoProviderChanged(Call call); 77e19cc005ddbff5313d6f7288587630b2410d005cTyler Gunn void onFeaturesChanged(Call call); 78766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon } 79766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon 80fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon private static final OnQueryCompleteListener sCallerInfoQueryListener = 8199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon new OnQueryCompleteListener() { 8299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon /** ${inheritDoc} */ 8399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon @Override 8499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon public void onQueryComplete(int token, Object cookie, CallerInfo callerInfo) { 8599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon if (cookie != null) { 8699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon ((Call) cookie).setCallerInfo(callerInfo, token); 8799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon } 88fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon } 8999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon }; 9099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon 9199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon private static final OnImageLoadCompleteListener sPhotoLoadListener = 9299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon new OnImageLoadCompleteListener() { 9399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon /** ${inheritDoc} */ 9499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon @Override 9599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon public void onImageLoadComplete( 9699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon int token, Drawable photo, Bitmap photoIcon, Object cookie) { 9799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon if (cookie != null) { 9899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon ((Call) cookie).setPhoto(photo, photoIcon, token); 9999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon } 10099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon } 10199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon }; 1020407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad 103810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal /** True if this is an incoming call. */ 104810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal private final boolean mIsIncoming; 105810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal 1060407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad /** 1070407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad * The time this call was created, typically also the time this call was added to the set 1080407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad * of pending outgoing calls (mPendingOutgoingCalls) that's maintained by the switchboard. 1090407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad * Beyond logging and such, may also be used for bookkeeping and specifically for marking 1100407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad * certain call attempts as failed attempts. 1110407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad */ 1128c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal private final long mCreationTimeMillis = System.currentTimeMillis(); 1138c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal 114fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon /** The gateway information associated with this call. This stores the original call handle 115fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon * that the user is attempting to connect to via the gateway, the actual handle to dial in 116fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon * order to connect the call via the gateway, as well as the package name of the gateway 117fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon * service. */ 118fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon private final GatewayInfo mGatewayInfo; 119fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon 12077d2d0e90bc2a67d526743b8e32f920a0d755fbaNancy Chen private final Subscription mSubscription; 12177d2d0e90bc2a67d526743b8e32f920a0d755fbaNancy Chen 1222174fb56907fddf5680355e097f4425f837983e2Santos Cordon private final Handler mHandler = new Handler(); 1232174fb56907fddf5680355e097f4425f837983e2Santos Cordon 1248c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal private long mConnectTimeMillis; 1250407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad 12661d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon /** The state of the call. */ 12761d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon private CallState mState; 12861d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon 12961d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon /** The handle with which to establish this call. */ 130ce704b9a5d9cf7db30a8c865975c70e5cbc0dc5cSailesh Nepal private Uri mHandle; 13161d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon 1320407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad /** 1338e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad * The call service which is attempted or already connecting this call. 134681663d17b6d92b604526a54b196fa88f25b6957Santos Cordon */ 135c195e3613af47a49e76821d3f24c05adb71cf920Santos Cordon private CallServiceWrapper mCallService; 136681663d17b6d92b604526a54b196fa88f25b6957Santos Cordon 1378e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad /** 1386192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad * The set of call services that were attempted in the process of placing/switching this call 1396192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad * but turned out unsuitable. Only used in the context of call switching. 1406192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad */ 1416192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad private Set<CallServiceWrapper> mIncompatibleCallServices; 1426192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad 1436aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal private boolean mIsEmergencyCall; 1446aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal 145b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati private boolean mSpeakerphoneOn; 146b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati 1476192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad /** 14879ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon * Disconnect cause for the call. Only valid if the state of the call is DISCONNECTED. 14979ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon * See {@link android.telephony.DisconnectCause}. 15079ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon */ 1518c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal private int mDisconnectCause = DisconnectCause.NOT_VALID; 15279ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon 15379ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon /** 15479ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon * Additional disconnect information provided by the call service. 15579ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon */ 15679ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon private String mDisconnectMessage; 15779ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon 15884fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal /** Info used by the call services. */ 1598c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal private Bundle mExtras = Bundle.EMPTY; 16084fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal 16184fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal /** The Uri to dial to perform the handoff. If this is null then handoff is not supported. */ 16284fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal private Uri mHandoffHandle; 16384fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal 16484fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal /** 16584fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal * References the call that is being handed off. This value is non-null for untracked calls 16684fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal * that are being used to perform a handoff. 16784fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal */ 16884fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal private Call mOriginalCall; 16984fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal 17079ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon /** 1718c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal * The descriptor for the call service that this call is being switched to, null if handoff is 1728c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal * not in progress. 1738c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal */ 1748c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal private CallServiceDescriptor mHandoffCallServiceDescriptor; 1758c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal 176766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon /** Set of listeners on this call. */ 177766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon private Set<Listener> mListeners = Sets.newHashSet(); 178766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon 179682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon private OutgoingCallProcessor mOutgoingCallProcessor; 180682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon 181682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon // TODO(santoscordon): The repositories should be changed into singleton types. 182682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon private CallServiceRepository mCallServiceRepository; 183682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon 184fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon /** Caller information retrieved from the latest contact query. */ 185fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon private CallerInfo mCallerInfo; 186fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon 187fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon /** The latest token used with a contact info query. */ 188fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon private int mQueryToken = 0; 189fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon 190cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad /** Whether this call is requesting that Telecomm play the ringback tone on its behalf. */ 191cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad private boolean mRequestingRingback = false; 192cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad 1932174fb56907fddf5680355e097f4425f837983e2Santos Cordon /** Incoming call-info to use when direct-to-voicemail query finishes. */ 1942174fb56907fddf5680355e097f4425f837983e2Santos Cordon private CallInfo mPendingDirectToVoicemailCallInfo; 1952174fb56907fddf5680355e097f4425f837983e2Santos Cordon 196a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon private boolean mIsConferenceCapable = false; 197a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon 198a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon private boolean mIsConference = false; 199a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon 200a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon private Call mParentCall = null; 201a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon 202a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon private List<Call> mChildCalls = new LinkedList<>(); 203a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon 204ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad /** Set of text message responses allowed for this call, if applicable. */ 205ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad private List<String> mCannedSmsResponses = Collections.EMPTY_LIST; 206ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad 207ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad /** Whether an attempt has been made to load the text message responses. */ 208ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad private boolean mCannedSmsResponsesLoadingStarted = false; 209ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad 210a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen private ICallVideoProvider mCallVideoProvider; 211a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen 212e19cc005ddbff5313d6f7288587630b2410d005cTyler Gunn /** Features associated with the call which the InCall UI may wish to show icons for. */ 213e19cc005ddbff5313d6f7288587630b2410d005cTyler Gunn private int mFeatures; 214e19cc005ddbff5313d6f7288587630b2410d005cTyler Gunn 2158c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal /** 216e59bb195972d65a71618af4fe13f1ad982253e16Sailesh Nepal * Creates an empty call object. 217810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal * 218810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal * @param isIncoming True if this is an incoming call. 219493e8f2ac0c611b43265c72715b71f6ec59bba0eSantos Cordon */ 220a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon Call(boolean isIncoming, boolean isConference) { 22177d2d0e90bc2a67d526743b8e32f920a0d755fbaNancy Chen this(null, null, null, isIncoming, isConference); 222493e8f2ac0c611b43265c72715b71f6ec59bba0eSantos Cordon } 223493e8f2ac0c611b43265c72715b71f6ec59bba0eSantos Cordon 224493e8f2ac0c611b43265c72715b71f6ec59bba0eSantos Cordon /** 2250407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad * Persists the specified parameters and initializes the new instance. 2260407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad * 2270407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad * @param handle The handle to dial. 22833501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee * @param gatewayInfo Gateway information to use for the call. 22977d2d0e90bc2a67d526743b8e32f920a0d755fbaNancy Chen * @param subscription Subscription information to use for the call. 230810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal * @param isIncoming True if this is an incoming call. 2310407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad */ 23277d2d0e90bc2a67d526743b8e32f920a0d755fbaNancy Chen Call(Uri handle, GatewayInfo gatewayInfo, Subscription subscription, 23377d2d0e90bc2a67d526743b8e32f920a0d755fbaNancy Chen boolean isIncoming, boolean isConference) { 234a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon mState = isConference ? CallState.ACTIVE : CallState.NEW; 2356aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal setHandle(handle); 23633501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee mGatewayInfo = gatewayInfo; 23777d2d0e90bc2a67d526743b8e32f920a0d755fbaNancy Chen mSubscription = subscription; 238810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal mIsIncoming = isIncoming; 239a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon mIsConference = isConference; 240ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad maybeLoadCannedSmsResponses(); 2410407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad } 2420407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad 243766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon void addListener(Listener listener) { 244766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon mListeners.add(listener); 245766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon } 246766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon 247766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon void removeListener(Listener listener) { 248766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon mListeners.remove(listener); 249766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon } 250766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon 25161d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon /** {@inheritDoc} */ 25261d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon @Override public String toString() { 2534538f01647fa207b41fb7e481cc180e67fd391deSailesh Nepal String component = null; 2544538f01647fa207b41fb7e481cc180e67fd391deSailesh Nepal if (mCallService != null && mCallService.getComponentName() != null) { 2554538f01647fa207b41fb7e481cc180e67fd391deSailesh Nepal component = mCallService.getComponentName().flattenToShortString(); 2564538f01647fa207b41fb7e481cc180e67fd391deSailesh Nepal } 2574538f01647fa207b41fb7e481cc180e67fd391deSailesh Nepal return String.format(Locale.US, "[%s, %s, %s]", mState, component, Log.piiHandle(mHandle)); 25861d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon } 25961d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon 2600b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon CallState getState() { 261a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon if (mIsConference) { 262a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon if (!mChildCalls.isEmpty()) { 263a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon // If we have child calls, just return the child call. 264a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon return mChildCalls.get(0).getState(); 265a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon } 266a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon return CallState.ACTIVE; 267a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon } else { 268a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon return mState; 269a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon } 2700b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon } 2710b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon 2720b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon /** 2730b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon * Sets the call state. Although there exists the notion of appropriate state transitions 2740b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon * (see {@link CallState}), in practice those expectations break down when cellular systems 2750b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon * misbehave and they do this very often. The result is that we do not enforce state transitions 2760b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon * and instead keep the code resilient to unexpected state changes. 2770b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon */ 278810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal void setState(CallState newState) { 27979ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon Preconditions.checkState(newState != CallState.DISCONNECTED || 28079ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon mDisconnectCause != DisconnectCause.NOT_VALID); 281810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal if (mState != newState) { 282810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal Log.v(this, "setState %s -> %s", mState, newState); 283810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal mState = newState; 284ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad maybeLoadCannedSmsResponses(); 285810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal } 2860b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon } 2870b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon 288cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad void setRequestingRingback(boolean requestingRingback) { 289cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad mRequestingRingback = requestingRingback; 290cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad for (Listener l : mListeners) { 291cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad l.onRequestingRingback(this, mRequestingRingback); 292cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad } 293cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad } 294cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad 295cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad boolean isRequestingRingback() { 296cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad return mRequestingRingback; 297cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad } 298cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad 299ce704b9a5d9cf7db30a8c865975c70e5cbc0dc5cSailesh Nepal Uri getHandle() { 3000bf5b912285e328a8f5eeec158d6caf17845b9f8Ben Gilad return mHandle; 3010bf5b912285e328a8f5eeec158d6caf17845b9f8Ben Gilad } 3020bf5b912285e328a8f5eeec158d6caf17845b9f8Ben Gilad 303ce704b9a5d9cf7db30a8c865975c70e5cbc0dc5cSailesh Nepal void setHandle(Uri handle) { 304fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon if ((mHandle == null && handle != null) || (mHandle != null && !mHandle.equals(handle))) { 305fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon mHandle = handle; 306fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon mIsEmergencyCall = mHandle != null && PhoneNumberUtils.isLocalEmergencyNumber( 3076625545769bd9c5aa15b7e1ee9402f75ad799e81Yorke Lee TelecommApp.getInstance(), mHandle.getSchemeSpecificPart()); 308fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon startCallerInfoLookup(); 309fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon } 3106aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal } 3116aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal 31299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon String getName() { 31399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon return mCallerInfo == null ? null : mCallerInfo.name; 31499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon } 31599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon 31699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon Bitmap getPhotoIcon() { 31799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon return mCallerInfo == null ? null : mCallerInfo.cachedPhotoIcon; 31899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon } 31999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon 32099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon Drawable getPhoto() { 32199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon return mCallerInfo == null ? null : mCallerInfo.cachedPhoto; 32299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon } 32399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon 32479ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon /** 32579ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon * @param disconnectCause The reason for the disconnection, any of 32679ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon * {@link android.telephony.DisconnectCause}. 32779ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon * @param disconnectMessage Optional call-service-provided message about the disconnect. 32879ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon */ 32979ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon void setDisconnectCause(int disconnectCause, String disconnectMessage) { 33079ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon // TODO: Consider combining this method with a setDisconnected() method that is totally 33179ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon // separate from setState. 33279ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon mDisconnectCause = disconnectCause; 33379ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon mDisconnectMessage = disconnectMessage; 33479ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon } 33579ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon 33679ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon int getDisconnectCause() { 33779ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon return mDisconnectCause; 33879ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon } 33979ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon 34079ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon String getDisconnectMessage() { 34179ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon return mDisconnectMessage; 34279ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon } 34379ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon 3446aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal boolean isEmergencyCall() { 3456aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal return mIsEmergencyCall; 34661d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon } 34761d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon 34833501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee /** 34933501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee * @return The original handle this call is associated with. In-call services should use this 35033501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee * handle when indicating in their UI the handle that is being called. 35133501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee */ 35233501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee public Uri getOriginalHandle() { 35333501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee if (mGatewayInfo != null && !mGatewayInfo.isEmpty()) { 35433501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee return mGatewayInfo.getOriginalHandle(); 35533501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee } 35633501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee return getHandle(); 35733501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee } 35833501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee 35933501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee GatewayInfo getGatewayInfo() { 36033501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee return mGatewayInfo; 36133501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee } 36233501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee 36377d2d0e90bc2a67d526743b8e32f920a0d755fbaNancy Chen Subscription getSubscription() { 36477d2d0e90bc2a67d526743b8e32f920a0d755fbaNancy Chen return mSubscription; 36577d2d0e90bc2a67d526743b8e32f920a0d755fbaNancy Chen } 36677d2d0e90bc2a67d526743b8e32f920a0d755fbaNancy Chen 367810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal boolean isIncoming() { 368810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal return mIsIncoming; 369810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal } 370810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal 3710407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad /** 3720407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad * @return The "age" of this call object in milliseconds, which typically also represents the 3738c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal * period since this call was added to the set pending outgoing calls, see 3748c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal * mCreationTimeMillis. 3750407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad */ 3768c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal long getAgeMillis() { 3778c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal return System.currentTimeMillis() - mCreationTimeMillis; 3780407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad } 3790b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon 380f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee /** 381f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee * @return The time when this call object was created and added to the set of pending outgoing 382f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee * calls. 383f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee */ 3848c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal long getCreationTimeMillis() { 3858c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal return mCreationTimeMillis; 3868c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal } 3878c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal 3888c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal long getConnectTimeMillis() { 3898c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal return mConnectTimeMillis; 3908c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal } 3918c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal 3928c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal void setConnectTimeMillis(long connectTimeMillis) { 3938c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal mConnectTimeMillis = connectTimeMillis; 394f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee } 395f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee 396a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon boolean isConferenceCapable() { 397a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon return mIsConferenceCapable; 398a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon } 399a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon 400a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon void setIsConferenceCapable(boolean isConferenceCapable) { 401a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon if (mIsConferenceCapable != isConferenceCapable) { 402a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon mIsConferenceCapable = isConferenceCapable; 403a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon for (Listener l : mListeners) { 404a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon l.onIsConferenceCapableChanged(this, mIsConferenceCapable); 405a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon } 406a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon } 407a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon } 408a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon 409a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon Call getParentCall() { 410a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon return mParentCall; 411a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon } 412a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon 413a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon List<Call> getChildCalls() { 414a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon return mChildCalls; 415a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon } 416a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon 417c195e3613af47a49e76821d3f24c05adb71cf920Santos Cordon CallServiceWrapper getCallService() { 418681663d17b6d92b604526a54b196fa88f25b6957Santos Cordon return mCallService; 419681663d17b6d92b604526a54b196fa88f25b6957Santos Cordon } 420681663d17b6d92b604526a54b196fa88f25b6957Santos Cordon 421c195e3613af47a49e76821d3f24c05adb71cf920Santos Cordon void setCallService(CallServiceWrapper callService) { 4220e5410a58043ce059884fdc8811a280655e5a920Sailesh Nepal setCallService(callService, null); 4230e5410a58043ce059884fdc8811a280655e5a920Sailesh Nepal } 4240e5410a58043ce059884fdc8811a280655e5a920Sailesh Nepal 4250e5410a58043ce059884fdc8811a280655e5a920Sailesh Nepal /** 4260e5410a58043ce059884fdc8811a280655e5a920Sailesh Nepal * Changes the call service this call is associated with. If callToReplace is non-null then this 4270e5410a58043ce059884fdc8811a280655e5a920Sailesh Nepal * call takes its place within the call service. 4280e5410a58043ce059884fdc8811a280655e5a920Sailesh Nepal */ 4290e5410a58043ce059884fdc8811a280655e5a920Sailesh Nepal void setCallService(CallServiceWrapper callService, Call callToReplace) { 4308e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad Preconditions.checkNotNull(callService); 4318e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad 432adee12dd6b3e85ce3ae419329226c9aa72c184fcYorke Lee clearCallService(); 4338e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad 4348e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad callService.incrementAssociatedCallCount(); 435681663d17b6d92b604526a54b196fa88f25b6957Santos Cordon mCallService = callService; 4360e5410a58043ce059884fdc8811a280655e5a920Sailesh Nepal if (callToReplace == null) { 4370e5410a58043ce059884fdc8811a280655e5a920Sailesh Nepal mCallService.addCall(this); 4380e5410a58043ce059884fdc8811a280655e5a920Sailesh Nepal } else { 4390e5410a58043ce059884fdc8811a280655e5a920Sailesh Nepal mCallService.replaceCall(this, callToReplace); 4400e5410a58043ce059884fdc8811a280655e5a920Sailesh Nepal } 441681663d17b6d92b604526a54b196fa88f25b6957Santos Cordon } 442681663d17b6d92b604526a54b196fa88f25b6957Santos Cordon 443681663d17b6d92b604526a54b196fa88f25b6957Santos Cordon /** 444681663d17b6d92b604526a54b196fa88f25b6957Santos Cordon * Clears the associated call service. 445681663d17b6d92b604526a54b196fa88f25b6957Santos Cordon */ 446681663d17b6d92b604526a54b196fa88f25b6957Santos Cordon void clearCallService() { 447adee12dd6b3e85ce3ae419329226c9aa72c184fcYorke Lee if (mCallService != null) { 448c499c1c0758dcb4b02048df96e7405994660ab3fSantos Cordon CallServiceWrapper callServiceTemp = mCallService; 449adee12dd6b3e85ce3ae419329226c9aa72c184fcYorke Lee mCallService = null; 450c499c1c0758dcb4b02048df96e7405994660ab3fSantos Cordon callServiceTemp.removeCall(this); 451c499c1c0758dcb4b02048df96e7405994660ab3fSantos Cordon 452c499c1c0758dcb4b02048df96e7405994660ab3fSantos Cordon // Decrementing the count can cause the service to unbind, which itself can trigger the 453c499c1c0758dcb4b02048df96e7405994660ab3fSantos Cordon // service-death code. Since the service death code tries to clean up any associated 454c499c1c0758dcb4b02048df96e7405994660ab3fSantos Cordon // calls, we need to make sure to remove that information (e.g., removeCall()) before 455c499c1c0758dcb4b02048df96e7405994660ab3fSantos Cordon // we decrement. Technically, invoking removeCall() prior to decrementing is all that is 456c499c1c0758dcb4b02048df96e7405994660ab3fSantos Cordon // necessary, but cleaning up mCallService prior to triggering an unbind is good to do. 457c499c1c0758dcb4b02048df96e7405994660ab3fSantos Cordon // If you change this, make sure to update {@link clearCallServiceSelector} as well. 458c499c1c0758dcb4b02048df96e7405994660ab3fSantos Cordon decrementAssociatedCallCount(callServiceTemp); 459adee12dd6b3e85ce3ae419329226c9aa72c184fcYorke Lee } 4608e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad } 4618e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad 4628e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad /** 463766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon * Starts the incoming call flow through the switchboard. When switchboard completes, it will 464766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon * invoke handle[Un]SuccessfulIncomingCall. 465766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon * 466766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon * @param descriptor The relevant call-service descriptor. 467766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon * @param extras The optional extras passed via 468766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon * {@link TelecommConstants#EXTRA_INCOMING_CALL_EXTRAS}. 469766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon */ 470766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon void startIncoming(CallServiceDescriptor descriptor, Bundle extras) { 471766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon Switchboard.getInstance().retrieveIncomingCall(this, descriptor, extras); 472766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon } 473766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon 4742174fb56907fddf5680355e097f4425f837983e2Santos Cordon /** 4752174fb56907fddf5680355e097f4425f837983e2Santos Cordon * Takes a verified incoming call and uses the handle to lookup direct-to-voicemail property 4762174fb56907fddf5680355e097f4425f837983e2Santos Cordon * from the contacts provider. The call is not yet exposed to the user at this point and 4772174fb56907fddf5680355e097f4425f837983e2Santos Cordon * the result of the query will determine if the call is rejected or passed through to the 4782174fb56907fddf5680355e097f4425f837983e2Santos Cordon * in-call UI. 4792174fb56907fddf5680355e097f4425f837983e2Santos Cordon */ 4802174fb56907fddf5680355e097f4425f837983e2Santos Cordon void handleVerifiedIncoming(CallInfo callInfo) { 481766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon Preconditions.checkState(callInfo.getState() == CallState.RINGING); 4822174fb56907fddf5680355e097f4425f837983e2Santos Cordon 4832174fb56907fddf5680355e097f4425f837983e2Santos Cordon // We do not handle incoming calls immediately when they are verified by the call service. 4842174fb56907fddf5680355e097f4425f837983e2Santos Cordon // We allow the caller-info-query code to execute first so that we can read the 4852174fb56907fddf5680355e097f4425f837983e2Santos Cordon // direct-to-voicemail property before deciding if we want to show the incoming call to the 4862174fb56907fddf5680355e097f4425f837983e2Santos Cordon // user or if we want to reject the call. 4872174fb56907fddf5680355e097f4425f837983e2Santos Cordon mPendingDirectToVoicemailCallInfo = callInfo; 4882174fb56907fddf5680355e097f4425f837983e2Santos Cordon 4892174fb56907fddf5680355e097f4425f837983e2Santos Cordon // Setting the handle triggers the caller info lookup code. 490766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon setHandle(callInfo.getHandle()); 491766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon 4922174fb56907fddf5680355e097f4425f837983e2Santos Cordon // Timeout the direct-to-voicemail lookup execution so that we dont wait too long before 4932174fb56907fddf5680355e097f4425f837983e2Santos Cordon // showing the user the incoming call screen. 4942174fb56907fddf5680355e097f4425f837983e2Santos Cordon mHandler.postDelayed(new Runnable() { 4952174fb56907fddf5680355e097f4425f837983e2Santos Cordon @Override 4962174fb56907fddf5680355e097f4425f837983e2Santos Cordon public void run() { 4972174fb56907fddf5680355e097f4425f837983e2Santos Cordon processDirectToVoicemail(); 4982174fb56907fddf5680355e097f4425f837983e2Santos Cordon } 499a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon }, Timeouts.getDirectToVoicemailMillis()); 5002174fb56907fddf5680355e097f4425f837983e2Santos Cordon } 5012174fb56907fddf5680355e097f4425f837983e2Santos Cordon 5022174fb56907fddf5680355e097f4425f837983e2Santos Cordon void processDirectToVoicemail() { 5032174fb56907fddf5680355e097f4425f837983e2Santos Cordon if (mPendingDirectToVoicemailCallInfo != null) { 5042174fb56907fddf5680355e097f4425f837983e2Santos Cordon if (mCallerInfo != null && mCallerInfo.shouldSendToVoicemail) { 5052174fb56907fddf5680355e097f4425f837983e2Santos Cordon Log.i(this, "Directing call to voicemail: %s.", this); 5062174fb56907fddf5680355e097f4425f837983e2Santos Cordon // TODO(santoscordon): Once we move State handling from CallsManager to Call, we 5072174fb56907fddf5680355e097f4425f837983e2Santos Cordon // will not need to set RINGING state prior to calling reject. 5082174fb56907fddf5680355e097f4425f837983e2Santos Cordon setState(CallState.RINGING); 509ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad reject(false, null); 5102174fb56907fddf5680355e097f4425f837983e2Santos Cordon } else { 5112174fb56907fddf5680355e097f4425f837983e2Santos Cordon // TODO(santoscordon): Make this class (not CallsManager) responsible for changing 5122174fb56907fddf5680355e097f4425f837983e2Santos Cordon // the call state to RINGING. 5132174fb56907fddf5680355e097f4425f837983e2Santos Cordon 5142174fb56907fddf5680355e097f4425f837983e2Santos Cordon // TODO(santoscordon): Replace this with state transition to RINGING. 5152174fb56907fddf5680355e097f4425f837983e2Santos Cordon for (Listener l : mListeners) { 5162174fb56907fddf5680355e097f4425f837983e2Santos Cordon l.onSuccessfulIncomingCall(this, mPendingDirectToVoicemailCallInfo); 5172174fb56907fddf5680355e097f4425f837983e2Santos Cordon } 5182174fb56907fddf5680355e097f4425f837983e2Santos Cordon } 519766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon 5202174fb56907fddf5680355e097f4425f837983e2Santos Cordon mPendingDirectToVoicemailCallInfo = null; 521766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon } 522766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon } 523766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon 524766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon void handleFailedIncoming() { 525766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon clearCallService(); 526766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon 527766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon // TODO: Needs more specific disconnect error for this case. 528766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon setDisconnectCause(DisconnectCause.ERROR_UNSPECIFIED, null); 529766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon setState(CallState.DISCONNECTED); 530766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon 531766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon // TODO(santoscordon): Replace this with state transitions related to "connecting". 532766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon for (Listener l : mListeners) { 533766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon l.onFailedIncomingCall(this); 534766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon } 535766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon } 536766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon 537766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon /** 538682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon * Starts the outgoing call sequence. Upon completion, there should exist an active connection 539682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon * through a call service (or the call will have failed). 540766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon */ 541766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon void startOutgoing() { 542682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon Preconditions.checkState(mOutgoingCallProcessor == null); 543682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon 544682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon mOutgoingCallProcessor = new OutgoingCallProcessor( 5455a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal this, Switchboard.getInstance().getCallServiceRepository(), this); 546682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon mOutgoingCallProcessor.process(); 547766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon } 548766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon 5495a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal @Override 5505a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal public void onOutgoingCallSuccess() { 551766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon // TODO(santoscordon): Replace this with state transitions related to "connecting". 552766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon for (Listener l : mListeners) { 553766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon l.onSuccessfulOutgoingCall(this); 554766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon } 5555a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal mOutgoingCallProcessor = null; 5565a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal } 5575a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal 5585a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal @Override 5595a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal public void onOutgoingCallFailure(int code, String msg) { 5605a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal // TODO(santoscordon): Replace this with state transitions related to "connecting". 5615a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal for (Listener l : mListeners) { 5625a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal l.onFailedOutgoingCall(this, code, msg); 5635a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal } 5645a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal 5655a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal clearCallService(); 5665a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal mOutgoingCallProcessor = null; 567766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon } 568766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon 5695a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal @Override 5705a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal public void onOutgoingCallCancel() { 571766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon // TODO(santoscordon): Replace this with state transitions related to "connecting". 572766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon for (Listener l : mListeners) { 5735a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal l.onCancelledOutgoingCall(this); 574766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon } 575682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon 576682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon clearCallService(); 5775a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal mOutgoingCallProcessor = null; 578766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon } 579766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon 580766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon /** 5816192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad * Adds the specified call service to the list of incompatible services. The set is used when 5826192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad * attempting to switch a phone call between call services such that incompatible services can 5836192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad * be avoided. 5846192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad * 5856192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad * @param callService The incompatible call service. 5866192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad */ 5876192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad void addIncompatibleCallService(CallServiceWrapper callService) { 5886192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad if (mIncompatibleCallServices == null) { 5896192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad mIncompatibleCallServices = Sets.newHashSet(); 5906192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad } 5916192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad mIncompatibleCallServices.add(callService); 5926192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad } 5936192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad 5946192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad /** 5956192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad * Checks whether or not the specified callService was identified as incompatible in the 5966192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad * context of this call. 5976192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad * 5986192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad * @param callService The call service to evaluate. 5996192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad * @return True upon incompatible call services and false otherwise. 6006192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad */ 6016192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad boolean isIncompatibleCallService(CallServiceWrapper callService) { 6026192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad return mIncompatibleCallServices != null && 6036192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad mIncompatibleCallServices.contains(callService); 6046192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad } 6056192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad 6066192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad /** 60774549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad * Plays the specified DTMF tone. 60874549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad */ 60974549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad void playDtmfTone(char digit) { 61074549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad if (mCallService == null) { 61174549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad Log.w(this, "playDtmfTone() request on a call without a call service."); 61274549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad } else { 613e59bb195972d65a71618af4fe13f1ad982253e16Sailesh Nepal Log.i(this, "Send playDtmfTone to call service for call %s", this); 614e59bb195972d65a71618af4fe13f1ad982253e16Sailesh Nepal mCallService.playDtmfTone(this, digit); 61574549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad } 61674549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad } 61774549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad 61874549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad /** 61974549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad * Stops playing any currently playing DTMF tone. 62074549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad */ 62174549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad void stopDtmfTone() { 62274549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad if (mCallService == null) { 62374549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad Log.w(this, "stopDtmfTone() request on a call without a call service."); 62474549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad } else { 625e59bb195972d65a71618af4fe13f1ad982253e16Sailesh Nepal Log.i(this, "Send stopDtmfTone to call service for call %s", this); 626e59bb195972d65a71618af4fe13f1ad982253e16Sailesh Nepal mCallService.stopDtmfTone(this); 62774549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad } 62874549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad } 62974549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad 63074549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad /** 631049b7b6a8d0cf44d687d827cb57a18fa23358206Santos Cordon * Attempts to disconnect the call through the call service. 632049b7b6a8d0cf44d687d827cb57a18fa23358206Santos Cordon */ 633049b7b6a8d0cf44d687d827cb57a18fa23358206Santos Cordon void disconnect() { 634766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon if (mState == CallState.NEW) { 635682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon Log.v(this, "Aborting call %s", this); 636682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon abort(); 63774d420be72fa30735fe9b7a25715f6db046c0398Santos Cordon } else if (mState != CallState.ABORTED && mState != CallState.DISCONNECTED) { 638766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon Preconditions.checkNotNull(mCallService); 639766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon 640e59bb195972d65a71618af4fe13f1ad982253e16Sailesh Nepal Log.i(this, "Send disconnect to call service for call: %s", this); 641c195e3613af47a49e76821d3f24c05adb71cf920Santos Cordon // The call isn't officially disconnected until the call service confirms that the call 642c195e3613af47a49e76821d3f24c05adb71cf920Santos Cordon // was actually disconnected. Only then is the association between call and call service 643c195e3613af47a49e76821d3f24c05adb71cf920Santos Cordon // severed, see {@link CallsManager#markCallAsDisconnected}. 644e59bb195972d65a71618af4fe13f1ad982253e16Sailesh Nepal mCallService.disconnect(this); 645049b7b6a8d0cf44d687d827cb57a18fa23358206Santos Cordon } 646049b7b6a8d0cf44d687d827cb57a18fa23358206Santos Cordon } 647049b7b6a8d0cf44d687d827cb57a18fa23358206Santos Cordon 648682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon void abort() { 649682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon if (mOutgoingCallProcessor != null) { 650682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon mOutgoingCallProcessor.abort(); 651682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon } 652682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon } 653682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon 6540b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon /** 65561d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon * Answers the call if it is ringing. 65661d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon */ 65761d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon void answer() { 65861d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon Preconditions.checkNotNull(mCallService); 65961d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon 66061d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon // Check to verify that the call is still in the ringing state. A call can change states 66161d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon // between the time the user hits 'answer' and Telecomm receives the command. 66261d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon if (isRinging("answer")) { 66361d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon // At this point, we are asking the call service to answer but we don't assume that 66461d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon // it will work. Instead, we wait until confirmation from the call service that the 66561d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon // call is in a non-RINGING state before changing the UI. See 66661d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon // {@link CallServiceAdapter#setActive} and other set* methods. 667e59bb195972d65a71618af4fe13f1ad982253e16Sailesh Nepal mCallService.answer(this); 66861d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon } 66961d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon } 67061d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon 67161d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon /** 67261d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon * Rejects the call if it is ringing. 673ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad * 674ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad * @param rejectWithMessage Whether to send a text message as part of the call rejection. 675ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad * @param textMessage An optional text message to send as part of the rejection. 67661d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon */ 677ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad void reject(boolean rejectWithMessage, String textMessage) { 67861d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon Preconditions.checkNotNull(mCallService); 67961d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon 68061d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon // Check to verify that the call is still in the ringing state. A call can change states 68161d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon // between the time the user hits 'reject' and Telecomm receives the command. 68261d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon if (isRinging("reject")) { 683e59bb195972d65a71618af4fe13f1ad982253e16Sailesh Nepal mCallService.reject(this); 68461d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon } 68561d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon } 68661d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon 68761d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon /** 688cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee * Puts the call on hold if it is currently active. 689cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee */ 690cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee void hold() { 691cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee Preconditions.checkNotNull(mCallService); 692cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee 693cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee if (mState == CallState.ACTIVE) { 694e59bb195972d65a71618af4fe13f1ad982253e16Sailesh Nepal mCallService.hold(this); 695cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee } 696cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee } 697cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee 698cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee /** 699cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee * Releases the call from hold if it is currently active. 700cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee */ 701cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee void unhold() { 702cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee Preconditions.checkNotNull(mCallService); 703cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee 704cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee if (mState == CallState.ON_HOLD) { 705e59bb195972d65a71618af4fe13f1ad982253e16Sailesh Nepal mCallService.unhold(this); 706cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee } 707cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee } 708cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee 709cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee /** 7100b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon * @return An object containing read-only information about this call. 7110b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon */ 712e59bb195972d65a71618af4fe13f1ad982253e16Sailesh Nepal CallInfo toCallInfo(String callId) { 71384fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal CallServiceDescriptor descriptor = null; 71484fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal if (mCallService != null) { 71584fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal descriptor = mCallService.getDescriptor(); 71684fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal } else if (mOriginalCall != null && mOriginalCall.mCallService != null) { 71784fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal descriptor = mOriginalCall.mCallService.getDescriptor(); 71884fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal } 719571f0737002251f09b9ef696dc8b4c9ce02abbaeSantos Cordon Bundle extras = mExtras; 720571f0737002251f09b9ef696dc8b4c9ce02abbaeSantos Cordon if (mGatewayInfo != null && mGatewayInfo.getGatewayProviderPackageName() != null && 721571f0737002251f09b9ef696dc8b4c9ce02abbaeSantos Cordon mGatewayInfo.getOriginalHandle() != null) { 722571f0737002251f09b9ef696dc8b4c9ce02abbaeSantos Cordon extras = (Bundle) mExtras.clone(); 723571f0737002251f09b9ef696dc8b4c9ce02abbaeSantos Cordon extras.putString( 724571f0737002251f09b9ef696dc8b4c9ce02abbaeSantos Cordon NewOutgoingCallIntentBroadcaster.EXTRA_GATEWAY_PROVIDER_PACKAGE, 725571f0737002251f09b9ef696dc8b4c9ce02abbaeSantos Cordon mGatewayInfo.getGatewayProviderPackageName()); 726571f0737002251f09b9ef696dc8b4c9ce02abbaeSantos Cordon extras.putParcelable( 727571f0737002251f09b9ef696dc8b4c9ce02abbaeSantos Cordon NewOutgoingCallIntentBroadcaster.EXTRA_GATEWAY_ORIGINAL_URI, 728571f0737002251f09b9ef696dc8b4c9ce02abbaeSantos Cordon mGatewayInfo.getOriginalHandle()); 729571f0737002251f09b9ef696dc8b4c9ce02abbaeSantos Cordon 730571f0737002251f09b9ef696dc8b4c9ce02abbaeSantos Cordon } 73177d2d0e90bc2a67d526743b8e32f920a0d755fbaNancy Chen return new CallInfo(callId, mState, mHandle, mGatewayInfo, mSubscription, 73277d2d0e90bc2a67d526743b8e32f920a0d755fbaNancy Chen extras, descriptor); 7330b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon } 7340b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon 7356aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal /** Checks if this is a live call or not. */ 7366aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal boolean isAlive() { 7376aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal switch (mState) { 7386aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal case NEW: 7396aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal case RINGING: 7406aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal case DISCONNECTED: 7416aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal case ABORTED: 7426aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal return false; 7436aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal default: 7446aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal return true; 7456aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal } 7466aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal } 7476aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal 74840f78c210512570f14cdfde9613dd85c510a1c0cSantos Cordon boolean isActive() { 74940f78c210512570f14cdfde9613dd85c510a1c0cSantos Cordon switch (mState) { 75040f78c210512570f14cdfde9613dd85c510a1c0cSantos Cordon case ACTIVE: 75140f78c210512570f14cdfde9613dd85c510a1c0cSantos Cordon case POST_DIAL: 75240f78c210512570f14cdfde9613dd85c510a1c0cSantos Cordon case POST_DIAL_WAIT: 75340f78c210512570f14cdfde9613dd85c510a1c0cSantos Cordon return true; 75440f78c210512570f14cdfde9613dd85c510a1c0cSantos Cordon default: 75540f78c210512570f14cdfde9613dd85c510a1c0cSantos Cordon return false; 75640f78c210512570f14cdfde9613dd85c510a1c0cSantos Cordon } 75740f78c210512570f14cdfde9613dd85c510a1c0cSantos Cordon } 75840f78c210512570f14cdfde9613dd85c510a1c0cSantos Cordon 75984fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal Bundle getExtras() { 76084fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal return mExtras; 76184fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal } 76284fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal 76384fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal void setExtras(Bundle extras) { 76484fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal mExtras = extras; 76584fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal } 76684fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal 76784fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal Uri getHandoffHandle() { 76884fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal return mHandoffHandle; 76984fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal } 77084fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal 77184fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal void setHandoffHandle(Uri handoffHandle) { 77284fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal mHandoffHandle = handoffHandle; 77384fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal } 77484fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal 77584fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal Call getOriginalCall() { 77684fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal return mOriginalCall; 77784fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal } 77884fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal 77984fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal void setOriginalCall(Call originalCall) { 78084fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal mOriginalCall = originalCall; 78184fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal } 78284fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal 7838c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal CallServiceDescriptor getHandoffCallServiceDescriptor() { 7848c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal return mHandoffCallServiceDescriptor; 7858c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal } 7868c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal 7878c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal void setHandoffCallServiceDescriptor(CallServiceDescriptor descriptor) { 7888c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal mHandoffCallServiceDescriptor = descriptor; 7898c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal } 7908c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal 7915ba7f27491e287f39a999ddd3d1ed6a7bad78272Santos Cordon Uri getRingtone() { 7925ba7f27491e287f39a999ddd3d1ed6a7bad78272Santos Cordon return mCallerInfo == null ? null : mCallerInfo.contactRingtoneUri; 7935ba7f27491e287f39a999ddd3d1ed6a7bad78272Santos Cordon } 7945ba7f27491e287f39a999ddd3d1ed6a7bad78272Santos Cordon 795352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton void onPostDialWait(String remaining) { 796352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton for (Listener l : mListeners) { 797352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton l.onPostDialWait(this, remaining); 798352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton } 799352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton } 800352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton 801352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton void postDialContinue(boolean proceed) { 802352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton getCallService().onPostDialContinue(this, proceed); 803352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton } 804352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton 805a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon void conferenceInto(Call conferenceCall) { 806a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon if (mCallService == null) { 807a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon Log.w(this, "conference requested on a call without a call service."); 808a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon } else { 809a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon mCallService.conference(conferenceCall, this); 810a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon } 811a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon } 812a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon 813a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon void expireConference() { 814a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon // The conference call expired before we got a confirmation of the conference from the 815a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon // call service...so start shutting down. 816a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon clearCallService(); 817a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon for (Listener l : mListeners) { 818a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon l.onExpiredConferenceCall(this); 819a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon } 820a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon } 821a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon 822a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon void confirmConference() { 823a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon Log.v(this, "confirming Conf call %s", mListeners); 824a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon for (Listener l : mListeners) { 825a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon l.onConfirmedConferenceCall(this); 826a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon } 827a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon } 828a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon 829a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon void splitFromConference() { 830a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon // TODO(santoscordon): todo 831a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon } 832a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon 833a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon void setParentCall(Call parentCall) { 834a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon if (parentCall == this) { 835a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon Log.e(this, new Exception(), "setting the parent to self"); 836a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon return; 837a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon } 838a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon Preconditions.checkState(parentCall == null || mParentCall == null); 839a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon 840a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon Call oldParent = mParentCall; 841a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon if (mParentCall != null) { 842a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon mParentCall.removeChildCall(this); 843a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon } 844a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon mParentCall = parentCall; 845a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon if (mParentCall != null) { 846a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon mParentCall.addChildCall(this); 847a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon } 848a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon 849a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon for (Listener l : mListeners) { 850a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon l.onParentChanged(this); 851a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon } 852a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon } 853a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon 854a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon private void addChildCall(Call call) { 855a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon if (!mChildCalls.contains(call)) { 856a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon mChildCalls.add(call); 857a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon 858a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon for (Listener l : mListeners) { 859a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon l.onChildrenChanged(this); 860a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon } 861a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon } 862a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon } 863a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon 864a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon private void removeChildCall(Call call) { 865a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon if (mChildCalls.remove(call)) { 866a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon for (Listener l : mListeners) { 867a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon l.onChildrenChanged(this); 868a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon } 869a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon } 870a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon } 871a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon 8720b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon /** 873ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad * Return whether the user can respond to this {@code Call} via an SMS message. 874ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad * 875ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad * @return true if the "Respond via SMS" feature should be enabled 876ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad * for this incoming call. 877ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad * 878ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad * The general rule is that we *do* allow "Respond via SMS" except for 879ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad * the few (relatively rare) cases where we know for sure it won't 880ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad * work, namely: 881ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad * - a bogus or blank incoming number 882ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad * - a call from a SIP address 883ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad * - a "call presentation" that doesn't allow the number to be revealed 884ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad * 885ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad * In all other cases, we allow the user to respond via SMS. 886ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad * 887ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad * Note that this behavior isn't perfect; for example we have no way 888ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad * to detect whether the incoming call is from a landline (with most 889ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad * networks at least), so we still enable this feature even though 890ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad * SMSes to that number will silently fail. 891ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad */ 892ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad boolean isRespondViaSmsCapable() { 893ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad if (mState != CallState.RINGING) { 894ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad return false; 895ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad } 896ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad 897ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad if (getHandle() == null) { 898ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad // No incoming number known or call presentation is "PRESENTATION_RESTRICTED", in 899ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad // other words, the user should not be able to see the incoming phone number. 900ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad return false; 901ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad } 902ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad 903ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad if (PhoneNumberUtils.isUriNumber(getHandle().toString())) { 904ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad // The incoming number is actually a URI (i.e. a SIP address), 905ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad // not a regular PSTN phone number, and we can't send SMSes to 906ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad // SIP addresses. 907ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad // (TODO: That might still be possible eventually, though. Is 908ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad // there some SIP-specific equivalent to sending a text message?) 909ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad return false; 910ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad } 911ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad 912ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad // Is there a valid SMS application on the phone? 913ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad if (SmsApplication.getDefaultRespondViaMessageApplication(TelecommApp.getInstance(), 914ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad true /*updateIfNeeded*/) == null) { 915ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad return false; 916ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad } 917ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad 918ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad // TODO: with some carriers (in certain countries) you *can* actually 919ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad // tell whether a given number is a mobile phone or not. So in that 920ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad // case we could potentially return false here if the incoming call is 921ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad // from a land line. 922ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad 923ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad // If none of the above special cases apply, it's OK to enable the 924ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad // "Respond via SMS" feature. 925ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad return true; 926ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad } 927ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad 928ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad List<String> getCannedSmsResponses() { 929ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad return mCannedSmsResponses; 930ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad } 931ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad 932ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad /** 93361d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon * @return True if the call is ringing, else logs the action name. 93461d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon */ 93561d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon private boolean isRinging(String actionName) { 93661d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon if (mState == CallState.RINGING) { 93761d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon return true; 93861d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon } 93961d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon 940f1c191d3974fed3f57680c63571ae0212c4622e7Sailesh Nepal Log.i(this, "Request to %s a non-ringing call %s", actionName, this); 94161d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon return false; 94261d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon } 94361d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon 9448e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad @SuppressWarnings("rawtypes") 9458e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad private void decrementAssociatedCallCount(ServiceBinder binder) { 9468e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad if (binder != null) { 9478e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad binder.decrementAssociatedCallCount(); 9488e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad } 9498e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad } 950fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon 951fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon /** 952fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon * Looks up contact information based on the current handle. 953fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon */ 954fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon private void startCallerInfoLookup() { 955fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon String number = mHandle == null ? null : mHandle.getSchemeSpecificPart(); 956fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon 957fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon mQueryToken++; // Updated so that previous queries can no longer set the information. 958fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon mCallerInfo = null; 959fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon if (!TextUtils.isEmpty(number)) { 9605ba7f27491e287f39a999ddd3d1ed6a7bad78272Santos Cordon Log.v(this, "Looking up information for: %s.", Log.piiHandle(number)); 961fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon CallerInfoAsyncQuery.startQuery( 962fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon mQueryToken, 963fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon TelecommApp.getInstance(), 964fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon number, 965fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon sCallerInfoQueryListener, 966fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon this); 967fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon } 968fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon } 969fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon 970fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon /** 97199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * Saves the specified caller info if the specified token matches that of the last query 972fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon * that was made. 973fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon * 974fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon * @param callerInfo The new caller information to set. 975fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon * @param token The token used with this query. 976fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon */ 977fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon private void setCallerInfo(CallerInfo callerInfo, int token) { 97899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon Preconditions.checkNotNull(callerInfo); 97999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon 980fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon if (mQueryToken == token) { 981fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon mCallerInfo = callerInfo; 9825ba7f27491e287f39a999ddd3d1ed6a7bad78272Santos Cordon Log.i(this, "CallerInfo received for %s: %s", Log.piiHandle(mHandle), callerInfo); 98399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon 98499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon if (mCallerInfo.person_id != 0) { 98599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon Uri personUri = 98699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon ContentUris.withAppendedId(Contacts.CONTENT_URI, mCallerInfo.person_id); 98799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon Log.d(this, "Searching person uri %s for call %s", personUri, this); 98899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon ContactsAsyncHelper.startObtainPhotoAsync( 98999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon token, 99099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon TelecommApp.getInstance(), 99199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon personUri, 99299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon sPhotoLoadListener, 99399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon this); 99499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon } 9952174fb56907fddf5680355e097f4425f837983e2Santos Cordon 9962174fb56907fddf5680355e097f4425f837983e2Santos Cordon processDirectToVoicemail(); 99799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon } 99899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon } 99999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon 100099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon /** 100199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * Saves the specified photo information if the specified token matches that of the last query. 100299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * 100399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * @param photo The photo as a drawable. 100499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * @param photoIcon The photo as a small icon. 100599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon * @param token The token used with this query. 100699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon */ 100799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon private void setPhoto(Drawable photo, Bitmap photoIcon, int token) { 100899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon if (mQueryToken == token) { 100999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon mCallerInfo.cachedPhoto = photo; 101099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon mCallerInfo.cachedPhotoIcon = photoIcon; 1011fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon } 1012fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon } 1013ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad 1014ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad private void maybeLoadCannedSmsResponses() { 1015ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad if (mIsIncoming && isRespondViaSmsCapable() && !mCannedSmsResponsesLoadingStarted) { 1016ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad Log.d(this, "maybeLoadCannedSmsResponses: starting task to load messages"); 1017ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad mCannedSmsResponsesLoadingStarted = true; 1018ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad RespondViaSmsManager.getInstance().loadCannedTextMessages( 1019ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad new Response<Void, List<String>>() { 1020ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad @Override 1021ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad public void onResult(Void request, List<String>... result) { 1022ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad if (result.length > 0) { 1023ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad Log.d(this, "maybeLoadCannedSmsResponses: got %s", result[0]); 1024ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad mCannedSmsResponses = result[0]; 1025ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad for (Listener l : mListeners) { 1026ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad l.onCannedSmsResponsesLoaded(Call.this); 1027ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad } 1028ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad } 1029ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad } 1030ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad 1031ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad @Override 1032ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad public void onError(Void request, int code, String msg) { 1033ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad Log.w(Call.this, "Error obtaining canned SMS responses: %d %s", code, 1034ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad msg); 1035ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad } 1036ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad } 1037ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad ); 1038ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad } else { 1039ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad Log.d(this, "maybeLoadCannedSmsResponses: doing nothing"); 1040ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad } 1041ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad } 1042b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati 1043b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati /** 1044b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati * Sets speakerphone option on when call begins. 1045b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati */ 1046b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati public void setStartWithSpeakerphoneOn(boolean startWithSpeakerphone) { 1047b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati mSpeakerphoneOn = startWithSpeakerphone; 1048b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati } 1049b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati 1050b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati /** 1051b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati * Returns speakerphone option. 1052b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati * 1053b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati * @return Whether or not speakerphone should be set automatically when call begins. 1054b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati */ 1055b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati public boolean getStartWithSpeakerphoneOn() { 1056b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati return mSpeakerphoneOn; 1057b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati } 1058e9a776560dfe6f000cfc0dc1ea36c0f37d937f53Andrew Lee 1059e9a776560dfe6f000cfc0dc1ea36c0f37d937f53Andrew Lee /** 1060e9a776560dfe6f000cfc0dc1ea36c0f37d937f53Andrew Lee * Sets a call video provider for the call. 1061e9a776560dfe6f000cfc0dc1ea36c0f37d937f53Andrew Lee */ 1062a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen public void setCallVideoProvider(ICallVideoProvider callVideoProvider) { 1063a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen mCallVideoProvider = callVideoProvider; 1064a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen for (Listener l : mListeners) { 1065a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen l.onCallVideoProviderChanged(Call.this); 1066a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen } 1067a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen } 1068a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen 1069a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen /** 1070a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen * @return Return the call video Provider binder. 1071a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen */ 1072a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen public ICallVideoProvider getCallVideoProvider() { 1073a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen return mCallVideoProvider; 1074e9a776560dfe6f000cfc0dc1ea36c0f37d937f53Andrew Lee } 1075e19cc005ddbff5313d6f7288587630b2410d005cTyler Gunn 1076e19cc005ddbff5313d6f7288587630b2410d005cTyler Gunn /** 1077e19cc005ddbff5313d6f7288587630b2410d005cTyler Gunn * Returns the features of this call. 1078e19cc005ddbff5313d6f7288587630b2410d005cTyler Gunn * 1079e19cc005ddbff5313d6f7288587630b2410d005cTyler Gunn * @return The features of this call. 1080e19cc005ddbff5313d6f7288587630b2410d005cTyler Gunn */ 1081e19cc005ddbff5313d6f7288587630b2410d005cTyler Gunn public int getFeatures() { 1082e19cc005ddbff5313d6f7288587630b2410d005cTyler Gunn return mFeatures; 1083e19cc005ddbff5313d6f7288587630b2410d005cTyler Gunn } 1084e19cc005ddbff5313d6f7288587630b2410d005cTyler Gunn 1085e19cc005ddbff5313d6f7288587630b2410d005cTyler Gunn /** 1086e19cc005ddbff5313d6f7288587630b2410d005cTyler Gunn * Set the features associated with the call and notify any listeners of the change. 1087e19cc005ddbff5313d6f7288587630b2410d005cTyler Gunn * 1088e19cc005ddbff5313d6f7288587630b2410d005cTyler Gunn * @param features The features. 1089e19cc005ddbff5313d6f7288587630b2410d005cTyler Gunn */ 1090e19cc005ddbff5313d6f7288587630b2410d005cTyler Gunn public void setFeatures(int features) { 1091e19cc005ddbff5313d6f7288587630b2410d005cTyler Gunn Log.d(this, "setFeatures: %d", features); 1092e19cc005ddbff5313d6f7288587630b2410d005cTyler Gunn mFeatures = features; 1093e19cc005ddbff5313d6f7288587630b2410d005cTyler Gunn for (Listener l : mListeners) { 1094e19cc005ddbff5313d6f7288587630b2410d005cTyler Gunn l.onFeaturesChanged(Call.this); 1095e19cc005ddbff5313d6f7288587630b2410d005cTyler Gunn } 1096e19cc005ddbff5313d6f7288587630b2410d005cTyler Gunn } 10979f2bed31374a56487f370be01224baf6ce97e8adBen Gilad} 1098