Call.java revision b1a95a77522b2a1c98b378a2e538d819918b7f2c
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
199d58de5df05d0358fc8ae57ab7e9a0c45337c602Sailesh Nepalimport android.app.PendingIntent;
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;
25e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepalimport android.telecomm.CallPropertyPresentation;
260b03b4b143234302f098ea18de3c32658b455ecaSantos Cordonimport android.telecomm.CallState;
2772890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordonimport android.telecomm.Connection;
28c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepalimport android.telecomm.ConnectionRequest;
2933501635c2cd21f40793041eff3b8ce3a5710d49Yorke Leeimport android.telecomm.GatewayInfo;
3072890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordonimport android.telecomm.ParcelableConnection;
3189176375c8d97db25588f720952a4fadbce2f9a3Evan Charltonimport android.telecomm.PhoneAccountHandle;
32ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awadimport android.telecomm.Response;
3335faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepalimport android.telecomm.StatusHints;
3479ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordonimport android.telephony.DisconnectCause;
356aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepalimport android.telephony.PhoneNumberUtils;
36fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordonimport android.text.TextUtils;
370b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon
38a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chenimport com.android.internal.telecomm.ICallVideoProvider;
39fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordonimport com.android.internal.telephony.CallerInfo;
40fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordonimport com.android.internal.telephony.CallerInfoAsyncQuery;
41fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordonimport com.android.internal.telephony.CallerInfoAsyncQuery.OnQueryCompleteListener;
42ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awadimport com.android.internal.telephony.SmsApplication;
4399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordonimport com.android.telecomm.ContactsAsyncHelper.OnImageLoadCompleteListener;
4461d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordonimport com.google.common.base.Preconditions;
4561d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
46ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awadimport java.util.Collections;
47a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordonimport java.util.LinkedList;
48a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordonimport java.util.List;
499199078322aea6df26f0d304a28a9a6d040f0717Sailesh Nepalimport java.util.Locale;
50e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepalimport java.util.Objects;
516192561b1f56d7c4e6c650e178e07ba61ad02667Ben Giladimport java.util.Set;
52dfc6601da7bfdf63cd5c7ed815c2cb5da7975f1dSantos Cordonimport java.util.concurrent.CopyOnWriteArraySet;
530407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad
542495d57b5b91f3a39529d8844a49d1be5f18b137Ben Gilad/**
552495d57b5b91f3a39529d8844a49d1be5f18b137Ben Gilad *  Encapsulates all aspects of a given phone call throughout its lifecycle, starting
562495d57b5b91f3a39529d8844a49d1be5f18b137Ben Gilad *  from the time the call intent was received by Telecomm (vs. the time the call was
572495d57b5b91f3a39529d8844a49d1be5f18b137Ben Gilad *  connected etc).
582495d57b5b91f3a39529d8844a49d1be5f18b137Ben Gilad */
59664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalfinal class Call implements CreateConnectionResponse {
60766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    /**
61766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon     * Listener for events on the call.
62766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon     */
63766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    interface Listener {
64766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon        void onSuccessfulOutgoingCall(Call call);
655a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal        void onFailedOutgoingCall(Call call, int errorCode, String errorMsg);
665a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal        void onCancelledOutgoingCall(Call call);
67c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        void onSuccessfulIncomingCall(Call call);
68766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon        void onFailedIncomingCall(Call call);
69cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad        void onRequestingRingback(Call call, boolean requestingRingback);
70352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton        void onPostDialWait(Call call, String remaining);
71e20bc974ffc24d852d09e153a280b51e0329299cSailesh Nepal        void onCallCapabilitiesChanged(Call call);
72a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        void onExpiredConferenceCall(Call call);
73a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        void onConfirmedConferenceCall(Call call);
74a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        void onParentChanged(Call call);
75a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        void onChildrenChanged(Call call);
76ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        void onCannedSmsResponsesLoaded(Call call);
77a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen        void onCallVideoProviderChanged(Call call);
7864c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        void onCallerInfoChanged(Call call);
797e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal        void onAudioModeIsVoipChanged(Call call);
8035faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal        void onStatusHintsChanged(Call call);
81e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        void onHandleChanged(Call call);
82e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        void onCallerDisplayNameChanged(Call call);
834a79660c984d54679ad4d2bdc89e224d9c8c375bAndrew Lee        void onVideoStateChanged(Call call);
849d58de5df05d0358fc8ae57ab7e9a0c45337c602Sailesh Nepal        void onStartActivityFromInCall(Call call, PendingIntent intent);
8569eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad        void onPhoneAccountChanged(Call call);
8664c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon    }
8764c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon
8864c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon    abstract static class ListenerBase implements Listener {
8964c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
9064c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        public void onSuccessfulOutgoingCall(Call call) {}
9164c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
9264c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        public void onFailedOutgoingCall(Call call, int errorCode, String errorMsg) {}
9364c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
9464c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        public void onCancelledOutgoingCall(Call call) {}
9564c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
96c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        public void onSuccessfulIncomingCall(Call call) {}
9764c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
9864c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        public void onFailedIncomingCall(Call call) {}
9964c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
10064c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        public void onRequestingRingback(Call call, boolean requestingRingback) {}
10164c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
10264c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        public void onPostDialWait(Call call, String remaining) {}
10364c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
104e20bc974ffc24d852d09e153a280b51e0329299cSailesh Nepal        public void onCallCapabilitiesChanged(Call call) {}
10564c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
10664c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        public void onExpiredConferenceCall(Call call) {}
10764c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
10864c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        public void onConfirmedConferenceCall(Call call) {}
10964c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
11064c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        public void onParentChanged(Call call) {}
11164c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
11264c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        public void onChildrenChanged(Call call) {}
11364c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
11464c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        public void onCannedSmsResponsesLoaded(Call call) {}
11564c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
11664c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        public void onCallVideoProviderChanged(Call call) {}
11764c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
11864c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        public void onCallerInfoChanged(Call call) {}
1197e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal        @Override
1207e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal        public void onAudioModeIsVoipChanged(Call call) {}
12135faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal        @Override
12235faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal        public void onStatusHintsChanged(Call call) {}
123e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        @Override
124e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        public void onHandleChanged(Call call) {}
125e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        @Override
126e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        public void onCallerDisplayNameChanged(Call call) {}
1274a79660c984d54679ad4d2bdc89e224d9c8c375bAndrew Lee        @Override
1284a79660c984d54679ad4d2bdc89e224d9c8c375bAndrew Lee        public void onVideoStateChanged(Call call) {}
1299d58de5df05d0358fc8ae57ab7e9a0c45337c602Sailesh Nepal        @Override
1309d58de5df05d0358fc8ae57ab7e9a0c45337c602Sailesh Nepal        public void onStartActivityFromInCall(Call call, PendingIntent intent) {}
13169eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad        @Override
13269eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad        public void onPhoneAccountChanged(Call call) {}
133766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    }
134766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon
135fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    private static final OnQueryCompleteListener sCallerInfoQueryListener =
13699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon            new OnQueryCompleteListener() {
13799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                /** ${inheritDoc} */
13899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                @Override
13999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                public void onQueryComplete(int token, Object cookie, CallerInfo callerInfo) {
14099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                    if (cookie != null) {
14199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                        ((Call) cookie).setCallerInfo(callerInfo, token);
14299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                    }
143fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon                }
14499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon            };
14599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon
14699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon    private static final OnImageLoadCompleteListener sPhotoLoadListener =
14799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon            new OnImageLoadCompleteListener() {
14899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                /** ${inheritDoc} */
14999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                @Override
15099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                public void onImageLoadComplete(
15199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                        int token, Drawable photo, Bitmap photoIcon, Object cookie) {
15299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                    if (cookie != null) {
15399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                        ((Call) cookie).setPhoto(photo, photoIcon, token);
15499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                    }
15599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                }
15699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon            };
1570407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad
158664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    private final Runnable mDirectToVoicemailRunnable = new Runnable() {
159664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        @Override
160664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        public void run() {
161664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            processDirectToVoicemail();
162664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        }
163664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    };
164664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
165810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal    /** True if this is an incoming call. */
166810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal    private final boolean mIsIncoming;
167810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal
1680407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad    /**
169664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal     * The time this call was created. Beyond logging and such, may also be used for bookkeeping
170664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal     * and specifically for marking certain call attempts as failed attempts.
1710407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad     */
1728c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal    private final long mCreationTimeMillis = System.currentTimeMillis();
1738c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal
174fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    /** The gateway information associated with this call. This stores the original call handle
175fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon     * that the user is attempting to connect to via the gateway, the actual handle to dial in
176fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon     * order to connect the call via the gateway, as well as the package name of the gateway
177fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon     * service. */
178fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    private final GatewayInfo mGatewayInfo;
179fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon
18089176375c8d97db25588f720952a4fadbce2f9a3Evan Charlton    private PhoneAccountHandle mPhoneAccountHandle;
18177d2d0e90bc2a67d526743b8e32f920a0d755fbaNancy Chen
1822174fb56907fddf5680355e097f4425f837983e2Santos Cordon    private final Handler mHandler = new Handler();
1832174fb56907fddf5680355e097f4425f837983e2Santos Cordon
1848c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal    private long mConnectTimeMillis;
1850407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad
18661d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    /** The state of the call. */
18761d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    private CallState mState;
18861d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
18961d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    /** The handle with which to establish this call. */
190ce704b9a5d9cf7db30a8c865975c70e5cbc0dc5cSailesh Nepal    private Uri mHandle;
19161d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
192e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    /** The {@link CallPropertyPresentation} that controls how the handle is shown. */
193e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    private int mHandlePresentation;
194e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal
195e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    /** The caller display name (CNAP) set by the connection service. */
196e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    private String mCallerDisplayName;
197e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal
198e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    /** The {@link CallPropertyPresentation} that controls how the caller display name is shown. */
199e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    private int mCallerDisplayNamePresentation;
200e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal
2010407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad    /**
202c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal     * The connection service which is attempted or already connecting this call.
203681663d17b6d92b604526a54b196fa88f25b6957Santos Cordon     */
204c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal    private ConnectionServiceWrapper mConnectionService;
2056192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad
2066aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal    private boolean mIsEmergencyCall;
2076aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal
208b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati    private boolean mSpeakerphoneOn;
209b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati
2100a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn    /**
2110a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn     * Tracks the video states which were applicable over the duration of a call.
2120a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn     * See {@link android.telecomm.VideoCallProfile} for a list of valid video states.
2130a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn     */
2140a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn    private int mVideoStateHistory;
2150a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn
216c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn    private int mVideoState;
217c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn
2186192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad    /**
21979ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon     * Disconnect cause for the call. Only valid if the state of the call is DISCONNECTED.
22079ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon     * See {@link android.telephony.DisconnectCause}.
22179ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon     */
2228c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal    private int mDisconnectCause = DisconnectCause.NOT_VALID;
22379ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon
22479ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon    /**
225c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal     * Additional disconnect information provided by the connection service.
22679ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon     */
22779ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon    private String mDisconnectMessage;
22879ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon
229c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal    /** Info used by the connection services. */
2308c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal    private Bundle mExtras = Bundle.EMPTY;
23184fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal
232766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    /** Set of listeners on this call. */
233dfc6601da7bfdf63cd5c7ed815c2cb5da7975f1dSantos Cordon    private Set<Listener> mListeners = new CopyOnWriteArraySet<>();
234766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon
235664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    private CreateConnectionProcessor mCreateConnectionProcessor;
236682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon
237fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    /** Caller information retrieved from the latest contact query. */
238fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    private CallerInfo mCallerInfo;
239fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon
240fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    /** The latest token used with a contact info query. */
241fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    private int mQueryToken = 0;
242fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon
243cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad    /** Whether this call is requesting that Telecomm play the ringback tone on its behalf. */
244cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad    private boolean mRequestingRingback = false;
245cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad
246c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal    /** Whether direct-to-voicemail query is pending. */
247c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal    private boolean mDirectToVoicemailQueryPending;
2482174fb56907fddf5680355e097f4425f837983e2Santos Cordon
249e20bc974ffc24d852d09e153a280b51e0329299cSailesh Nepal    private int mCallCapabilities;
250a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
251a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    private boolean mIsConference = false;
252a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
253a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    private Call mParentCall = null;
254a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
255a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    private List<Call> mChildCalls = new LinkedList<>();
256a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
257ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    /** Set of text message responses allowed for this call, if applicable. */
258ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    private List<String> mCannedSmsResponses = Collections.EMPTY_LIST;
259ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad
260ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    /** Whether an attempt has been made to load the text message responses. */
261ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    private boolean mCannedSmsResponsesLoadingStarted = false;
262ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad
263a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen    private ICallVideoProvider mCallVideoProvider;
264a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen
2657e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal    private boolean mAudioModeIsVoip;
26635faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal    private StatusHints mStatusHints;
267664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    private final ConnectionServiceRepository mRepository;
2687e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal
2698c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal    /**
2700407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad     * Persists the specified parameters and initializes the new instance.
2710407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad     *
2720407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad     * @param handle The handle to dial.
27333501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee     * @param gatewayInfo Gateway information to use for the call.
27494d01629010a61f6112713f22330d5fd4baae851Evan Charlton     * @param accountHandle Account information to use for the call.
275810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal     * @param isIncoming True if this is an incoming call.
2760407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad     */
277664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    Call(
278664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            ConnectionServiceRepository repository,
279664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            Uri handle,
280664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            GatewayInfo gatewayInfo,
28194d01629010a61f6112713f22330d5fd4baae851Evan Charlton            PhoneAccountHandle accountHandle,
282664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            boolean isIncoming,
283664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            boolean isConference) {
284a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        mState = isConference ? CallState.ACTIVE : CallState.NEW;
285664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        mRepository = repository;
286e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        setHandle(handle, CallPropertyPresentation.ALLOWED);
28733501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee        mGatewayInfo = gatewayInfo;
28894d01629010a61f6112713f22330d5fd4baae851Evan Charlton        mPhoneAccountHandle = accountHandle;
289810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal        mIsIncoming = isIncoming;
290a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        mIsConference = isConference;
291ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        maybeLoadCannedSmsResponses();
2920407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad    }
2930407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad
294766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    void addListener(Listener listener) {
295766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon        mListeners.add(listener);
296766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    }
297766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon
298766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    void removeListener(Listener listener) {
299766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon        mListeners.remove(listener);
300766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    }
301766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon
30261d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    /** {@inheritDoc} */
30361d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    @Override public String toString() {
3044538f01647fa207b41fb7e481cc180e67fd391deSailesh Nepal        String component = null;
305c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        if (mConnectionService != null && mConnectionService.getComponentName() != null) {
306c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            component = mConnectionService.getComponentName().flattenToShortString();
3074538f01647fa207b41fb7e481cc180e67fd391deSailesh Nepal        }
3080a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn
3090a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn        return String.format(Locale.US, "[%s, %s, %s, %d]", mState, component,
3100a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn                Log.piiHandle(mHandle), getVideoState());
31161d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    }
31261d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
3130b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon    CallState getState() {
314a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        if (mIsConference) {
315a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            if (!mChildCalls.isEmpty()) {
316a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon                // If we have child calls, just return the child call.
317a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon                return mChildCalls.get(0).getState();
318a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            }
319a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            return CallState.ACTIVE;
320a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        } else {
321a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            return mState;
322a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        }
3230b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon    }
3240b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon
3250b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon    /**
3260b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon     * Sets the call state. Although there exists the notion of appropriate state transitions
3270b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon     * (see {@link CallState}), in practice those expectations break down when cellular systems
3280b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon     * misbehave and they do this very often. The result is that we do not enforce state transitions
3290b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon     * and instead keep the code resilient to unexpected state changes.
3300b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon     */
331810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal    void setState(CallState newState) {
33279ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon        Preconditions.checkState(newState != CallState.DISCONNECTED ||
33379ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon                mDisconnectCause != DisconnectCause.NOT_VALID);
334810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal        if (mState != newState) {
335810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal            Log.v(this, "setState %s -> %s", mState, newState);
336810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal            mState = newState;
337ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            maybeLoadCannedSmsResponses();
338810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal        }
3390b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon    }
3400b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon
341cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad    void setRequestingRingback(boolean requestingRingback) {
342cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad        mRequestingRingback = requestingRingback;
343cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad        for (Listener l : mListeners) {
344cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad            l.onRequestingRingback(this, mRequestingRingback);
345cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad        }
346cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad    }
347cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad
348cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad    boolean isRequestingRingback() {
349cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad        return mRequestingRingback;
350cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad    }
351cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad
352ce704b9a5d9cf7db30a8c865975c70e5cbc0dc5cSailesh Nepal    Uri getHandle() {
3530bf5b912285e328a8f5eeec158d6caf17845b9f8Ben Gilad        return mHandle;
3540bf5b912285e328a8f5eeec158d6caf17845b9f8Ben Gilad    }
3550bf5b912285e328a8f5eeec158d6caf17845b9f8Ben Gilad
356e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    int getHandlePresentation() {
357e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        return mHandlePresentation;
358e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    }
359e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal
360e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    void setHandle(Uri handle, int presentation) {
361e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        if (!Objects.equals(handle, mHandle) || presentation != mHandlePresentation) {
362fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon            mHandle = handle;
363e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal            mHandlePresentation = presentation;
364fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon            mIsEmergencyCall = mHandle != null && PhoneNumberUtils.isLocalEmergencyNumber(
3656625545769bd9c5aa15b7e1ee9402f75ad799e81Yorke Lee                    TelecommApp.getInstance(), mHandle.getSchemeSpecificPart());
366fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon            startCallerInfoLookup();
367e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal            for (Listener l : mListeners) {
368e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal                l.onHandleChanged(this);
369e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal            }
370e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        }
371e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    }
372e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal
373e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    String getCallerDisplayName() {
374e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        return mCallerDisplayName;
375e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    }
376e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal
377e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    int getCallerDisplayNamePresentation() {
378e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        return mCallerDisplayNamePresentation;
379e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    }
380e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal
381e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    void setCallerDisplayName(String callerDisplayName, int presentation) {
382e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        if (!TextUtils.equals(callerDisplayName, mCallerDisplayName) ||
383e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal                presentation != mCallerDisplayNamePresentation) {
384e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal            mCallerDisplayName = callerDisplayName;
385e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal            mCallerDisplayNamePresentation = presentation;
386e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal            for (Listener l : mListeners) {
387e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal                l.onCallerDisplayNameChanged(this);
388e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal            }
389fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon        }
3906aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal    }
3916aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal
39299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon    String getName() {
39399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon        return mCallerInfo == null ? null : mCallerInfo.name;
39499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon    }
39599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon
39699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon    Bitmap getPhotoIcon() {
39799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon        return mCallerInfo == null ? null : mCallerInfo.cachedPhotoIcon;
39899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon    }
39999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon
40099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon    Drawable getPhoto() {
40199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon        return mCallerInfo == null ? null : mCallerInfo.cachedPhoto;
40299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon    }
40399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon
40479ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon    /**
40579ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon     * @param disconnectCause The reason for the disconnection, any of
40679ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon     *         {@link android.telephony.DisconnectCause}.
407905dfba7883666f45a0c6958d8bc6c19d68972d9Sailesh Nepal     * @param disconnectMessage Optional message about the disconnect.
40879ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon     */
40979ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon    void setDisconnectCause(int disconnectCause, String disconnectMessage) {
41079ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon        // TODO: Consider combining this method with a setDisconnected() method that is totally
41179ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon        // separate from setState.
41279ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon        mDisconnectCause = disconnectCause;
41379ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon        mDisconnectMessage = disconnectMessage;
41479ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon    }
41579ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon
41679ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon    int getDisconnectCause() {
41779ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon        return mDisconnectCause;
41879ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon    }
41979ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon
42079ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon    String getDisconnectMessage() {
42179ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon        return mDisconnectMessage;
42279ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon    }
42379ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon
4246aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal    boolean isEmergencyCall() {
4256aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal        return mIsEmergencyCall;
42661d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    }
42761d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
42833501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee    /**
42933501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee     * @return The original handle this call is associated with. In-call services should use this
43033501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee     * handle when indicating in their UI the handle that is being called.
43133501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee     */
43233501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee    public Uri getOriginalHandle() {
43333501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee        if (mGatewayInfo != null && !mGatewayInfo.isEmpty()) {
43433501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee            return mGatewayInfo.getOriginalHandle();
43533501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee        }
43633501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee        return getHandle();
43733501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee    }
43833501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee
43933501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee    GatewayInfo getGatewayInfo() {
44033501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee        return mGatewayInfo;
44133501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee    }
44233501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee
44389176375c8d97db25588f720952a4fadbce2f9a3Evan Charlton    PhoneAccountHandle getPhoneAccount() {
44489176375c8d97db25588f720952a4fadbce2f9a3Evan Charlton        return mPhoneAccountHandle;
44577d2d0e90bc2a67d526743b8e32f920a0d755fbaNancy Chen    }
44677d2d0e90bc2a67d526743b8e32f920a0d755fbaNancy Chen
44789176375c8d97db25588f720952a4fadbce2f9a3Evan Charlton    void setPhoneAccount(PhoneAccountHandle accountHandle) {
44889176375c8d97db25588f720952a4fadbce2f9a3Evan Charlton        if (!Objects.equals(mPhoneAccountHandle, accountHandle)) {
44989176375c8d97db25588f720952a4fadbce2f9a3Evan Charlton            mPhoneAccountHandle = accountHandle;
45069eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad            for (Listener l : mListeners) {
45169eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad                l.onPhoneAccountChanged(this);
45269eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad            }
45369eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad        }
45453ceedc1f5ae5a075c7a3186db8bb4db32cbe583Nancy Chen    }
45553ceedc1f5ae5a075c7a3186db8bb4db32cbe583Nancy Chen
456810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal    boolean isIncoming() {
457810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal        return mIsIncoming;
458810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal    }
459810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal
4600407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad    /**
4610407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad     * @return The "age" of this call object in milliseconds, which typically also represents the
4628c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal     *     period since this call was added to the set pending outgoing calls, see
4638c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal     *     mCreationTimeMillis.
4640407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad     */
4658c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal    long getAgeMillis() {
4668c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal        return System.currentTimeMillis() - mCreationTimeMillis;
4670407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad    }
4680b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon
469f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    /**
470f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * @return The time when this call object was created and added to the set of pending outgoing
471f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     *     calls.
472f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     */
4738c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal    long getCreationTimeMillis() {
4748c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal        return mCreationTimeMillis;
4758c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal    }
4768c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal
4778c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal    long getConnectTimeMillis() {
4788c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal        return mConnectTimeMillis;
4798c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal    }
4808c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal
4818c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal    void setConnectTimeMillis(long connectTimeMillis) {
4828c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal        mConnectTimeMillis = connectTimeMillis;
483f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    }
484f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
485e20bc974ffc24d852d09e153a280b51e0329299cSailesh Nepal    int getCallCapabilities() {
486e20bc974ffc24d852d09e153a280b51e0329299cSailesh Nepal        return mCallCapabilities;
487a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    }
488a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
489e20bc974ffc24d852d09e153a280b51e0329299cSailesh Nepal    void setCallCapabilities(int callCapabilities) {
490e20bc974ffc24d852d09e153a280b51e0329299cSailesh Nepal        if (mCallCapabilities != callCapabilities) {
491e20bc974ffc24d852d09e153a280b51e0329299cSailesh Nepal            mCallCapabilities = callCapabilities;
492a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            for (Listener l : mListeners) {
493e20bc974ffc24d852d09e153a280b51e0329299cSailesh Nepal                l.onCallCapabilitiesChanged(this);
494a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            }
495a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        }
496a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    }
497a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
498a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    Call getParentCall() {
499a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        return mParentCall;
500a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    }
501a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
502a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    List<Call> getChildCalls() {
503a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        return mChildCalls;
504a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    }
505a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
506c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal    ConnectionServiceWrapper getConnectionService() {
507c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        return mConnectionService;
508681663d17b6d92b604526a54b196fa88f25b6957Santos Cordon    }
509681663d17b6d92b604526a54b196fa88f25b6957Santos Cordon
510c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal    void setConnectionService(ConnectionServiceWrapper service) {
511c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        Preconditions.checkNotNull(service);
5128e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad
513c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        clearConnectionService();
5148e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad
515c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        service.incrementAssociatedCallCount();
516c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        mConnectionService = service;
517c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        mConnectionService.addCall(this);
518681663d17b6d92b604526a54b196fa88f25b6957Santos Cordon    }
519681663d17b6d92b604526a54b196fa88f25b6957Santos Cordon
520681663d17b6d92b604526a54b196fa88f25b6957Santos Cordon    /**
521c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal     * Clears the associated connection service.
522681663d17b6d92b604526a54b196fa88f25b6957Santos Cordon     */
523c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal    void clearConnectionService() {
524c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        if (mConnectionService != null) {
525c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            ConnectionServiceWrapper serviceTemp = mConnectionService;
526c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            mConnectionService = null;
527c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            serviceTemp.removeCall(this);
528c499c1c0758dcb4b02048df96e7405994660ab3fSantos Cordon
529c499c1c0758dcb4b02048df96e7405994660ab3fSantos Cordon            // Decrementing the count can cause the service to unbind, which itself can trigger the
530c499c1c0758dcb4b02048df96e7405994660ab3fSantos Cordon            // service-death code.  Since the service death code tries to clean up any associated
531c499c1c0758dcb4b02048df96e7405994660ab3fSantos Cordon            // calls, we need to make sure to remove that information (e.g., removeCall()) before
532c499c1c0758dcb4b02048df96e7405994660ab3fSantos Cordon            // we decrement. Technically, invoking removeCall() prior to decrementing is all that is
533c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            // necessary, but cleaning up mConnectionService prior to triggering an unbind is good
534c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            // to do.
535c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            decrementAssociatedCallCount(serviceTemp);
536adee12dd6b3e85ce3ae419329226c9aa72c184fcYorke Lee        }
5378e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad    }
5388e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad
539664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    private void processDirectToVoicemail() {
540c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        if (mDirectToVoicemailQueryPending) {
5412174fb56907fddf5680355e097f4425f837983e2Santos Cordon            if (mCallerInfo != null && mCallerInfo.shouldSendToVoicemail) {
5422174fb56907fddf5680355e097f4425f837983e2Santos Cordon                Log.i(this, "Directing call to voicemail: %s.", this);
5432174fb56907fddf5680355e097f4425f837983e2Santos Cordon                // TODO(santoscordon): Once we move State handling from CallsManager to Call, we
5442174fb56907fddf5680355e097f4425f837983e2Santos Cordon                // will not need to set RINGING state prior to calling reject.
5452174fb56907fddf5680355e097f4425f837983e2Santos Cordon                setState(CallState.RINGING);
546ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                reject(false, null);
5472174fb56907fddf5680355e097f4425f837983e2Santos Cordon            } else {
5482174fb56907fddf5680355e097f4425f837983e2Santos Cordon                // TODO(santoscordon): Make this class (not CallsManager) responsible for changing
5492174fb56907fddf5680355e097f4425f837983e2Santos Cordon                // the call state to RINGING.
5502174fb56907fddf5680355e097f4425f837983e2Santos Cordon
5512174fb56907fddf5680355e097f4425f837983e2Santos Cordon                // TODO(santoscordon): Replace this with state transition to RINGING.
5522174fb56907fddf5680355e097f4425f837983e2Santos Cordon                for (Listener l : mListeners) {
553c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal                    l.onSuccessfulIncomingCall(this);
5542174fb56907fddf5680355e097f4425f837983e2Santos Cordon                }
5552174fb56907fddf5680355e097f4425f837983e2Santos Cordon            }
556766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon
557c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            mDirectToVoicemailQueryPending = false;
558766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon        }
559766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    }
560766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon
561766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    /**
562664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal     * Starts the create connection sequence. Upon completion, there should exist an active
563664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal     * connection through a connection service (or the call will have failed).
564766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon     */
565664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    void startCreateConnection() {
566664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        Preconditions.checkState(mCreateConnectionProcessor == null);
567664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        mCreateConnectionProcessor = new CreateConnectionProcessor(this, mRepository, this);
568664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        mCreateConnectionProcessor.process();
569766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    }
570766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon
5715a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal    @Override
57272890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon    public void handleCreateConnectionSuccessful(
57372890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon            ConnectionRequest request, ParcelableConnection connection) {
574664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        mCreateConnectionProcessor = null;
57572890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon        setState(getStateFromConnectionState(connection.getState()));
57672890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon        setPhoneAccount(connection.getPhoneAccount());
57772890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon        setHandle(connection.getHandle(), connection.getHandlePresentation());
57872890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon        setCallerDisplayName(
57972890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon                connection.getCallerDisplayName(), connection.getCallerDisplayNamePresentation());
58072890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon        setCallVideoProvider(connection.getCallVideoProvider());
581b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        setVideoState(connection.getVideoState());
582664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
583664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        if (mIsIncoming) {
584664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            // We do not handle incoming calls immediately when they are verified by the connection
585664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            // service. We allow the caller-info-query code to execute first so that we can read the
586664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            // direct-to-voicemail property before deciding if we want to show the incoming call to
587664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            // the user or if we want to reject the call.
588664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            mDirectToVoicemailQueryPending = true;
589664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
590664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            // Timeout the direct-to-voicemail lookup execution so that we dont wait too long before
591664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            // showing the user the incoming call screen.
592664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            mHandler.postDelayed(mDirectToVoicemailRunnable, Timeouts.getDirectToVoicemailMillis());
593664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        } else {
594664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            for (Listener l : mListeners) {
595664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal                l.onSuccessfulOutgoingCall(this);
596664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            }
597766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon        }
5985a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal    }
5995a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal
6005a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal    @Override
601664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    public void handleCreateConnectionFailed(int code, String msg) {
602664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        mCreateConnectionProcessor = null;
603664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        if (mIsIncoming) {
604664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            clearConnectionService();
605664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            setDisconnectCause(code, null);
606664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            setState(CallState.DISCONNECTED);
607664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
608664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
609664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            for (int i = 0; i < listeners.length; i++) {
610664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal                listeners[i].onFailedIncomingCall(this);
611664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            }
612664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        } else {
613664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
614664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            for (int i = 0; i < listeners.length; i++) {
615664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal                listeners[i].onFailedOutgoingCall(this, code, msg);
616664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            }
617664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            clearConnectionService();
6185a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal        }
619766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    }
620766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon
6215a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal    @Override
622664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    public void handleCreateConnectionCancelled() {
623664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        mCreateConnectionProcessor = null;
624664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        if (mIsIncoming) {
625664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            clearConnectionService();
626664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            setDisconnectCause(DisconnectCause.ERROR_UNSPECIFIED, null);
627664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            setState(CallState.DISCONNECTED);
628664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
629664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
630664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            for (int i = 0; i < listeners.length; i++) {
631664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal                listeners[i].onFailedIncomingCall(this);
632664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            }
633664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        } else {
634664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
635664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            for (int i = 0; i < listeners.length; i++) {
636664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal                listeners[i].onCancelledOutgoingCall(this);
637664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            }
638664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            clearConnectionService();
639766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon        }
640766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    }
641766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon
642766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    /**
64374549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad     * Plays the specified DTMF tone.
64474549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad     */
64574549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad    void playDtmfTone(char digit) {
646c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        if (mConnectionService == null) {
647c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            Log.w(this, "playDtmfTone() request on a call without a connection service.");
64874549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad        } else {
649c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            Log.i(this, "Send playDtmfTone to connection service for call %s", this);
650c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            mConnectionService.playDtmfTone(this, digit);
65174549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad        }
65274549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad    }
65374549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad
65474549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad    /**
65574549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad     * Stops playing any currently playing DTMF tone.
65674549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad     */
65774549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad    void stopDtmfTone() {
658c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        if (mConnectionService == null) {
659c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            Log.w(this, "stopDtmfTone() request on a call without a connectino service.");
66074549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad        } else {
661c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            Log.i(this, "Send stopDtmfTone to connection service for call %s", this);
662c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            mConnectionService.stopDtmfTone(this);
66374549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad        }
66474549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad    }
66574549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad
66674549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad    /**
667c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal     * Attempts to disconnect the call through the connection service.
668049b7b6a8d0cf44d687d827cb57a18fa23358206Santos Cordon     */
669049b7b6a8d0cf44d687d827cb57a18fa23358206Santos Cordon    void disconnect() {
67053ceedc1f5ae5a075c7a3186db8bb4db32cbe583Nancy Chen        if (mState == CallState.NEW || mState == CallState.PRE_DIAL_WAIT) {
671682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon            Log.v(this, "Aborting call %s", this);
672682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon            abort();
67374d420be72fa30735fe9b7a25715f6db046c0398Santos Cordon        } else if (mState != CallState.ABORTED && mState != CallState.DISCONNECTED) {
674c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            Preconditions.checkNotNull(mConnectionService);
675766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon
676c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            Log.i(this, "Send disconnect to connection service for call: %s", this);
677c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            // The call isn't officially disconnected until the connection service confirms that the
678c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            // call was actually disconnected. Only then is the association between call and
679c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            // connection service severed, see {@link CallsManager#markCallAsDisconnected}.
680c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            mConnectionService.disconnect(this);
681049b7b6a8d0cf44d687d827cb57a18fa23358206Santos Cordon        }
682049b7b6a8d0cf44d687d827cb57a18fa23358206Santos Cordon    }
683049b7b6a8d0cf44d687d827cb57a18fa23358206Santos Cordon
684682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon    void abort() {
685664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        if (mCreateConnectionProcessor != null) {
686664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            mCreateConnectionProcessor.abort();
68753ceedc1f5ae5a075c7a3186db8bb4db32cbe583Nancy Chen        } else if (mState == CallState.PRE_DIAL_WAIT) {
68853ceedc1f5ae5a075c7a3186db8bb4db32cbe583Nancy Chen            handleCreateConnectionFailed(DisconnectCause.LOCAL, null);
689682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon        }
690682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon    }
691682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon
6920b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon    /**
69361d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon     * Answers the call if it is ringing.
69438931d0ad60f00a9f50c90cef446166731f0b871Andrew Lee     *
69538931d0ad60f00a9f50c90cef446166731f0b871Andrew Lee     * @param videoState The video state in which to answer the call.
69661d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon     */
69738931d0ad60f00a9f50c90cef446166731f0b871Andrew Lee    void answer(int videoState) {
698c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        Preconditions.checkNotNull(mConnectionService);
69961d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
70061d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon        // Check to verify that the call is still in the ringing state. A call can change states
70161d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon        // between the time the user hits 'answer' and Telecomm receives the command.
70261d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon        if (isRinging("answer")) {
703c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            // At this point, we are asking the connection service to answer but we don't assume
704c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            // that it will work. Instead, we wait until confirmation from the connectino service
705c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            // that the call is in a non-RINGING state before changing the UI. See
706c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            // {@link ConnectionServiceAdapter#setActive} and other set* methods.
70738931d0ad60f00a9f50c90cef446166731f0b871Andrew Lee            mConnectionService.answer(this, videoState);
70861d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon        }
70961d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    }
71061d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
71161d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    /**
71261d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon     * Rejects the call if it is ringing.
713ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     *
714ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * @param rejectWithMessage Whether to send a text message as part of the call rejection.
715ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * @param textMessage An optional text message to send as part of the rejection.
71661d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon     */
717ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    void reject(boolean rejectWithMessage, String textMessage) {
718c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        Preconditions.checkNotNull(mConnectionService);
71961d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
72061d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon        // Check to verify that the call is still in the ringing state. A call can change states
72161d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon        // between the time the user hits 'reject' and Telecomm receives the command.
72261d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon        if (isRinging("reject")) {
723c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            mConnectionService.reject(this);
72461d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon        }
72561d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    }
72661d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
72761d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    /**
728cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee     * Puts the call on hold if it is currently active.
729cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee     */
730cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee    void hold() {
731c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        Preconditions.checkNotNull(mConnectionService);
732cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee
733cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee        if (mState == CallState.ACTIVE) {
734c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            mConnectionService.hold(this);
735cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee        }
736cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee    }
737cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee
738cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee    /**
739cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee     * Releases the call from hold if it is currently active.
740cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee     */
741cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee    void unhold() {
742c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        Preconditions.checkNotNull(mConnectionService);
743cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee
744cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee        if (mState == CallState.ON_HOLD) {
745c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            mConnectionService.unhold(this);
746571f0737002251f09b9ef696dc8b4c9ce02abbaeSantos Cordon        }
7470b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon    }
7480b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon
7496aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal    /** Checks if this is a live call or not. */
7506aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal    boolean isAlive() {
7516aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal        switch (mState) {
7526aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal            case NEW:
7536aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal            case RINGING:
7546aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal            case DISCONNECTED:
7556aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal            case ABORTED:
7566aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal                return false;
7576aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal            default:
7586aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal                return true;
7596aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal        }
7606aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal    }
7616aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal
76240f78c210512570f14cdfde9613dd85c510a1c0cSantos Cordon    boolean isActive() {
76384bfe47a2447c4983bcc58468000f04683eec55bIhab Awad        return mState == CallState.ACTIVE;
76440f78c210512570f14cdfde9613dd85c510a1c0cSantos Cordon    }
76540f78c210512570f14cdfde9613dd85c510a1c0cSantos Cordon
76684fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal    Bundle getExtras() {
76784fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal        return mExtras;
76884fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal    }
76984fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal
77084fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal    void setExtras(Bundle extras) {
77184fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal        mExtras = extras;
77284fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal    }
77384fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal
7745ba7f27491e287f39a999ddd3d1ed6a7bad78272Santos Cordon    Uri getRingtone() {
7755ba7f27491e287f39a999ddd3d1ed6a7bad78272Santos Cordon        return mCallerInfo == null ? null : mCallerInfo.contactRingtoneUri;
7765ba7f27491e287f39a999ddd3d1ed6a7bad78272Santos Cordon    }
7775ba7f27491e287f39a999ddd3d1ed6a7bad78272Santos Cordon
778352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton    void onPostDialWait(String remaining) {
779352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton        for (Listener l : mListeners) {
780352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton            l.onPostDialWait(this, remaining);
781352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton        }
782352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton    }
783352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton
784352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton    void postDialContinue(boolean proceed) {
785c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        mConnectionService.onPostDialContinue(this, proceed);
786352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton    }
787352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton
78877da19ea28b8753d439660b4352c1bf914f63a92Sailesh Nepal    void phoneAccountClicked() {
789c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        mConnectionService.onPhoneAccountClicked(this);
79077da19ea28b8753d439660b4352c1bf914f63a92Sailesh Nepal    }
79177da19ea28b8753d439660b4352c1bf914f63a92Sailesh Nepal
792a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    void conferenceInto(Call conferenceCall) {
793c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        if (mConnectionService == null) {
794c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            Log.w(this, "conference requested on a call without a connection service.");
795a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        } else {
796c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            mConnectionService.conference(conferenceCall, this);
797a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        }
798a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    }
799a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
800a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    void expireConference() {
801a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        // The conference call expired before we got a confirmation of the conference from the
802c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        // connection service...so start shutting down.
803c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        clearConnectionService();
804a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        for (Listener l : mListeners) {
805a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            l.onExpiredConferenceCall(this);
806a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        }
807a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    }
808a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
809a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    void confirmConference() {
810a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        Log.v(this, "confirming Conf call %s", mListeners);
811a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        for (Listener l : mListeners) {
812a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            l.onConfirmedConferenceCall(this);
813a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        }
814a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    }
815a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
816a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    void splitFromConference() {
817a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        // TODO(santoscordon): todo
818a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    }
819a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
820e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    void swapWithBackgroundCall() {
821e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        mConnectionService.swapWithBackgroundCall(this);
822e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    }
823e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal
824a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    void setParentCall(Call parentCall) {
825a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        if (parentCall == this) {
826a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            Log.e(this, new Exception(), "setting the parent to self");
827a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            return;
828a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        }
829a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        Preconditions.checkState(parentCall == null || mParentCall == null);
830a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
831a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        Call oldParent = mParentCall;
832a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        if (mParentCall != null) {
833a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            mParentCall.removeChildCall(this);
834a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        }
835a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        mParentCall = parentCall;
836a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        if (mParentCall != null) {
837a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            mParentCall.addChildCall(this);
838a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        }
839a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
840a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        for (Listener l : mListeners) {
841a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            l.onParentChanged(this);
842a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        }
843a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    }
844a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
845a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    private void addChildCall(Call call) {
846a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        if (!mChildCalls.contains(call)) {
847a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            mChildCalls.add(call);
848a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
849a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            for (Listener l : mListeners) {
850a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon                l.onChildrenChanged(this);
851a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            }
852a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        }
853a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    }
854a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
855a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    private void removeChildCall(Call call) {
856a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        if (mChildCalls.remove(call)) {
857a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            for (Listener l : mListeners) {
858a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon                l.onChildrenChanged(this);
859a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            }
860a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        }
861a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    }
862a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
8630b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon    /**
864ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * Return whether the user can respond to this {@code Call} via an SMS message.
865ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     *
866ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * @return true if the "Respond via SMS" feature should be enabled
867ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * for this incoming call.
868ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     *
869ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * The general rule is that we *do* allow "Respond via SMS" except for
870ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * the few (relatively rare) cases where we know for sure it won't
871ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * work, namely:
872ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     *   - a bogus or blank incoming number
873ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     *   - a call from a SIP address
874ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     *   - a "call presentation" that doesn't allow the number to be revealed
875ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     *
876ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * In all other cases, we allow the user to respond via SMS.
877ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     *
878ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * Note that this behavior isn't perfect; for example we have no way
879ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * to detect whether the incoming call is from a landline (with most
880ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * networks at least), so we still enable this feature even though
881ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * SMSes to that number will silently fail.
882ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     */
883ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    boolean isRespondViaSmsCapable() {
884ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        if (mState != CallState.RINGING) {
885ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            return false;
886ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        }
887ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad
888ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        if (getHandle() == null) {
889ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            // No incoming number known or call presentation is "PRESENTATION_RESTRICTED", in
890ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            // other words, the user should not be able to see the incoming phone number.
891ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            return false;
892ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        }
893ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad
894ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        if (PhoneNumberUtils.isUriNumber(getHandle().toString())) {
895ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            // The incoming number is actually a URI (i.e. a SIP address),
896ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            // not a regular PSTN phone number, and we can't send SMSes to
897ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            // SIP addresses.
898ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            // (TODO: That might still be possible eventually, though. Is
899ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            // there some SIP-specific equivalent to sending a text message?)
900ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            return false;
901ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        }
902ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad
903ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        // Is there a valid SMS application on the phone?
904ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        if (SmsApplication.getDefaultRespondViaMessageApplication(TelecommApp.getInstance(),
905ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                true /*updateIfNeeded*/) == null) {
906ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            return false;
907ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        }
908ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad
909ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        // TODO: with some carriers (in certain countries) you *can* actually
910ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        // tell whether a given number is a mobile phone or not. So in that
911ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        // case we could potentially return false here if the incoming call is
912ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        // from a land line.
913ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad
914ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        // If none of the above special cases apply, it's OK to enable the
915ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        // "Respond via SMS" feature.
916ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        return true;
917ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    }
918ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad
919ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    List<String> getCannedSmsResponses() {
920ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        return mCannedSmsResponses;
921ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    }
922ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad
923ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    /**
92461d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon     * @return True if the call is ringing, else logs the action name.
92561d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon     */
92661d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    private boolean isRinging(String actionName) {
92761d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon        if (mState == CallState.RINGING) {
92861d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon            return true;
92961d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon        }
93061d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
931f1c191d3974fed3f57680c63571ae0212c4622e7Sailesh Nepal        Log.i(this, "Request to %s a non-ringing call %s", actionName, this);
93261d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon        return false;
93361d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    }
93461d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
9358e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad    @SuppressWarnings("rawtypes")
9368e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad    private void decrementAssociatedCallCount(ServiceBinder binder) {
9378e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad        if (binder != null) {
9388e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad            binder.decrementAssociatedCallCount();
9398e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad        }
9408e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad    }
941fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon
942fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    /**
943fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon     * Looks up contact information based on the current handle.
944fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon     */
945fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    private void startCallerInfoLookup() {
946fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon        String number = mHandle == null ? null : mHandle.getSchemeSpecificPart();
947fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon
948fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon        mQueryToken++;  // Updated so that previous queries can no longer set the information.
949fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon        mCallerInfo = null;
950fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon        if (!TextUtils.isEmpty(number)) {
9515ba7f27491e287f39a999ddd3d1ed6a7bad78272Santos Cordon            Log.v(this, "Looking up information for: %s.", Log.piiHandle(number));
952fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon            CallerInfoAsyncQuery.startQuery(
953fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon                    mQueryToken,
954fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon                    TelecommApp.getInstance(),
955fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon                    number,
956fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon                    sCallerInfoQueryListener,
957fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon                    this);
958fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon        }
959fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    }
960fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon
961fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    /**
96299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon     * Saves the specified caller info if the specified token matches that of the last query
963fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon     * that was made.
964fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon     *
965fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon     * @param callerInfo The new caller information to set.
966fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon     * @param token The token used with this query.
967fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon     */
968fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    private void setCallerInfo(CallerInfo callerInfo, int token) {
96999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon        Preconditions.checkNotNull(callerInfo);
97099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon
971fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon        if (mQueryToken == token) {
972fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon            mCallerInfo = callerInfo;
9735ba7f27491e287f39a999ddd3d1ed6a7bad78272Santos Cordon            Log.i(this, "CallerInfo received for %s: %s", Log.piiHandle(mHandle), callerInfo);
97499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon
975a1662d0ae89d9fb514a5ac68cbc76660e34dae00Makoto Onuki            if (mCallerInfo.contactDisplayPhotoUri != null) {
976a1662d0ae89d9fb514a5ac68cbc76660e34dae00Makoto Onuki                Log.d(this, "Searching person uri %s for call %s",
977a1662d0ae89d9fb514a5ac68cbc76660e34dae00Makoto Onuki                        mCallerInfo.contactDisplayPhotoUri, this);
97899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                ContactsAsyncHelper.startObtainPhotoAsync(
97999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                        token,
98099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                        TelecommApp.getInstance(),
981a1662d0ae89d9fb514a5ac68cbc76660e34dae00Makoto Onuki                        mCallerInfo.contactDisplayPhotoUri,
98299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                        sPhotoLoadListener,
98399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                        this);
984a1662d0ae89d9fb514a5ac68cbc76660e34dae00Makoto Onuki                // Do not call onCallerInfoChanged yet in this case.  We call it in setPhoto().
98564c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon            } else {
98664c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon                for (Listener l : mListeners) {
98764c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon                    l.onCallerInfoChanged(this);
98864c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon                }
98999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon            }
9902174fb56907fddf5680355e097f4425f837983e2Santos Cordon
9912174fb56907fddf5680355e097f4425f837983e2Santos Cordon            processDirectToVoicemail();
99299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon        }
99399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon    }
99499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon
9956f3f7affb13e93cb70868d3114f02f1ed593194eYorke Lee    CallerInfo getCallerInfo() {
9966f3f7affb13e93cb70868d3114f02f1ed593194eYorke Lee        return mCallerInfo;
9976f3f7affb13e93cb70868d3114f02f1ed593194eYorke Lee    }
9986f3f7affb13e93cb70868d3114f02f1ed593194eYorke Lee
99999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon    /**
100099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon     * Saves the specified photo information if the specified token matches that of the last query.
100199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon     *
100299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon     * @param photo The photo as a drawable.
100399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon     * @param photoIcon The photo as a small icon.
100499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon     * @param token The token used with this query.
100599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon     */
100699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon    private void setPhoto(Drawable photo, Bitmap photoIcon, int token) {
100799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon        if (mQueryToken == token) {
100899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon            mCallerInfo.cachedPhoto = photo;
100999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon            mCallerInfo.cachedPhotoIcon = photoIcon;
101064c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon
101164c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon            for (Listener l : mListeners) {
101264c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon                l.onCallerInfoChanged(this);
101364c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon            }
1014fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon        }
1015fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    }
1016ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad
1017ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    private void maybeLoadCannedSmsResponses() {
1018ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        if (mIsIncoming && isRespondViaSmsCapable() && !mCannedSmsResponsesLoadingStarted) {
1019ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            Log.d(this, "maybeLoadCannedSmsResponses: starting task to load messages");
1020ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            mCannedSmsResponsesLoadingStarted = true;
1021ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            RespondViaSmsManager.getInstance().loadCannedTextMessages(
1022ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                    new Response<Void, List<String>>() {
1023ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                        @Override
1024ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                        public void onResult(Void request, List<String>... result) {
1025ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                            if (result.length > 0) {
1026ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                                Log.d(this, "maybeLoadCannedSmsResponses: got %s", result[0]);
1027ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                                mCannedSmsResponses = result[0];
1028ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                                for (Listener l : mListeners) {
1029ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                                    l.onCannedSmsResponsesLoaded(Call.this);
1030ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                                }
1031ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                            }
1032ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                        }
1033ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad
1034ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                        @Override
1035ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                        public void onError(Void request, int code, String msg) {
1036ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                            Log.w(Call.this, "Error obtaining canned SMS responses: %d %s", code,
1037ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                                    msg);
1038ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                        }
1039ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                    }
1040ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            );
1041ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        } else {
1042ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            Log.d(this, "maybeLoadCannedSmsResponses: doing nothing");
1043ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        }
1044ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    }
1045b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati
1046b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati    /**
1047b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati     * Sets speakerphone option on when call begins.
1048b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati     */
1049b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati    public void setStartWithSpeakerphoneOn(boolean startWithSpeakerphone) {
1050b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati        mSpeakerphoneOn = startWithSpeakerphone;
1051b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati    }
1052b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati
1053b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati    /**
1054b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati     * Returns speakerphone option.
1055b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati     *
1056b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati     * @return Whether or not speakerphone should be set automatically when call begins.
1057b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati     */
1058b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati    public boolean getStartWithSpeakerphoneOn() {
1059b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati        return mSpeakerphoneOn;
1060b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati    }
1061e9a776560dfe6f000cfc0dc1ea36c0f37d937f53Andrew Lee
1062e9a776560dfe6f000cfc0dc1ea36c0f37d937f53Andrew Lee    /**
1063e9a776560dfe6f000cfc0dc1ea36c0f37d937f53Andrew Lee     * Sets a call video provider for the call.
1064e9a776560dfe6f000cfc0dc1ea36c0f37d937f53Andrew Lee     */
1065a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen    public void setCallVideoProvider(ICallVideoProvider callVideoProvider) {
1066a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen        mCallVideoProvider = callVideoProvider;
1067a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen        for (Listener l : mListeners) {
1068a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen            l.onCallVideoProviderChanged(Call.this);
1069a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen        }
1070a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen    }
1071a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen
1072a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen    /**
1073a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen     * @return Return the call video Provider binder.
1074a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen     */
1075a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen    public ICallVideoProvider getCallVideoProvider() {
1076a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen        return mCallVideoProvider;
1077e9a776560dfe6f000cfc0dc1ea36c0f37d937f53Andrew Lee    }
1078e19cc005ddbff5313d6f7288587630b2410d005cTyler Gunn
1079e19cc005ddbff5313d6f7288587630b2410d005cTyler Gunn    /**
1080c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn     * The current video state for the call.
1081c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn     * Valid values: {@link android.telecomm.VideoCallProfile#VIDEO_STATE_AUDIO_ONLY},
1082c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn     * {@link android.telecomm.VideoCallProfile#VIDEO_STATE_BIDIRECTIONAL},
1083c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn     * {@link android.telecomm.VideoCallProfile#VIDEO_STATE_TX_ENABLED},
1084c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn     * {@link android.telecomm.VideoCallProfile#VIDEO_STATE_RX_ENABLED}.
1085c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn     *
1086c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn     * @return True if video is enabled.
1087c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn     */
1088c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn    public int getVideoState() {
1089c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn        return mVideoState;
1090c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn    }
1091c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn
1092c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn    /**
10930a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn     * Returns the video states which were applicable over the duration of a call.
10940a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn     * See {@link android.telecomm.VideoCallProfile} for a list of valid video states.
10950a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn     *
10960a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn     * @return The video states applicable over the duration of the call.
10970a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn     */
10980a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn    public int getVideoStateHistory() {
10990a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn        return mVideoStateHistory;
11000a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn    }
11010a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn
11020a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn    /**
11030a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn     * Determines the current video state for the call.
11040a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn     * For an outgoing call determines the desired video state for the call.
1105c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn     * Valid values: {@link android.telecomm.VideoCallProfile#VIDEO_STATE_AUDIO_ONLY},
1106c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn     * {@link android.telecomm.VideoCallProfile#VIDEO_STATE_BIDIRECTIONAL},
1107c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn     * {@link android.telecomm.VideoCallProfile#VIDEO_STATE_TX_ENABLED},
1108c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn     * {@link android.telecomm.VideoCallProfile#VIDEO_STATE_RX_ENABLED}.
1109c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn     *
11100a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn     * @param videoState The video state for the call.
1111c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn     */
1112c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn    public void setVideoState(int videoState) {
11130a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn        // Track which video states were applicable over the duration of the call.
11140a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn        mVideoStateHistory = mVideoStateHistory | videoState;
11150a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn
1116c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn        mVideoState = videoState;
11174a79660c984d54679ad4d2bdc89e224d9c8c375bAndrew Lee        for (Listener l : mListeners) {
11184a79660c984d54679ad4d2bdc89e224d9c8c375bAndrew Lee            l.onVideoStateChanged(this);
11194a79660c984d54679ad4d2bdc89e224d9c8c375bAndrew Lee        }
1120c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn    }
11217e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal
11227e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal    public boolean getAudioModeIsVoip() {
11237e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal        return mAudioModeIsVoip;
11247e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal    }
11257e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal
11267e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal    public void setAudioModeIsVoip(boolean audioModeIsVoip) {
11277e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal        mAudioModeIsVoip = audioModeIsVoip;
11287e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal        for (Listener l : mListeners) {
112935faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal            l.onAudioModeIsVoipChanged(this);
113035faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal        }
113135faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal    }
113235faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal
113335faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal    public StatusHints getStatusHints() {
113435faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal        return mStatusHints;
113535faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal    }
113635faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal
113735faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal    public void setStatusHints(StatusHints statusHints) {
113835faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal        mStatusHints = statusHints;
113935faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal        for (Listener l : mListeners) {
114035faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal            l.onStatusHintsChanged(this);
11417e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal        }
11427e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal    }
11439d58de5df05d0358fc8ae57ab7e9a0c45337c602Sailesh Nepal
11449d58de5df05d0358fc8ae57ab7e9a0c45337c602Sailesh Nepal    public void startActivityFromInCall(PendingIntent intent) {
11459d58de5df05d0358fc8ae57ab7e9a0c45337c602Sailesh Nepal        if (intent.isActivity()) {
11469d58de5df05d0358fc8ae57ab7e9a0c45337c602Sailesh Nepal            for (Listener l : mListeners) {
11479d58de5df05d0358fc8ae57ab7e9a0c45337c602Sailesh Nepal                l.onStartActivityFromInCall(this, intent);
11489d58de5df05d0358fc8ae57ab7e9a0c45337c602Sailesh Nepal            }
11499d58de5df05d0358fc8ae57ab7e9a0c45337c602Sailesh Nepal        } else {
11509d58de5df05d0358fc8ae57ab7e9a0c45337c602Sailesh Nepal            Log.w(this, "startActivityFromInCall, activity intent required");
11519d58de5df05d0358fc8ae57ab7e9a0c45337c602Sailesh Nepal        }
11529d58de5df05d0358fc8ae57ab7e9a0c45337c602Sailesh Nepal    }
115372890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon
115472890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon    private CallState getStateFromConnectionState(int state) {
115572890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon        switch (state) {
115672890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon            case Connection.State.ACTIVE:
115772890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon                return CallState.ACTIVE;
115872890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon            case Connection.State.DIALING:
115972890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon                return CallState.DIALING;
116072890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon            case Connection.State.DISCONNECTED:
116172890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon                return CallState.DISCONNECTED;
116272890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon            case Connection.State.HOLDING:
116372890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon                return CallState.ON_HOLD;
116472890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon            case Connection.State.NEW:
116572890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon                return CallState.NEW;
116672890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon            case Connection.State.RINGING:
116772890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon                return CallState.RINGING;
116872890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon        }
116972890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon        return CallState.DISCONNECTED;
117072890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon    }
11719f2bed31374a56487f370be01224baf6ce97e8adBen Gilad}
1172