Call.java revision 4a79660c984d54679ad4d2bdc89e224d9c8c375b
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
19905dfba7883666f45a0c6958d8bc6c19d68972d9Sailesh Nepalimport android.content.ComponentName;
2099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordonimport android.content.ContentUris;
2199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordonimport android.graphics.Bitmap;
2299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordonimport android.graphics.drawable.Drawable;
23ce704b9a5d9cf7db30a8c865975c70e5cbc0dc5cSailesh Nepalimport android.net.Uri;
2484fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepalimport android.os.Bundle;
25fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordonimport android.os.Handler;
2699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordonimport android.provider.ContactsContract.Contacts;
27e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepalimport android.telecomm.CallPropertyPresentation;
280b03b4b143234302f098ea18de3c32658b455ecaSantos Cordonimport android.telecomm.CallState;
29c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepalimport android.telecomm.ConnectionRequest;
3033501635c2cd21f40793041eff3b8ce3a5710d49Yorke Leeimport android.telecomm.GatewayInfo;
3198a556026109f816501fa887efdddae78d0c2d65Ihab Awadimport android.telecomm.PhoneAccount;
32ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awadimport android.telecomm.Response;
3335faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepalimport android.telecomm.StatusHints;
34766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordonimport android.telecomm.TelecommConstants;
3579ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordonimport android.telephony.DisconnectCause;
366aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepalimport android.telephony.PhoneNumberUtils;
37fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordonimport android.text.TextUtils;
380b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon
39a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chenimport com.android.internal.telecomm.ICallVideoProvider;
40fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordonimport com.android.internal.telephony.CallerInfo;
41fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordonimport com.android.internal.telephony.CallerInfoAsyncQuery;
42fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordonimport com.android.internal.telephony.CallerInfoAsyncQuery.OnQueryCompleteListener;
43ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awadimport com.android.internal.telephony.SmsApplication;
4499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordonimport com.android.telecomm.ContactsAsyncHelper.OnImageLoadCompleteListener;
4561d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordonimport com.google.common.base.Preconditions;
46ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awadimport com.google.common.collect.Sets;
4761d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
48ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awadimport java.util.Collections;
49a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordonimport java.util.LinkedList;
50a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordonimport java.util.List;
519199078322aea6df26f0d304a28a9a6d040f0717Sailesh Nepalimport java.util.Locale;
52e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepalimport java.util.Objects;
536192561b1f56d7c4e6c650e178e07ba61ad02667Ben Giladimport java.util.Set;
540407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad
552495d57b5b91f3a39529d8844a49d1be5f18b137Ben Gilad/**
562495d57b5b91f3a39529d8844a49d1be5f18b137Ben Gilad *  Encapsulates all aspects of a given phone call throughout its lifecycle, starting
572495d57b5b91f3a39529d8844a49d1be5f18b137Ben Gilad *  from the time the call intent was received by Telecomm (vs. the time the call was
582495d57b5b91f3a39529d8844a49d1be5f18b137Ben Gilad *  connected etc).
592495d57b5b91f3a39529d8844a49d1be5f18b137Ben Gilad */
60664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalfinal class Call implements CreateConnectionResponse {
61766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    /**
62766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon     * Listener for events on the call.
63766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon     */
64766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    interface Listener {
65766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon        void onSuccessfulOutgoingCall(Call call);
665a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal        void onFailedOutgoingCall(Call call, int errorCode, String errorMsg);
675a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal        void onCancelledOutgoingCall(Call call);
68c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        void onSuccessfulIncomingCall(Call call);
69766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon        void onFailedIncomingCall(Call call);
70cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad        void onRequestingRingback(Call call, boolean requestingRingback);
71352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton        void onPostDialWait(Call call, String remaining);
72e20bc974ffc24d852d09e153a280b51e0329299cSailesh Nepal        void onCallCapabilitiesChanged(Call call);
73a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        void onExpiredConferenceCall(Call call);
74a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        void onConfirmedConferenceCall(Call call);
75a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        void onParentChanged(Call call);
76a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        void onChildrenChanged(Call call);
77ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        void onCannedSmsResponsesLoaded(Call call);
78a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen        void onCallVideoProviderChanged(Call call);
7964c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        void onCallerInfoChanged(Call call);
807e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal        void onAudioModeIsVoipChanged(Call call);
8135faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal        void onStatusHintsChanged(Call call);
82e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        void onHandleChanged(Call call);
83e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        void onCallerDisplayNameChanged(Call call);
844a79660c984d54679ad4d2bdc89e224d9c8c375bAndrew Lee        void onVideoStateChanged(Call call);
8564c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon    }
8664c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon
8764c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon    abstract static class ListenerBase implements Listener {
8864c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
8964c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        public void onSuccessfulOutgoingCall(Call call) {}
9064c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
9164c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        public void onFailedOutgoingCall(Call call, int errorCode, String errorMsg) {}
9264c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
9364c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        public void onCancelledOutgoingCall(Call call) {}
9464c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
95c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        public void onSuccessfulIncomingCall(Call call) {}
9664c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
9764c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        public void onFailedIncomingCall(Call call) {}
9864c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
9964c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        public void onRequestingRingback(Call call, boolean requestingRingback) {}
10064c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
10164c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        public void onPostDialWait(Call call, String remaining) {}
10264c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
103e20bc974ffc24d852d09e153a280b51e0329299cSailesh Nepal        public void onCallCapabilitiesChanged(Call call) {}
10464c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
10564c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        public void onExpiredConferenceCall(Call call) {}
10664c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
10764c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        public void onConfirmedConferenceCall(Call call) {}
10864c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
10964c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        public void onParentChanged(Call call) {}
11064c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
11164c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        public void onChildrenChanged(Call call) {}
11264c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
11364c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        public void onCannedSmsResponsesLoaded(Call call) {}
11464c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
11564c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        public void onCallVideoProviderChanged(Call call) {}
11664c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
11764c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        public void onCallerInfoChanged(Call call) {}
1187e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal        @Override
1197e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal        public void onAudioModeIsVoipChanged(Call call) {}
12035faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal        @Override
12135faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal        public void onStatusHintsChanged(Call call) {}
122e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        @Override
123e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        public void onHandleChanged(Call call) {}
124e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        @Override
125e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        public void onCallerDisplayNameChanged(Call call) {}
1264a79660c984d54679ad4d2bdc89e224d9c8c375bAndrew Lee        @Override
1274a79660c984d54679ad4d2bdc89e224d9c8c375bAndrew Lee        public void onVideoStateChanged(Call call) {}
128766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    }
129766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon
130fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    private static final OnQueryCompleteListener sCallerInfoQueryListener =
13199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon            new OnQueryCompleteListener() {
13299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                /** ${inheritDoc} */
13399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                @Override
13499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                public void onQueryComplete(int token, Object cookie, CallerInfo callerInfo) {
13599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                    if (cookie != null) {
13699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                        ((Call) cookie).setCallerInfo(callerInfo, token);
13799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                    }
138fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon                }
13999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon            };
14099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon
14199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon    private static final OnImageLoadCompleteListener sPhotoLoadListener =
14299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon            new OnImageLoadCompleteListener() {
14399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                /** ${inheritDoc} */
14499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                @Override
14599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                public void onImageLoadComplete(
14699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                        int token, Drawable photo, Bitmap photoIcon, Object cookie) {
14799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                    if (cookie != null) {
14899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                        ((Call) cookie).setPhoto(photo, photoIcon, token);
14999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                    }
15099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                }
15199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon            };
1520407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad
153664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    private final Runnable mDirectToVoicemailRunnable = new Runnable() {
154664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        @Override
155664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        public void run() {
156664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            processDirectToVoicemail();
157664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        }
158664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    };
159664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
160810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal    /** True if this is an incoming call. */
161810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal    private final boolean mIsIncoming;
162810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal
1630407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad    /**
164664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal     * The time this call was created. Beyond logging and such, may also be used for bookkeeping
165664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal     * and specifically for marking certain call attempts as failed attempts.
1660407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad     */
1678c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal    private final long mCreationTimeMillis = System.currentTimeMillis();
1688c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal
169fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    /** The gateway information associated with this call. This stores the original call handle
170fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon     * that the user is attempting to connect to via the gateway, the actual handle to dial in
171fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon     * order to connect the call via the gateway, as well as the package name of the gateway
172fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon     * service. */
173fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    private final GatewayInfo mGatewayInfo;
174fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon
175b0ba087e1ab7b2b14032a2cb1911f3f4ede05531Sailesh Nepal    private PhoneAccount mPhoneAccount;
17677d2d0e90bc2a67d526743b8e32f920a0d755fbaNancy Chen
1772174fb56907fddf5680355e097f4425f837983e2Santos Cordon    private final Handler mHandler = new Handler();
1782174fb56907fddf5680355e097f4425f837983e2Santos Cordon
1798c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal    private long mConnectTimeMillis;
1800407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad
18161d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    /** The state of the call. */
18261d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    private CallState mState;
18361d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
18461d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    /** The handle with which to establish this call. */
185ce704b9a5d9cf7db30a8c865975c70e5cbc0dc5cSailesh Nepal    private Uri mHandle;
18661d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
187e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    /** The {@link CallPropertyPresentation} that controls how the handle is shown. */
188e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    private int mHandlePresentation;
189e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal
190e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    /** The caller display name (CNAP) set by the connection service. */
191e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    private String mCallerDisplayName;
192e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal
193e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    /** The {@link CallPropertyPresentation} that controls how the caller display name is shown. */
194e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    private int mCallerDisplayNamePresentation;
195e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal
1960407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad    /**
197c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal     * The connection service which is attempted or already connecting this call.
198681663d17b6d92b604526a54b196fa88f25b6957Santos Cordon     */
199c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal    private ConnectionServiceWrapper mConnectionService;
2006192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad
2016aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal    private boolean mIsEmergencyCall;
2026aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal
203b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati    private boolean mSpeakerphoneOn;
204b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati
205c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn    private int mVideoState;
206c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn
2076192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad    /**
20879ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon     * Disconnect cause for the call. Only valid if the state of the call is DISCONNECTED.
20979ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon     * See {@link android.telephony.DisconnectCause}.
21079ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon     */
2118c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal    private int mDisconnectCause = DisconnectCause.NOT_VALID;
21279ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon
21379ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon    /**
214c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal     * Additional disconnect information provided by the connection service.
21579ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon     */
21679ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon    private String mDisconnectMessage;
21779ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon
218c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal    /** Info used by the connection services. */
2198c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal    private Bundle mExtras = Bundle.EMPTY;
22084fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal
221766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    /** Set of listeners on this call. */
222766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    private Set<Listener> mListeners = Sets.newHashSet();
223766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon
224664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    private CreateConnectionProcessor mCreateConnectionProcessor;
225682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon
226fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    /** Caller information retrieved from the latest contact query. */
227fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    private CallerInfo mCallerInfo;
228fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon
229fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    /** The latest token used with a contact info query. */
230fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    private int mQueryToken = 0;
231fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon
232cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad    /** Whether this call is requesting that Telecomm play the ringback tone on its behalf. */
233cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad    private boolean mRequestingRingback = false;
234cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad
235c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal    /** Whether direct-to-voicemail query is pending. */
236c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal    private boolean mDirectToVoicemailQueryPending;
2372174fb56907fddf5680355e097f4425f837983e2Santos Cordon
238e20bc974ffc24d852d09e153a280b51e0329299cSailesh Nepal    private int mCallCapabilities;
239a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
240a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    private boolean mIsConference = false;
241a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
242a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    private Call mParentCall = null;
243a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
244a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    private List<Call> mChildCalls = new LinkedList<>();
245a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
246ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    /** Set of text message responses allowed for this call, if applicable. */
247ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    private List<String> mCannedSmsResponses = Collections.EMPTY_LIST;
248ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad
249ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    /** Whether an attempt has been made to load the text message responses. */
250ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    private boolean mCannedSmsResponsesLoadingStarted = false;
251ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad
252a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen    private ICallVideoProvider mCallVideoProvider;
253a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen
2547e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal    private boolean mAudioModeIsVoip;
25535faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal    private StatusHints mStatusHints;
256664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    private final ConnectionServiceRepository mRepository;
2577e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal
2588c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal    /**
2590407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad     * Persists the specified parameters and initializes the new instance.
2600407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad     *
2610407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad     * @param handle The handle to dial.
26233501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee     * @param gatewayInfo Gateway information to use for the call.
26398a556026109f816501fa887efdddae78d0c2d65Ihab Awad     * @param account Account information to use for the call.
264810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal     * @param isIncoming True if this is an incoming call.
2650407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad     */
266664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    Call(
267664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            ConnectionServiceRepository repository,
268664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            Uri handle,
269664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            GatewayInfo gatewayInfo,
270664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            PhoneAccount account,
271664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            boolean isIncoming,
272664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            boolean isConference) {
273a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        mState = isConference ? CallState.ACTIVE : CallState.NEW;
274664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        mRepository = repository;
275e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        setHandle(handle, CallPropertyPresentation.ALLOWED);
27633501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee        mGatewayInfo = gatewayInfo;
277b0ba087e1ab7b2b14032a2cb1911f3f4ede05531Sailesh Nepal        mPhoneAccount = account;
278810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal        mIsIncoming = isIncoming;
279a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        mIsConference = isConference;
280ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        maybeLoadCannedSmsResponses();
2810407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad    }
2820407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad
283766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    void addListener(Listener listener) {
284766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon        mListeners.add(listener);
285766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    }
286766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon
287766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    void removeListener(Listener listener) {
288766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon        mListeners.remove(listener);
289766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    }
290766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon
29161d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    /** {@inheritDoc} */
29261d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    @Override public String toString() {
2934538f01647fa207b41fb7e481cc180e67fd391deSailesh Nepal        String component = null;
294c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        if (mConnectionService != null && mConnectionService.getComponentName() != null) {
295c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            component = mConnectionService.getComponentName().flattenToShortString();
2964538f01647fa207b41fb7e481cc180e67fd391deSailesh Nepal        }
2974538f01647fa207b41fb7e481cc180e67fd391deSailesh Nepal        return String.format(Locale.US, "[%s, %s, %s]", mState, component, Log.piiHandle(mHandle));
29861d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    }
29961d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
3000b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon    CallState getState() {
301a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        if (mIsConference) {
302a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            if (!mChildCalls.isEmpty()) {
303a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon                // If we have child calls, just return the child call.
304a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon                return mChildCalls.get(0).getState();
305a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            }
306a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            return CallState.ACTIVE;
307a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        } else {
308a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            return mState;
309a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        }
3100b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon    }
3110b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon
3120b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon    /**
3130b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon     * Sets the call state. Although there exists the notion of appropriate state transitions
3140b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon     * (see {@link CallState}), in practice those expectations break down when cellular systems
3150b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon     * misbehave and they do this very often. The result is that we do not enforce state transitions
3160b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon     * and instead keep the code resilient to unexpected state changes.
3170b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon     */
318810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal    void setState(CallState newState) {
31979ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon        Preconditions.checkState(newState != CallState.DISCONNECTED ||
32079ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon                mDisconnectCause != DisconnectCause.NOT_VALID);
321810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal        if (mState != newState) {
322810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal            Log.v(this, "setState %s -> %s", mState, newState);
323810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal            mState = newState;
324ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            maybeLoadCannedSmsResponses();
325810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal        }
3260b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon    }
3270b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon
328cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad    void setRequestingRingback(boolean requestingRingback) {
329cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad        mRequestingRingback = requestingRingback;
330cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad        for (Listener l : mListeners) {
331cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad            l.onRequestingRingback(this, mRequestingRingback);
332cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad        }
333cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad    }
334cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad
335cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad    boolean isRequestingRingback() {
336cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad        return mRequestingRingback;
337cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad    }
338cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad
339ce704b9a5d9cf7db30a8c865975c70e5cbc0dc5cSailesh Nepal    Uri getHandle() {
3400bf5b912285e328a8f5eeec158d6caf17845b9f8Ben Gilad        return mHandle;
3410bf5b912285e328a8f5eeec158d6caf17845b9f8Ben Gilad    }
3420bf5b912285e328a8f5eeec158d6caf17845b9f8Ben Gilad
343e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    int getHandlePresentation() {
344e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        return mHandlePresentation;
345e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    }
346e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal
347e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    void setHandle(Uri handle, int presentation) {
348e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        if (!Objects.equals(handle, mHandle) || presentation != mHandlePresentation) {
349fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon            mHandle = handle;
350e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal            mHandlePresentation = presentation;
351fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon            mIsEmergencyCall = mHandle != null && PhoneNumberUtils.isLocalEmergencyNumber(
3526625545769bd9c5aa15b7e1ee9402f75ad799e81Yorke Lee                    TelecommApp.getInstance(), mHandle.getSchemeSpecificPart());
353fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon            startCallerInfoLookup();
354e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal            for (Listener l : mListeners) {
355e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal                l.onHandleChanged(this);
356e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal            }
357e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        }
358e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    }
359e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal
360e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    String getCallerDisplayName() {
361e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        return mCallerDisplayName;
362e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    }
363e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal
364e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    int getCallerDisplayNamePresentation() {
365e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        return mCallerDisplayNamePresentation;
366e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    }
367e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal
368e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    void setCallerDisplayName(String callerDisplayName, int presentation) {
369e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        if (!TextUtils.equals(callerDisplayName, mCallerDisplayName) ||
370e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal                presentation != mCallerDisplayNamePresentation) {
371e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal            mCallerDisplayName = callerDisplayName;
372e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal            mCallerDisplayNamePresentation = presentation;
373e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal            for (Listener l : mListeners) {
374e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal                l.onCallerDisplayNameChanged(this);
375e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal            }
376fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon        }
3776aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal    }
3786aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal
37999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon    String getName() {
38099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon        return mCallerInfo == null ? null : mCallerInfo.name;
38199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon    }
38299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon
38399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon    Bitmap getPhotoIcon() {
38499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon        return mCallerInfo == null ? null : mCallerInfo.cachedPhotoIcon;
38599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon    }
38699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon
38799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon    Drawable getPhoto() {
38899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon        return mCallerInfo == null ? null : mCallerInfo.cachedPhoto;
38999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon    }
39099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon
39179ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon    /**
39279ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon     * @param disconnectCause The reason for the disconnection, any of
39379ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon     *         {@link android.telephony.DisconnectCause}.
394905dfba7883666f45a0c6958d8bc6c19d68972d9Sailesh Nepal     * @param disconnectMessage Optional message about the disconnect.
39579ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon     */
39679ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon    void setDisconnectCause(int disconnectCause, String disconnectMessage) {
39779ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon        // TODO: Consider combining this method with a setDisconnected() method that is totally
39879ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon        // separate from setState.
39979ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon        mDisconnectCause = disconnectCause;
40079ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon        mDisconnectMessage = disconnectMessage;
40179ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon    }
40279ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon
40379ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon    int getDisconnectCause() {
40479ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon        return mDisconnectCause;
40579ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon    }
40679ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon
40779ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon    String getDisconnectMessage() {
40879ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon        return mDisconnectMessage;
40979ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon    }
41079ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon
4116aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal    boolean isEmergencyCall() {
4126aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal        return mIsEmergencyCall;
41361d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    }
41461d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
41533501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee    /**
41633501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee     * @return The original handle this call is associated with. In-call services should use this
41733501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee     * handle when indicating in their UI the handle that is being called.
41833501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee     */
41933501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee    public Uri getOriginalHandle() {
42033501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee        if (mGatewayInfo != null && !mGatewayInfo.isEmpty()) {
42133501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee            return mGatewayInfo.getOriginalHandle();
42233501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee        }
42333501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee        return getHandle();
42433501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee    }
42533501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee
42633501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee    GatewayInfo getGatewayInfo() {
42733501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee        return mGatewayInfo;
42833501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee    }
42933501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee
430b0ba087e1ab7b2b14032a2cb1911f3f4ede05531Sailesh Nepal    PhoneAccount getPhoneAccount() {
431b0ba087e1ab7b2b14032a2cb1911f3f4ede05531Sailesh Nepal        return mPhoneAccount;
43277d2d0e90bc2a67d526743b8e32f920a0d755fbaNancy Chen    }
43377d2d0e90bc2a67d526743b8e32f920a0d755fbaNancy Chen
434810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal    boolean isIncoming() {
435810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal        return mIsIncoming;
436810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal    }
437810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal
4380407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad    /**
4390407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad     * @return The "age" of this call object in milliseconds, which typically also represents the
4408c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal     *     period since this call was added to the set pending outgoing calls, see
4418c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal     *     mCreationTimeMillis.
4420407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad     */
4438c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal    long getAgeMillis() {
4448c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal        return System.currentTimeMillis() - mCreationTimeMillis;
4450407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad    }
4460b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon
447f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    /**
448f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * @return The time when this call object was created and added to the set of pending outgoing
449f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     *     calls.
450f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     */
4518c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal    long getCreationTimeMillis() {
4528c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal        return mCreationTimeMillis;
4538c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal    }
4548c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal
4558c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal    long getConnectTimeMillis() {
4568c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal        return mConnectTimeMillis;
4578c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal    }
4588c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal
4598c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal    void setConnectTimeMillis(long connectTimeMillis) {
4608c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal        mConnectTimeMillis = connectTimeMillis;
461f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    }
462f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee
463e20bc974ffc24d852d09e153a280b51e0329299cSailesh Nepal    int getCallCapabilities() {
464e20bc974ffc24d852d09e153a280b51e0329299cSailesh Nepal        return mCallCapabilities;
465a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    }
466a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
467e20bc974ffc24d852d09e153a280b51e0329299cSailesh Nepal    void setCallCapabilities(int callCapabilities) {
468e20bc974ffc24d852d09e153a280b51e0329299cSailesh Nepal        if (mCallCapabilities != callCapabilities) {
469e20bc974ffc24d852d09e153a280b51e0329299cSailesh Nepal            mCallCapabilities = callCapabilities;
470a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            for (Listener l : mListeners) {
471e20bc974ffc24d852d09e153a280b51e0329299cSailesh Nepal                l.onCallCapabilitiesChanged(this);
472a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            }
473a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        }
474a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    }
475a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
476a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    Call getParentCall() {
477a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        return mParentCall;
478a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    }
479a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
480a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    List<Call> getChildCalls() {
481a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        return mChildCalls;
482a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    }
483a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
484c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal    ConnectionServiceWrapper getConnectionService() {
485c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        return mConnectionService;
486681663d17b6d92b604526a54b196fa88f25b6957Santos Cordon    }
487681663d17b6d92b604526a54b196fa88f25b6957Santos Cordon
488c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal    void setConnectionService(ConnectionServiceWrapper service) {
489c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        Preconditions.checkNotNull(service);
4908e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad
491c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        clearConnectionService();
4928e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad
493c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        service.incrementAssociatedCallCount();
494c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        mConnectionService = service;
495c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        mConnectionService.addCall(this);
496681663d17b6d92b604526a54b196fa88f25b6957Santos Cordon    }
497681663d17b6d92b604526a54b196fa88f25b6957Santos Cordon
498681663d17b6d92b604526a54b196fa88f25b6957Santos Cordon    /**
499c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal     * Clears the associated connection service.
500681663d17b6d92b604526a54b196fa88f25b6957Santos Cordon     */
501c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal    void clearConnectionService() {
502c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        if (mConnectionService != null) {
503c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            ConnectionServiceWrapper serviceTemp = mConnectionService;
504c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            mConnectionService = null;
505c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            serviceTemp.removeCall(this);
506c499c1c0758dcb4b02048df96e7405994660ab3fSantos Cordon
507c499c1c0758dcb4b02048df96e7405994660ab3fSantos Cordon            // Decrementing the count can cause the service to unbind, which itself can trigger the
508c499c1c0758dcb4b02048df96e7405994660ab3fSantos Cordon            // service-death code.  Since the service death code tries to clean up any associated
509c499c1c0758dcb4b02048df96e7405994660ab3fSantos Cordon            // calls, we need to make sure to remove that information (e.g., removeCall()) before
510c499c1c0758dcb4b02048df96e7405994660ab3fSantos Cordon            // we decrement. Technically, invoking removeCall() prior to decrementing is all that is
511c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            // necessary, but cleaning up mConnectionService prior to triggering an unbind is good
512c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            // to do.
513c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            decrementAssociatedCallCount(serviceTemp);
514adee12dd6b3e85ce3ae419329226c9aa72c184fcYorke Lee        }
5158e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad    }
5168e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad
517664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    private void processDirectToVoicemail() {
518c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        if (mDirectToVoicemailQueryPending) {
5192174fb56907fddf5680355e097f4425f837983e2Santos Cordon            if (mCallerInfo != null && mCallerInfo.shouldSendToVoicemail) {
5202174fb56907fddf5680355e097f4425f837983e2Santos Cordon                Log.i(this, "Directing call to voicemail: %s.", this);
5212174fb56907fddf5680355e097f4425f837983e2Santos Cordon                // TODO(santoscordon): Once we move State handling from CallsManager to Call, we
5222174fb56907fddf5680355e097f4425f837983e2Santos Cordon                // will not need to set RINGING state prior to calling reject.
5232174fb56907fddf5680355e097f4425f837983e2Santos Cordon                setState(CallState.RINGING);
524ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                reject(false, null);
5252174fb56907fddf5680355e097f4425f837983e2Santos Cordon            } else {
5262174fb56907fddf5680355e097f4425f837983e2Santos Cordon                // TODO(santoscordon): Make this class (not CallsManager) responsible for changing
5272174fb56907fddf5680355e097f4425f837983e2Santos Cordon                // the call state to RINGING.
5282174fb56907fddf5680355e097f4425f837983e2Santos Cordon
5292174fb56907fddf5680355e097f4425f837983e2Santos Cordon                // TODO(santoscordon): Replace this with state transition to RINGING.
5302174fb56907fddf5680355e097f4425f837983e2Santos Cordon                for (Listener l : mListeners) {
531c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal                    l.onSuccessfulIncomingCall(this);
5322174fb56907fddf5680355e097f4425f837983e2Santos Cordon                }
5332174fb56907fddf5680355e097f4425f837983e2Santos Cordon            }
534766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon
535c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            mDirectToVoicemailQueryPending = false;
536766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon        }
537766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    }
538766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon
539766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    /**
540664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal     * Starts the create connection sequence. Upon completion, there should exist an active
541664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal     * connection through a connection service (or the call will have failed).
542766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon     */
543664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    void startCreateConnection() {
544664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        Preconditions.checkState(mCreateConnectionProcessor == null);
545664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        mCreateConnectionProcessor = new CreateConnectionProcessor(this, mRepository, this);
546664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        mCreateConnectionProcessor.process();
547766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    }
548766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon
5495a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal    @Override
550664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    public void handleCreateConnectionSuccessful(ConnectionRequest request) {
551664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        mCreateConnectionProcessor = null;
552664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        mPhoneAccount = request.getAccount();
553664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
554664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        if (mIsIncoming) {
555664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            // We do not handle incoming calls immediately when they are verified by the connection
556664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            // service. We allow the caller-info-query code to execute first so that we can read the
557664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            // direct-to-voicemail property before deciding if we want to show the incoming call to
558664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            // the user or if we want to reject the call.
559664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            mDirectToVoicemailQueryPending = true;
560664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
561664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            // Setting the handle triggers the caller info lookup code.
562664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            setHandle(request.getHandle(), request.getHandlePresentation());
563664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
564664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            // Timeout the direct-to-voicemail lookup execution so that we dont wait too long before
565664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            // showing the user the incoming call screen.
566664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            mHandler.postDelayed(mDirectToVoicemailRunnable, Timeouts.getDirectToVoicemailMillis());
567664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        } else {
568664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            for (Listener l : mListeners) {
569664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal                l.onSuccessfulOutgoingCall(this);
570664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            }
571766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon        }
5725a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal    }
5735a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal
5745a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal    @Override
575664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    public void handleCreateConnectionFailed(int code, String msg) {
576664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        mCreateConnectionProcessor = null;
577664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        if (mIsIncoming) {
578664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            clearConnectionService();
579664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            setDisconnectCause(code, null);
580664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            setState(CallState.DISCONNECTED);
581664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
582664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
583664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            for (int i = 0; i < listeners.length; i++) {
584664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal                listeners[i].onFailedIncomingCall(this);
585664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            }
586664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        } else {
587664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
588664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            for (int i = 0; i < listeners.length; i++) {
589664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal                listeners[i].onFailedOutgoingCall(this, code, msg);
590664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            }
591664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            clearConnectionService();
5925a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal        }
593766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    }
594766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon
5955a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal    @Override
596664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    public void handleCreateConnectionCancelled() {
597664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        mCreateConnectionProcessor = null;
598664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        if (mIsIncoming) {
599664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            clearConnectionService();
600664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            setDisconnectCause(DisconnectCause.ERROR_UNSPECIFIED, null);
601664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            setState(CallState.DISCONNECTED);
602664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
603664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
604664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            for (int i = 0; i < listeners.length; i++) {
605664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal                listeners[i].onFailedIncomingCall(this);
606664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            }
607664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        } else {
608664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
609664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            for (int i = 0; i < listeners.length; i++) {
610664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal                listeners[i].onCancelledOutgoingCall(this);
611664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            }
612664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            clearConnectionService();
613766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon        }
614766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    }
615766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon
616766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    /**
61774549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad     * Plays the specified DTMF tone.
61874549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad     */
61974549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad    void playDtmfTone(char digit) {
620c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        if (mConnectionService == null) {
621c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            Log.w(this, "playDtmfTone() request on a call without a connection service.");
62274549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad        } else {
623c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            Log.i(this, "Send playDtmfTone to connection service for call %s", this);
624c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            mConnectionService.playDtmfTone(this, digit);
62574549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad        }
62674549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad    }
62774549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad
62874549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad    /**
62974549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad     * Stops playing any currently playing DTMF tone.
63074549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad     */
63174549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad    void stopDtmfTone() {
632c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        if (mConnectionService == null) {
633c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            Log.w(this, "stopDtmfTone() request on a call without a connectino service.");
63474549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad        } else {
635c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            Log.i(this, "Send stopDtmfTone to connection service for call %s", this);
636c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            mConnectionService.stopDtmfTone(this);
63774549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad        }
63874549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad    }
63974549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad
64074549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad    /**
641c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal     * Attempts to disconnect the call through the connection service.
642049b7b6a8d0cf44d687d827cb57a18fa23358206Santos Cordon     */
643049b7b6a8d0cf44d687d827cb57a18fa23358206Santos Cordon    void disconnect() {
644766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon        if (mState == CallState.NEW) {
645682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon            Log.v(this, "Aborting call %s", this);
646682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon            abort();
64774d420be72fa30735fe9b7a25715f6db046c0398Santos Cordon        } else if (mState != CallState.ABORTED && mState != CallState.DISCONNECTED) {
648c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            Preconditions.checkNotNull(mConnectionService);
649766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon
650c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            Log.i(this, "Send disconnect to connection service for call: %s", this);
651c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            // The call isn't officially disconnected until the connection service confirms that the
652c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            // call was actually disconnected. Only then is the association between call and
653c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            // connection service severed, see {@link CallsManager#markCallAsDisconnected}.
654c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            mConnectionService.disconnect(this);
655049b7b6a8d0cf44d687d827cb57a18fa23358206Santos Cordon        }
656049b7b6a8d0cf44d687d827cb57a18fa23358206Santos Cordon    }
657049b7b6a8d0cf44d687d827cb57a18fa23358206Santos Cordon
658682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon    void abort() {
659664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        if (mCreateConnectionProcessor != null) {
660664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            mCreateConnectionProcessor.abort();
661682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon        }
662682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon    }
663682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon
6640b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon    /**
66561d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon     * Answers the call if it is ringing.
66661d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon     */
66761d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    void answer() {
668c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        Preconditions.checkNotNull(mConnectionService);
66961d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
67061d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon        // Check to verify that the call is still in the ringing state. A call can change states
67161d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon        // between the time the user hits 'answer' and Telecomm receives the command.
67261d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon        if (isRinging("answer")) {
673c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            // At this point, we are asking the connection service to answer but we don't assume
674c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            // that it will work. Instead, we wait until confirmation from the connectino service
675c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            // that the call is in a non-RINGING state before changing the UI. See
676c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            // {@link ConnectionServiceAdapter#setActive} and other set* methods.
677c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            mConnectionService.answer(this);
67861d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon        }
67961d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    }
68061d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
68161d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    /**
68261d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon     * Rejects the call if it is ringing.
683ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     *
684ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * @param rejectWithMessage Whether to send a text message as part of the call rejection.
685ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * @param textMessage An optional text message to send as part of the rejection.
68661d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon     */
687ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    void reject(boolean rejectWithMessage, String textMessage) {
688c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        Preconditions.checkNotNull(mConnectionService);
68961d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
69061d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon        // Check to verify that the call is still in the ringing state. A call can change states
69161d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon        // between the time the user hits 'reject' and Telecomm receives the command.
69261d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon        if (isRinging("reject")) {
693c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            mConnectionService.reject(this);
69461d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon        }
69561d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    }
69661d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
69761d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    /**
698cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee     * Puts the call on hold if it is currently active.
699cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee     */
700cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee    void hold() {
701c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        Preconditions.checkNotNull(mConnectionService);
702cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee
703cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee        if (mState == CallState.ACTIVE) {
704c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            mConnectionService.hold(this);
705cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee        }
706cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee    }
707cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee
708cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee    /**
709cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee     * Releases the call from hold if it is currently active.
710cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee     */
711cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee    void unhold() {
712c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        Preconditions.checkNotNull(mConnectionService);
713cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee
714cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee        if (mState == CallState.ON_HOLD) {
715c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            mConnectionService.unhold(this);
716571f0737002251f09b9ef696dc8b4c9ce02abbaeSantos Cordon        }
7170b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon    }
7180b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon
7196aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal    /** Checks if this is a live call or not. */
7206aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal    boolean isAlive() {
7216aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal        switch (mState) {
7226aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal            case NEW:
7236aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal            case RINGING:
7246aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal            case DISCONNECTED:
7256aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal            case ABORTED:
7266aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal                return false;
7276aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal            default:
7286aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal                return true;
7296aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal        }
7306aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal    }
7316aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal
73240f78c210512570f14cdfde9613dd85c510a1c0cSantos Cordon    boolean isActive() {
73384bfe47a2447c4983bcc58468000f04683eec55bIhab Awad        return mState == CallState.ACTIVE;
73440f78c210512570f14cdfde9613dd85c510a1c0cSantos Cordon    }
73540f78c210512570f14cdfde9613dd85c510a1c0cSantos Cordon
73684fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal    Bundle getExtras() {
73784fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal        return mExtras;
73884fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal    }
73984fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal
74084fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal    void setExtras(Bundle extras) {
74184fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal        mExtras = extras;
74284fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal    }
74384fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal
7445ba7f27491e287f39a999ddd3d1ed6a7bad78272Santos Cordon    Uri getRingtone() {
7455ba7f27491e287f39a999ddd3d1ed6a7bad78272Santos Cordon        return mCallerInfo == null ? null : mCallerInfo.contactRingtoneUri;
7465ba7f27491e287f39a999ddd3d1ed6a7bad78272Santos Cordon    }
7475ba7f27491e287f39a999ddd3d1ed6a7bad78272Santos Cordon
748352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton    void onPostDialWait(String remaining) {
749352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton        for (Listener l : mListeners) {
750352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton            l.onPostDialWait(this, remaining);
751352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton        }
752352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton    }
753352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton
754352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton    void postDialContinue(boolean proceed) {
755c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        mConnectionService.onPostDialContinue(this, proceed);
756352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton    }
757352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton
75877da19ea28b8753d439660b4352c1bf914f63a92Sailesh Nepal    void phoneAccountClicked() {
759c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        mConnectionService.onPhoneAccountClicked(this);
76077da19ea28b8753d439660b4352c1bf914f63a92Sailesh Nepal    }
76177da19ea28b8753d439660b4352c1bf914f63a92Sailesh Nepal
762a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    void conferenceInto(Call conferenceCall) {
763c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        if (mConnectionService == null) {
764c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            Log.w(this, "conference requested on a call without a connection service.");
765a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        } else {
766c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            mConnectionService.conference(conferenceCall, this);
767a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        }
768a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    }
769a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
770a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    void expireConference() {
771a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        // The conference call expired before we got a confirmation of the conference from the
772c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        // connection service...so start shutting down.
773c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        clearConnectionService();
774a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        for (Listener l : mListeners) {
775a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            l.onExpiredConferenceCall(this);
776a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        }
777a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    }
778a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
779a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    void confirmConference() {
780a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        Log.v(this, "confirming Conf call %s", mListeners);
781a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        for (Listener l : mListeners) {
782a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            l.onConfirmedConferenceCall(this);
783a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        }
784a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    }
785a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
786a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    void splitFromConference() {
787a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        // TODO(santoscordon): todo
788a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    }
789a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
790e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    void swapWithBackgroundCall() {
791e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        mConnectionService.swapWithBackgroundCall(this);
792e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    }
793e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal
794a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    void setParentCall(Call parentCall) {
795a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        if (parentCall == this) {
796a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            Log.e(this, new Exception(), "setting the parent to self");
797a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            return;
798a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        }
799a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        Preconditions.checkState(parentCall == null || mParentCall == null);
800a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
801a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        Call oldParent = mParentCall;
802a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        if (mParentCall != null) {
803a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            mParentCall.removeChildCall(this);
804a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        }
805a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        mParentCall = parentCall;
806a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        if (mParentCall != null) {
807a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            mParentCall.addChildCall(this);
808a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        }
809a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
810a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        for (Listener l : mListeners) {
811a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            l.onParentChanged(this);
812a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        }
813a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    }
814a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
815a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    private void addChildCall(Call call) {
816a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        if (!mChildCalls.contains(call)) {
817a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            mChildCalls.add(call);
818a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
819a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            for (Listener l : mListeners) {
820a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon                l.onChildrenChanged(this);
821a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            }
822a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        }
823a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    }
824a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
825a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    private void removeChildCall(Call call) {
826a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        if (mChildCalls.remove(call)) {
827a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            for (Listener l : mListeners) {
828a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon                l.onChildrenChanged(this);
829a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            }
830a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        }
831a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    }
832a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
8330b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon    /**
834ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * Return whether the user can respond to this {@code Call} via an SMS message.
835ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     *
836ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * @return true if the "Respond via SMS" feature should be enabled
837ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * for this incoming call.
838ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     *
839ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * The general rule is that we *do* allow "Respond via SMS" except for
840ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * the few (relatively rare) cases where we know for sure it won't
841ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * work, namely:
842ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     *   - a bogus or blank incoming number
843ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     *   - a call from a SIP address
844ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     *   - a "call presentation" that doesn't allow the number to be revealed
845ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     *
846ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * In all other cases, we allow the user to respond via SMS.
847ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     *
848ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * Note that this behavior isn't perfect; for example we have no way
849ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * to detect whether the incoming call is from a landline (with most
850ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * networks at least), so we still enable this feature even though
851ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * SMSes to that number will silently fail.
852ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     */
853ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    boolean isRespondViaSmsCapable() {
854ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        if (mState != CallState.RINGING) {
855ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            return false;
856ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        }
857ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad
858ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        if (getHandle() == null) {
859ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            // No incoming number known or call presentation is "PRESENTATION_RESTRICTED", in
860ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            // other words, the user should not be able to see the incoming phone number.
861ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            return false;
862ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        }
863ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad
864ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        if (PhoneNumberUtils.isUriNumber(getHandle().toString())) {
865ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            // The incoming number is actually a URI (i.e. a SIP address),
866ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            // not a regular PSTN phone number, and we can't send SMSes to
867ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            // SIP addresses.
868ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            // (TODO: That might still be possible eventually, though. Is
869ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            // there some SIP-specific equivalent to sending a text message?)
870ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            return false;
871ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        }
872ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad
873ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        // Is there a valid SMS application on the phone?
874ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        if (SmsApplication.getDefaultRespondViaMessageApplication(TelecommApp.getInstance(),
875ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                true /*updateIfNeeded*/) == null) {
876ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            return false;
877ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        }
878ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad
879ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        // TODO: with some carriers (in certain countries) you *can* actually
880ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        // tell whether a given number is a mobile phone or not. So in that
881ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        // case we could potentially return false here if the incoming call is
882ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        // from a land line.
883ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad
884ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        // If none of the above special cases apply, it's OK to enable the
885ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        // "Respond via SMS" feature.
886ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        return true;
887ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    }
888ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad
889ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    List<String> getCannedSmsResponses() {
890ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        return mCannedSmsResponses;
891ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    }
892ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad
893ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    /**
89461d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon     * @return True if the call is ringing, else logs the action name.
89561d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon     */
89661d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    private boolean isRinging(String actionName) {
89761d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon        if (mState == CallState.RINGING) {
89861d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon            return true;
89961d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon        }
90061d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
901f1c191d3974fed3f57680c63571ae0212c4622e7Sailesh Nepal        Log.i(this, "Request to %s a non-ringing call %s", actionName, this);
90261d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon        return false;
90361d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    }
90461d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
9058e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad    @SuppressWarnings("rawtypes")
9068e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad    private void decrementAssociatedCallCount(ServiceBinder binder) {
9078e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad        if (binder != null) {
9088e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad            binder.decrementAssociatedCallCount();
9098e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad        }
9108e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad    }
911fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon
912fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    /**
913fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon     * Looks up contact information based on the current handle.
914fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon     */
915fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    private void startCallerInfoLookup() {
916fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon        String number = mHandle == null ? null : mHandle.getSchemeSpecificPart();
917fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon
918fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon        mQueryToken++;  // Updated so that previous queries can no longer set the information.
919fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon        mCallerInfo = null;
920fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon        if (!TextUtils.isEmpty(number)) {
9215ba7f27491e287f39a999ddd3d1ed6a7bad78272Santos Cordon            Log.v(this, "Looking up information for: %s.", Log.piiHandle(number));
922fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon            CallerInfoAsyncQuery.startQuery(
923fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon                    mQueryToken,
924fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon                    TelecommApp.getInstance(),
925fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon                    number,
926fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon                    sCallerInfoQueryListener,
927fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon                    this);
928fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon        }
929fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    }
930fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon
931fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    /**
93299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon     * Saves the specified caller info if the specified token matches that of the last query
933fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon     * that was made.
934fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon     *
935fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon     * @param callerInfo The new caller information to set.
936fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon     * @param token The token used with this query.
937fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon     */
938fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    private void setCallerInfo(CallerInfo callerInfo, int token) {
93999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon        Preconditions.checkNotNull(callerInfo);
94099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon
941fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon        if (mQueryToken == token) {
942fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon            mCallerInfo = callerInfo;
9435ba7f27491e287f39a999ddd3d1ed6a7bad78272Santos Cordon            Log.i(this, "CallerInfo received for %s: %s", Log.piiHandle(mHandle), callerInfo);
94499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon
945a1662d0ae89d9fb514a5ac68cbc76660e34dae00Makoto Onuki            if (mCallerInfo.contactDisplayPhotoUri != null) {
946a1662d0ae89d9fb514a5ac68cbc76660e34dae00Makoto Onuki                Log.d(this, "Searching person uri %s for call %s",
947a1662d0ae89d9fb514a5ac68cbc76660e34dae00Makoto Onuki                        mCallerInfo.contactDisplayPhotoUri, this);
94899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                ContactsAsyncHelper.startObtainPhotoAsync(
94999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                        token,
95099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                        TelecommApp.getInstance(),
951a1662d0ae89d9fb514a5ac68cbc76660e34dae00Makoto Onuki                        mCallerInfo.contactDisplayPhotoUri,
95299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                        sPhotoLoadListener,
95399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                        this);
954a1662d0ae89d9fb514a5ac68cbc76660e34dae00Makoto Onuki                // Do not call onCallerInfoChanged yet in this case.  We call it in setPhoto().
95564c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon            } else {
95664c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon                for (Listener l : mListeners) {
95764c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon                    l.onCallerInfoChanged(this);
95864c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon                }
95999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon            }
9602174fb56907fddf5680355e097f4425f837983e2Santos Cordon
9612174fb56907fddf5680355e097f4425f837983e2Santos Cordon            processDirectToVoicemail();
96299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon        }
96399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon    }
96499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon
9656f3f7affb13e93cb70868d3114f02f1ed593194eYorke Lee    CallerInfo getCallerInfo() {
9666f3f7affb13e93cb70868d3114f02f1ed593194eYorke Lee        return mCallerInfo;
9676f3f7affb13e93cb70868d3114f02f1ed593194eYorke Lee    }
9686f3f7affb13e93cb70868d3114f02f1ed593194eYorke Lee
96999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon    /**
97099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon     * Saves the specified photo information if the specified token matches that of the last query.
97199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon     *
97299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon     * @param photo The photo as a drawable.
97399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon     * @param photoIcon The photo as a small icon.
97499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon     * @param token The token used with this query.
97599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon     */
97699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon    private void setPhoto(Drawable photo, Bitmap photoIcon, int token) {
97799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon        if (mQueryToken == token) {
97899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon            mCallerInfo.cachedPhoto = photo;
97999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon            mCallerInfo.cachedPhotoIcon = photoIcon;
98064c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon
98164c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon            for (Listener l : mListeners) {
98264c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon                l.onCallerInfoChanged(this);
98364c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon            }
984fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon        }
985fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    }
986ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad
987ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    private void maybeLoadCannedSmsResponses() {
988ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        if (mIsIncoming && isRespondViaSmsCapable() && !mCannedSmsResponsesLoadingStarted) {
989ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            Log.d(this, "maybeLoadCannedSmsResponses: starting task to load messages");
990ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            mCannedSmsResponsesLoadingStarted = true;
991ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            RespondViaSmsManager.getInstance().loadCannedTextMessages(
992ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                    new Response<Void, List<String>>() {
993ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                        @Override
994ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                        public void onResult(Void request, List<String>... result) {
995ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                            if (result.length > 0) {
996ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                                Log.d(this, "maybeLoadCannedSmsResponses: got %s", result[0]);
997ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                                mCannedSmsResponses = result[0];
998ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                                for (Listener l : mListeners) {
999ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                                    l.onCannedSmsResponsesLoaded(Call.this);
1000ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                                }
1001ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                            }
1002ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                        }
1003ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad
1004ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                        @Override
1005ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                        public void onError(Void request, int code, String msg) {
1006ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                            Log.w(Call.this, "Error obtaining canned SMS responses: %d %s", code,
1007ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                                    msg);
1008ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                        }
1009ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                    }
1010ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            );
1011ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        } else {
1012ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            Log.d(this, "maybeLoadCannedSmsResponses: doing nothing");
1013ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        }
1014ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    }
1015b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati
1016b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati    /**
1017b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati     * Sets speakerphone option on when call begins.
1018b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati     */
1019b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati    public void setStartWithSpeakerphoneOn(boolean startWithSpeakerphone) {
1020b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati        mSpeakerphoneOn = startWithSpeakerphone;
1021b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati    }
1022b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati
1023b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati    /**
1024b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati     * Returns speakerphone option.
1025b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati     *
1026b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati     * @return Whether or not speakerphone should be set automatically when call begins.
1027b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati     */
1028b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati    public boolean getStartWithSpeakerphoneOn() {
1029b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati        return mSpeakerphoneOn;
1030b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati    }
1031e9a776560dfe6f000cfc0dc1ea36c0f37d937f53Andrew Lee
1032e9a776560dfe6f000cfc0dc1ea36c0f37d937f53Andrew Lee    /**
1033e9a776560dfe6f000cfc0dc1ea36c0f37d937f53Andrew Lee     * Sets a call video provider for the call.
1034e9a776560dfe6f000cfc0dc1ea36c0f37d937f53Andrew Lee     */
1035a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen    public void setCallVideoProvider(ICallVideoProvider callVideoProvider) {
1036a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen        mCallVideoProvider = callVideoProvider;
1037a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen        for (Listener l : mListeners) {
1038a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen            l.onCallVideoProviderChanged(Call.this);
1039a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen        }
1040a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen    }
1041a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen
1042a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen    /**
1043a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen     * @return Return the call video Provider binder.
1044a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen     */
1045a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen    public ICallVideoProvider getCallVideoProvider() {
1046a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen        return mCallVideoProvider;
1047e9a776560dfe6f000cfc0dc1ea36c0f37d937f53Andrew Lee    }
1048e19cc005ddbff5313d6f7288587630b2410d005cTyler Gunn
1049e19cc005ddbff5313d6f7288587630b2410d005cTyler Gunn    /**
1050c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn     * The current video state for the call.
1051c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn     * Valid values: {@link android.telecomm.VideoCallProfile#VIDEO_STATE_AUDIO_ONLY},
1052c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn     * {@link android.telecomm.VideoCallProfile#VIDEO_STATE_BIDIRECTIONAL},
1053c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn     * {@link android.telecomm.VideoCallProfile#VIDEO_STATE_TX_ENABLED},
1054c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn     * {@link android.telecomm.VideoCallProfile#VIDEO_STATE_RX_ENABLED}.
1055c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn     *
1056c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn     * @return True if video is enabled.
1057c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn     */
1058c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn    public int getVideoState() {
1059c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn        return mVideoState;
1060c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn    }
1061c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn
1062c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn    /**
1063c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn     * At the start of the call, determines the desired video state for the call.
1064c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn     * Valid values: {@link android.telecomm.VideoCallProfile#VIDEO_STATE_AUDIO_ONLY},
1065c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn     * {@link android.telecomm.VideoCallProfile#VIDEO_STATE_BIDIRECTIONAL},
1066c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn     * {@link android.telecomm.VideoCallProfile#VIDEO_STATE_TX_ENABLED},
1067c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn     * {@link android.telecomm.VideoCallProfile#VIDEO_STATE_RX_ENABLED}.
1068c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn     *
1069c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn     * @param videoState The desired video state for the call.
1070c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn     */
1071c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn    public void setVideoState(int videoState) {
1072c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn        mVideoState = videoState;
10734a79660c984d54679ad4d2bdc89e224d9c8c375bAndrew Lee        for (Listener l : mListeners) {
10744a79660c984d54679ad4d2bdc89e224d9c8c375bAndrew Lee            l.onVideoStateChanged(this);
10754a79660c984d54679ad4d2bdc89e224d9c8c375bAndrew Lee        }
1076c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn    }
10777e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal
10787e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal    public boolean getAudioModeIsVoip() {
10797e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal        return mAudioModeIsVoip;
10807e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal    }
10817e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal
10827e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal    public void setAudioModeIsVoip(boolean audioModeIsVoip) {
10837e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal        mAudioModeIsVoip = audioModeIsVoip;
10847e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal        for (Listener l : mListeners) {
108535faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal            l.onAudioModeIsVoipChanged(this);
108635faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal        }
108735faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal    }
108835faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal
108935faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal    public StatusHints getStatusHints() {
109035faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal        return mStatusHints;
109135faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal    }
109235faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal
109335faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal    public void setStatusHints(StatusHints statusHints) {
109435faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal        mStatusHints = statusHints;
109535faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal        for (Listener l : mListeners) {
109635faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal            l.onStatusHintsChanged(this);
10977e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal        }
10987e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal    }
10999f2bed31374a56487f370be01224baf6ce97e8adBen Gilad}
1100