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
177cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnpackage com.android.server.telecom;
189f2bed31374a56487f370be01224baf6ce97e8adBen Gilad
1991d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunnimport android.content.Context;
2099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordonimport android.graphics.Bitmap;
2199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordonimport android.graphics.drawable.Drawable;
22ce704b9a5d9cf7db30a8c865975c70e5cbc0dc5cSailesh Nepalimport android.net.Uri;
2384fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepalimport android.os.Bundle;
24fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordonimport android.os.Handler;
25e4a9c412f5c6f76f006659f0b4e171ef4547dc45Yorke Leeimport android.os.Trace;
268a736a887b50d4d042c008b2073e24e1b4681dfbYorke Leeimport android.provider.ContactsContract.Contacts;
277cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.CallState;
28701dc006ac11625b55d872f1639107b028933895Andrew Leeimport android.telecom.DisconnectCause;
297cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.Connection;
307cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.GatewayInfo;
317cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.ParcelableConnection;
327cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.PhoneAccount;
337cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.PhoneAccountHandle;
347cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.Response;
357cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.StatusHints;
367cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.TelecomManager;
377cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.VideoProfile;
386aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepalimport android.telephony.PhoneNumberUtils;
39fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordonimport android.text.TextUtils;
400b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon
417cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport com.android.internal.telecom.IVideoProvider;
42fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordonimport com.android.internal.telephony.CallerInfo;
43fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordonimport com.android.internal.telephony.CallerInfoAsyncQuery;
44fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordonimport com.android.internal.telephony.CallerInfoAsyncQuery.OnQueryCompleteListener;
45ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awadimport com.android.internal.telephony.SmsApplication;
467cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport com.android.server.telecom.ContactsAsyncHelper.OnImageLoadCompleteListener;
4791d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunnimport com.android.internal.util.Preconditions;
4861d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
4912d61825cd0d6aa06272db3f77b5e30dce379951Santos Cordonimport java.util.ArrayList;
50ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awadimport java.util.Collections;
51a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordonimport java.util.LinkedList;
52a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordonimport java.util.List;
539199078322aea6df26f0d304a28a9a6d040f0717Sailesh Nepalimport java.util.Locale;
54e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepalimport java.util.Objects;
556192561b1f56d7c4e6c650e178e07ba61ad02667Ben Giladimport java.util.Set;
56a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shraunerimport java.util.concurrent.ConcurrentHashMap;
570407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad
582495d57b5b91f3a39529d8844a49d1be5f18b137Ben Gilad/**
592495d57b5b91f3a39529d8844a49d1be5f18b137Ben Gilad *  Encapsulates all aspects of a given phone call throughout its lifecycle, starting
607cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunn *  from the time the call intent was received by Telecom (vs. the time the call was
612495d57b5b91f3a39529d8844a49d1be5f18b137Ben Gilad *  connected etc).
622495d57b5b91f3a39529d8844a49d1be5f18b137Ben Gilad */
63664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepalfinal class Call implements CreateConnectionResponse {
64766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    /**
65766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon     * Listener for events on the call.
66766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon     */
67766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    interface Listener {
686fb37c87836b5245046bd3b14320823ab839a10cIhab Awad        void onSuccessfulOutgoingCall(Call call, int callState);
69701dc006ac11625b55d872f1639107b028933895Andrew Lee        void onFailedOutgoingCall(Call call, DisconnectCause disconnectCause);
70c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        void onSuccessfulIncomingCall(Call call);
71766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon        void onFailedIncomingCall(Call call);
729250e5fa9987c3ab80e11e1955657055f5866539Yorke Lee        void onSuccessfulUnknownCall(Call call, int callState);
739250e5fa9987c3ab80e11e1955657055f5866539Yorke Lee        void onFailedUnknownCall(Call call);
745be64bc46c23b614d5452ca398a6bb7a512f1887Andrew Lee        void onRingbackRequested(Call call, boolean ringbackRequested);
75352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton        void onPostDialWait(Call call, String remaining);
76a469f76c1710a945933910840f11f9fda0445d82Nancy Chen        void onPostDialChar(Call call, char nextChar);
7707bc5ee853bc9a0b4cd46e0c702888b2c7989392Ihab Awad        void onConnectionCapabilitiesChanged(Call call);
78a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        void onParentChanged(Call call);
79a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        void onChildrenChanged(Call call);
80ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        void onCannedSmsResponsesLoaded(Call call);
813bcf935b25470e94c8c6855862434d15b785c54aAndrew Lee        void onVideoCallProviderChanged(Call call);
8264c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        void onCallerInfoChanged(Call call);
835be64bc46c23b614d5452ca398a6bb7a512f1887Andrew Lee        void onIsVoipAudioModeChanged(Call call);
8435faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal        void onStatusHintsChanged(Call call);
85e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        void onHandleChanged(Call call);
86e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        void onCallerDisplayNameChanged(Call call);
874a79660c984d54679ad4d2bdc89e224d9c8c375bAndrew Lee        void onVideoStateChanged(Call call);
88b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        void onTargetPhoneAccountChanged(Call call);
89b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        void onConnectionManagerPhoneAccountChanged(Call call);
9012d61825cd0d6aa06272db3f77b5e30dce379951Santos Cordon        void onPhoneAccountChanged(Call call);
9112d61825cd0d6aa06272db3f77b5e30dce379951Santos Cordon        void onConferenceableCallsChanged(Call call);
92cf5b2918ca58b155911a66222ae5b4d21cb5b8ecSantos Cordon        boolean onCanceledViaNewOutgoingCallBroadcast(Call call);
9364c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon    }
9464c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon
9564c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon    abstract static class ListenerBase implements Listener {
9664c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
976fb37c87836b5245046bd3b14320823ab839a10cIhab Awad        public void onSuccessfulOutgoingCall(Call call, int callState) {}
9864c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
99701dc006ac11625b55d872f1639107b028933895Andrew Lee        public void onFailedOutgoingCall(Call call, DisconnectCause disconnectCause) {}
10064c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
101c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        public void onSuccessfulIncomingCall(Call call) {}
10264c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
10364c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        public void onFailedIncomingCall(Call call) {}
10464c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
1059250e5fa9987c3ab80e11e1955657055f5866539Yorke Lee        public void onSuccessfulUnknownCall(Call call, int callState) {}
1069250e5fa9987c3ab80e11e1955657055f5866539Yorke Lee        @Override
1079250e5fa9987c3ab80e11e1955657055f5866539Yorke Lee        public void onFailedUnknownCall(Call call) {}
1089250e5fa9987c3ab80e11e1955657055f5866539Yorke Lee        @Override
1095be64bc46c23b614d5452ca398a6bb7a512f1887Andrew Lee        public void onRingbackRequested(Call call, boolean ringbackRequested) {}
11064c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
11164c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        public void onPostDialWait(Call call, String remaining) {}
11264c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
113a469f76c1710a945933910840f11f9fda0445d82Nancy Chen        public void onPostDialChar(Call call, char nextChar) {}
114a469f76c1710a945933910840f11f9fda0445d82Nancy Chen        @Override
11507bc5ee853bc9a0b4cd46e0c702888b2c7989392Ihab Awad        public void onConnectionCapabilitiesChanged(Call call) {}
11664c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
11764c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        public void onParentChanged(Call call) {}
11864c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
11964c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        public void onChildrenChanged(Call call) {}
12064c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
12164c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        public void onCannedSmsResponsesLoaded(Call call) {}
12264c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
1233bcf935b25470e94c8c6855862434d15b785c54aAndrew Lee        public void onVideoCallProviderChanged(Call call) {}
12464c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        @Override
12564c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon        public void onCallerInfoChanged(Call call) {}
1267e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal        @Override
1275be64bc46c23b614d5452ca398a6bb7a512f1887Andrew Lee        public void onIsVoipAudioModeChanged(Call call) {}
12835faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal        @Override
12935faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal        public void onStatusHintsChanged(Call call) {}
130e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        @Override
131e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        public void onHandleChanged(Call call) {}
132e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        @Override
133e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        public void onCallerDisplayNameChanged(Call call) {}
1344a79660c984d54679ad4d2bdc89e224d9c8c375bAndrew Lee        @Override
1354a79660c984d54679ad4d2bdc89e224d9c8c375bAndrew Lee        public void onVideoStateChanged(Call call) {}
1369d58de5df05d0358fc8ae57ab7e9a0c45337c602Sailesh Nepal        @Override
137b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        public void onTargetPhoneAccountChanged(Call call) {}
138b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        @Override
139b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        public void onConnectionManagerPhoneAccountChanged(Call call) {}
14012d61825cd0d6aa06272db3f77b5e30dce379951Santos Cordon        @Override
14112d61825cd0d6aa06272db3f77b5e30dce379951Santos Cordon        public void onPhoneAccountChanged(Call call) {}
14212d61825cd0d6aa06272db3f77b5e30dce379951Santos Cordon        @Override
14312d61825cd0d6aa06272db3f77b5e30dce379951Santos Cordon        public void onConferenceableCallsChanged(Call call) {}
144cf5b2918ca58b155911a66222ae5b4d21cb5b8ecSantos Cordon        @Override
145cf5b2918ca58b155911a66222ae5b4d21cb5b8ecSantos Cordon        public boolean onCanceledViaNewOutgoingCallBroadcast(Call call) {
146cf5b2918ca58b155911a66222ae5b4d21cb5b8ecSantos Cordon            return false;
147cf5b2918ca58b155911a66222ae5b4d21cb5b8ecSantos Cordon        }
148766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    }
149766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon
150fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    private static final OnQueryCompleteListener sCallerInfoQueryListener =
15199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon            new OnQueryCompleteListener() {
15299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                /** ${inheritDoc} */
15399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                @Override
15499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                public void onQueryComplete(int token, Object cookie, CallerInfo callerInfo) {
15599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                    if (cookie != null) {
15699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                        ((Call) cookie).setCallerInfo(callerInfo, token);
15799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                    }
158fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon                }
15999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon            };
16099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon
16199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon    private static final OnImageLoadCompleteListener sPhotoLoadListener =
16299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon            new OnImageLoadCompleteListener() {
16399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                /** ${inheritDoc} */
16499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                @Override
16599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                public void onImageLoadComplete(
16699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                        int token, Drawable photo, Bitmap photoIcon, Object cookie) {
16799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                    if (cookie != null) {
16899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                        ((Call) cookie).setPhoto(photo, photoIcon, token);
16999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                    }
17099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                }
17199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon            };
1720407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad
173664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    private final Runnable mDirectToVoicemailRunnable = new Runnable() {
174664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        @Override
175664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        public void run() {
176664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            processDirectToVoicemail();
177664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        }
178664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    };
179664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
180810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal    /** True if this is an incoming call. */
181810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal    private final boolean mIsIncoming;
182810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal
1839250e5fa9987c3ab80e11e1955657055f5866539Yorke Lee    /** True if this is a currently unknown call that was not previously tracked by CallsManager,
1849250e5fa9987c3ab80e11e1955657055f5866539Yorke Lee     *  and did not originate via the regular incoming/outgoing call code paths.
1859250e5fa9987c3ab80e11e1955657055f5866539Yorke Lee     */
1869250e5fa9987c3ab80e11e1955657055f5866539Yorke Lee    private boolean mIsUnknown;
1879250e5fa9987c3ab80e11e1955657055f5866539Yorke Lee
1880407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad    /**
189664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal     * The time this call was created. Beyond logging and such, may also be used for bookkeeping
190664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal     * and specifically for marking certain call attempts as failed attempts.
1910407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad     */
1920c1e4f6713d04f193e211e0b3d25968c0ece8535Yorke Lee    private long mCreationTimeMillis = System.currentTimeMillis();
1938c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal
19440f9b179e6aaa0d906d38a48040425f82727aab4Santos Cordon    /** The time this call was made active. */
19540f9b179e6aaa0d906d38a48040425f82727aab4Santos Cordon    private long mConnectTimeMillis = 0;
19640f9b179e6aaa0d906d38a48040425f82727aab4Santos Cordon
19740f9b179e6aaa0d906d38a48040425f82727aab4Santos Cordon    /** The time this call was disconnected. */
19840f9b179e6aaa0d906d38a48040425f82727aab4Santos Cordon    private long mDisconnectTimeMillis = 0;
19940f9b179e6aaa0d906d38a48040425f82727aab4Santos Cordon
200fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    /** The gateway information associated with this call. This stores the original call handle
201fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon     * that the user is attempting to connect to via the gateway, the actual handle to dial in
202fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon     * order to connect the call via the gateway, as well as the package name of the gateway
203fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon     * service. */
2040d3076c3dfa54f1102a843735ca774759e52d8b8Nancy Chen    private GatewayInfo mGatewayInfo;
205fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon
206b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    private PhoneAccountHandle mConnectionManagerPhoneAccountHandle;
207b78b27693afbe9736f0a54ec473328955251f885Ihab Awad
208b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    private PhoneAccountHandle mTargetPhoneAccountHandle;
20977d2d0e90bc2a67d526743b8e32f920a0d755fbaNancy Chen
2102174fb56907fddf5680355e097f4425f837983e2Santos Cordon    private final Handler mHandler = new Handler();
2112174fb56907fddf5680355e097f4425f837983e2Santos Cordon
21212d61825cd0d6aa06272db3f77b5e30dce379951Santos Cordon    private final List<Call> mConferenceableCalls = new ArrayList<>();
21312d61825cd0d6aa06272db3f77b5e30dce379951Santos Cordon
21461d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    /** The state of the call. */
2156fb37c87836b5245046bd3b14320823ab839a10cIhab Awad    private int mState;
21661d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
21761d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    /** The handle with which to establish this call. */
218ce704b9a5d9cf7db30a8c865975c70e5cbc0dc5cSailesh Nepal    private Uri mHandle;
21961d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
220201b437535ebd07a3d8bf771920a4cb72d145ff3Nancy Chen    /**
2217cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunn     * The presentation requirements for the handle. See {@link TelecomManager} for valid values.
222201b437535ebd07a3d8bf771920a4cb72d145ff3Nancy Chen     */
223e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    private int mHandlePresentation;
224e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal
225e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    /** The caller display name (CNAP) set by the connection service. */
226e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    private String mCallerDisplayName;
227e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal
228201b437535ebd07a3d8bf771920a4cb72d145ff3Nancy Chen    /**
2297cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunn     * The presentation requirements for the handle. See {@link TelecomManager} for valid values.
230201b437535ebd07a3d8bf771920a4cb72d145ff3Nancy Chen     */
231e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    private int mCallerDisplayNamePresentation;
232e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal
2330407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad    /**
234c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal     * The connection service which is attempted or already connecting this call.
235681663d17b6d92b604526a54b196fa88f25b6957Santos Cordon     */
236c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal    private ConnectionServiceWrapper mConnectionService;
2376192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad
2386aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal    private boolean mIsEmergencyCall;
2396aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal
240b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati    private boolean mSpeakerphoneOn;
241b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati
2420a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn    /**
2430a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn     * Tracks the video states which were applicable over the duration of a call.
2446fb37c87836b5245046bd3b14320823ab839a10cIhab Awad     * See {@link VideoProfile} for a list of valid video states.
2450a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn     */
2460a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn    private int mVideoStateHistory;
2470a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn
248c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn    private int mVideoState;
249c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn
2506192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad    /**
2516fb37c87836b5245046bd3b14320823ab839a10cIhab Awad     * Disconnect cause for the call. Only valid if the state of the call is STATE_DISCONNECTED.
252701dc006ac11625b55d872f1639107b028933895Andrew Lee     * See {@link android.telecom.DisconnectCause}.
25379ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon     */
254701dc006ac11625b55d872f1639107b028933895Andrew Lee    private DisconnectCause mDisconnectCause = new DisconnectCause(DisconnectCause.UNKNOWN);
25579ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon
256c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal    /** Info used by the connection services. */
2578c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal    private Bundle mExtras = Bundle.EMPTY;
25884fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal
259a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shrauner    /** Set of listeners on this call.
260a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shrauner     *
261a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shrauner     * ConcurrentHashMap constructor params: 8 is initial table size, 0.9f is
262a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shrauner     * load factor before resizing, 1 means we only expect a single thread to
263a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shrauner     * access the map so make only a single shard
264a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shrauner     */
265a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shrauner    private final Set<Listener> mListeners = Collections.newSetFromMap(
266a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shrauner            new ConcurrentHashMap<Listener, Boolean>(8, 0.9f, 1));
267766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon
268664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    private CreateConnectionProcessor mCreateConnectionProcessor;
269682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon
270fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    /** Caller information retrieved from the latest contact query. */
271fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    private CallerInfo mCallerInfo;
272fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon
273fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    /** The latest token used with a contact info query. */
274fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    private int mQueryToken = 0;
275fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon
2767cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunn    /** Whether this call is requesting that Telecom play the ringback tone on its behalf. */
2775be64bc46c23b614d5452ca398a6bb7a512f1887Andrew Lee    private boolean mRingbackRequested = false;
278cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad
279c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal    /** Whether direct-to-voicemail query is pending. */
280c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal    private boolean mDirectToVoicemailQueryPending;
2812174fb56907fddf5680355e097f4425f837983e2Santos Cordon
28207bc5ee853bc9a0b4cd46e0c702888b2c7989392Ihab Awad    private int mConnectionCapabilities;
283a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
284a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    private boolean mIsConference = false;
285a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
286a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    private Call mParentCall = null;
287a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
288a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    private List<Call> mChildCalls = new LinkedList<>();
289a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
290ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    /** Set of text message responses allowed for this call, if applicable. */
291ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    private List<String> mCannedSmsResponses = Collections.EMPTY_LIST;
292ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad
293ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    /** Whether an attempt has been made to load the text message responses. */
294ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    private boolean mCannedSmsResponsesLoadingStarted = false;
295ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad
2966fb37c87836b5245046bd3b14320823ab839a10cIhab Awad    private IVideoProvider mVideoProvider;
297a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen
2985be64bc46c23b614d5452ca398a6bb7a512f1887Andrew Lee    private boolean mIsVoipAudioMode;
29935faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal    private StatusHints mStatusHints;
300664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    private final ConnectionServiceRepository mRepository;
30191d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn    private final Context mContext;
3027e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal
30388a4a60284de8e1222488667b810b098c16d22acSantos Cordon    private boolean mWasConferencePreviouslyMerged = false;
30488a4a60284de8e1222488667b810b098c16d22acSantos Cordon
30588a4a60284de8e1222488667b810b098c16d22acSantos Cordon    // For conferences which support merge/swap at their level, we retain a notion of an active call.
30688a4a60284de8e1222488667b810b098c16d22acSantos Cordon    // This is used for BluetoothPhoneService.  In order to support hold/merge, it must have the notion
30788a4a60284de8e1222488667b810b098c16d22acSantos Cordon    // of the current "active" call within the conference call. This maintains the "active" call and
30888a4a60284de8e1222488667b810b098c16d22acSantos Cordon    // switches every time the user hits "swap".
30988a4a60284de8e1222488667b810b098c16d22acSantos Cordon    private Call mConferenceLevelActiveCall = null;
31088a4a60284de8e1222488667b810b098c16d22acSantos Cordon
311aa47937652d80d8bd19860ec521d28ffea745e63Tyler Gunn    private boolean mIsLocallyDisconnecting = false;
312aa47937652d80d8bd19860ec521d28ffea745e63Tyler Gunn
3138c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal    /**
3140407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad     * Persists the specified parameters and initializes the new instance.
3150407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad     *
31691d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn     * @param context The context.
31791d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn     * @param repository The connection service repository.
3180407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad     * @param handle The handle to dial.
31933501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee     * @param gatewayInfo Gateway information to use for the call.
320b78b27693afbe9736f0a54ec473328955251f885Ihab Awad     * @param connectionManagerPhoneAccountHandle Account to use for the service managing the call.
321b78b27693afbe9736f0a54ec473328955251f885Ihab Awad     *         This account must be one that was registered with the
322b78b27693afbe9736f0a54ec473328955251f885Ihab Awad     *         {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER} flag.
323b78b27693afbe9736f0a54ec473328955251f885Ihab Awad     * @param targetPhoneAccountHandle Account information to use for the call. This account must be
324b78b27693afbe9736f0a54ec473328955251f885Ihab Awad     *         one that was registered with the {@link PhoneAccount#CAPABILITY_CALL_PROVIDER} flag.
325810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal     * @param isIncoming True if this is an incoming call.
3260407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad     */
327664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    Call(
32891d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn            Context context,
329664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            ConnectionServiceRepository repository,
330664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            Uri handle,
331664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            GatewayInfo gatewayInfo,
332b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            PhoneAccountHandle connectionManagerPhoneAccountHandle,
333b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            PhoneAccountHandle targetPhoneAccountHandle,
334664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            boolean isIncoming,
335664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            boolean isConference) {
336a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        mState = isConference ? CallState.ACTIVE : CallState.NEW;
33791d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn        mContext = context;
338664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        mRepository = repository;
3390d3076c3dfa54f1102a843735ca774759e52d8b8Nancy Chen        setHandle(handle);
3407cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunn        setHandle(handle, TelecomManager.PRESENTATION_ALLOWED);
34133501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee        mGatewayInfo = gatewayInfo;
342f193ba45fae5bc87e6a57779e4f5b56be59d08b0Santos Cordon        setConnectionManagerPhoneAccount(connectionManagerPhoneAccountHandle);
343f193ba45fae5bc87e6a57779e4f5b56be59d08b0Santos Cordon        setTargetPhoneAccount(targetPhoneAccountHandle);
344810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal        mIsIncoming = isIncoming;
345a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        mIsConference = isConference;
346ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        maybeLoadCannedSmsResponses();
3470407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad    }
3480407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad
349d92e73772327537fe65edda43ca0ceb6fc781e51Tyler Gunn    /**
350d92e73772327537fe65edda43ca0ceb6fc781e51Tyler Gunn     * Persists the specified parameters and initializes the new instance.
351d92e73772327537fe65edda43ca0ceb6fc781e51Tyler Gunn     *
352d92e73772327537fe65edda43ca0ceb6fc781e51Tyler Gunn     * @param context The context.
353d92e73772327537fe65edda43ca0ceb6fc781e51Tyler Gunn     * @param repository The connection service repository.
354d92e73772327537fe65edda43ca0ceb6fc781e51Tyler Gunn     * @param handle The handle to dial.
355d92e73772327537fe65edda43ca0ceb6fc781e51Tyler Gunn     * @param gatewayInfo Gateway information to use for the call.
356d92e73772327537fe65edda43ca0ceb6fc781e51Tyler Gunn     * @param connectionManagerPhoneAccountHandle Account to use for the service managing the call.
357d92e73772327537fe65edda43ca0ceb6fc781e51Tyler Gunn     *         This account must be one that was registered with the
358d92e73772327537fe65edda43ca0ceb6fc781e51Tyler Gunn     *         {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER} flag.
359d92e73772327537fe65edda43ca0ceb6fc781e51Tyler Gunn     * @param targetPhoneAccountHandle Account information to use for the call. This account must be
360d92e73772327537fe65edda43ca0ceb6fc781e51Tyler Gunn     *         one that was registered with the {@link PhoneAccount#CAPABILITY_CALL_PROVIDER} flag.
361d92e73772327537fe65edda43ca0ceb6fc781e51Tyler Gunn     * @param isIncoming True if this is an incoming call.
362d92e73772327537fe65edda43ca0ceb6fc781e51Tyler Gunn     * @param connectTimeMillis The connection time of the call.
363d92e73772327537fe65edda43ca0ceb6fc781e51Tyler Gunn     */
364d92e73772327537fe65edda43ca0ceb6fc781e51Tyler Gunn    Call(
365d92e73772327537fe65edda43ca0ceb6fc781e51Tyler Gunn            Context context,
366d92e73772327537fe65edda43ca0ceb6fc781e51Tyler Gunn            ConnectionServiceRepository repository,
367d92e73772327537fe65edda43ca0ceb6fc781e51Tyler Gunn            Uri handle,
368d92e73772327537fe65edda43ca0ceb6fc781e51Tyler Gunn            GatewayInfo gatewayInfo,
369d92e73772327537fe65edda43ca0ceb6fc781e51Tyler Gunn            PhoneAccountHandle connectionManagerPhoneAccountHandle,
370d92e73772327537fe65edda43ca0ceb6fc781e51Tyler Gunn            PhoneAccountHandle targetPhoneAccountHandle,
371d92e73772327537fe65edda43ca0ceb6fc781e51Tyler Gunn            boolean isIncoming,
372d92e73772327537fe65edda43ca0ceb6fc781e51Tyler Gunn            boolean isConference,
373d92e73772327537fe65edda43ca0ceb6fc781e51Tyler Gunn            long connectTimeMillis) {
374d92e73772327537fe65edda43ca0ceb6fc781e51Tyler Gunn        this(context, repository, handle, gatewayInfo, connectionManagerPhoneAccountHandle,
375d92e73772327537fe65edda43ca0ceb6fc781e51Tyler Gunn                targetPhoneAccountHandle, isIncoming, isConference);
376d92e73772327537fe65edda43ca0ceb6fc781e51Tyler Gunn
377d92e73772327537fe65edda43ca0ceb6fc781e51Tyler Gunn        mConnectTimeMillis = connectTimeMillis;
378d92e73772327537fe65edda43ca0ceb6fc781e51Tyler Gunn    }
379d92e73772327537fe65edda43ca0ceb6fc781e51Tyler Gunn
380766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    void addListener(Listener listener) {
381766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon        mListeners.add(listener);
382766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    }
383766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon
384766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    void removeListener(Listener listener) {
385a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shrauner        if (listener != null) {
386a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shrauner            mListeners.remove(listener);
387a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shrauner        }
388766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    }
389766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon
39061d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    /** {@inheritDoc} */
39112d61825cd0d6aa06272db3f77b5e30dce379951Santos Cordon    @Override
39212d61825cd0d6aa06272db3f77b5e30dce379951Santos Cordon    public String toString() {
3934538f01647fa207b41fb7e481cc180e67fd391deSailesh Nepal        String component = null;
394c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        if (mConnectionService != null && mConnectionService.getComponentName() != null) {
395c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            component = mConnectionService.getComponentName().flattenToShortString();
3964538f01647fa207b41fb7e481cc180e67fd391deSailesh Nepal        }
3970a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn
39866fe882a6437de1010af0dc8cd7350f81f2e028aSantos Cordon        return String.format(Locale.US, "[%s, %s, %s, %s, %d, childs(%d), has_parent(%b), [%s]",
39966fe882a6437de1010af0dc8cd7350f81f2e028aSantos Cordon                System.identityHashCode(this),
40066fe882a6437de1010af0dc8cd7350f81f2e028aSantos Cordon                CallState.toString(mState),
40166fe882a6437de1010af0dc8cd7350f81f2e028aSantos Cordon                component,
40266fe882a6437de1010af0dc8cd7350f81f2e028aSantos Cordon                Log.piiHandle(mHandle),
40366fe882a6437de1010af0dc8cd7350f81f2e028aSantos Cordon                getVideoState(),
40466fe882a6437de1010af0dc8cd7350f81f2e028aSantos Cordon                getChildCalls().size(),
40566fe882a6437de1010af0dc8cd7350f81f2e028aSantos Cordon                getParentCall() != null,
40607bc5ee853bc9a0b4cd46e0c702888b2c7989392Ihab Awad                Connection.capabilitiesToString(getConnectionCapabilities()));
40761d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    }
40861d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
4096fb37c87836b5245046bd3b14320823ab839a10cIhab Awad    int getState() {
4100fbe6321e341ddce186634266dba2db3fa426b88Santos Cordon        return mState;
4110b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon    }
4120b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon
413646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal    private boolean shouldContinueProcessingAfterDisconnect() {
414646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal        // Stop processing once the call is active.
415646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal        if (!CreateConnectionTimeout.isCallBeingPlaced(this)) {
416646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal            return false;
417646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal        }
418646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal
419646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal        // Make sure that there are additional connection services to process.
420646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal        if (mCreateConnectionProcessor == null
421646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal            || !mCreateConnectionProcessor.isProcessingComplete()
422646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal            || !mCreateConnectionProcessor.hasMorePhoneAccounts()) {
423646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal            return false;
424646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal        }
425646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal
426646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal        if (mDisconnectCause == null) {
427646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal            return false;
428646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal        }
429646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal
430646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal        // Continue processing if the current attempt failed or timed out.
431646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal        return mDisconnectCause.getCode() == DisconnectCause.ERROR ||
432646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal            mCreateConnectionProcessor.isCallTimedOut();
433646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal    }
434646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal
4350b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon    /**
4360b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon     * Sets the call state. Although there exists the notion of appropriate state transitions
4370b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon     * (see {@link CallState}), in practice those expectations break down when cellular systems
4380b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon     * misbehave and they do this very often. The result is that we do not enforce state transitions
4390b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon     * and instead keep the code resilient to unexpected state changes.
4400b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon     */
4416fb37c87836b5245046bd3b14320823ab839a10cIhab Awad    void setState(int newState) {
442810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal        if (mState != newState) {
443810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal            Log.v(this, "setState %s -> %s", mState, newState);
4442767926bb2d241d651e823a25d5a24295c120ec5Sailesh Nepal
445646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal            if (newState == CallState.DISCONNECTED && shouldContinueProcessingAfterDisconnect()) {
446646fa3d6eaea71fb4c3270fde1a30eeb7c5e4288Sailesh Nepal                Log.w(this, "continuing processing disconnected call with another service");
4472767926bb2d241d651e823a25d5a24295c120ec5Sailesh Nepal                mCreateConnectionProcessor.continueProcessingIfPossible(this, mDisconnectCause);
4482767926bb2d241d651e823a25d5a24295c120ec5Sailesh Nepal                return;
4492767926bb2d241d651e823a25d5a24295c120ec5Sailesh Nepal            }
4502767926bb2d241d651e823a25d5a24295c120ec5Sailesh Nepal
451810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal            mState = newState;
452ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            maybeLoadCannedSmsResponses();
453672321e603555849831dd88d5c9f93d88143ee48Santos Cordon
45440f9b179e6aaa0d906d38a48040425f82727aab4Santos Cordon            if (mState == CallState.ACTIVE || mState == CallState.ON_HOLD) {
45540f9b179e6aaa0d906d38a48040425f82727aab4Santos Cordon                if (mConnectTimeMillis == 0) {
45640f9b179e6aaa0d906d38a48040425f82727aab4Santos Cordon                    // We check to see if mConnectTime is already set to prevent the
45740f9b179e6aaa0d906d38a48040425f82727aab4Santos Cordon                    // call from resetting active time when it goes in and out of
45840f9b179e6aaa0d906d38a48040425f82727aab4Santos Cordon                    // ACTIVE/ON_HOLD
45940f9b179e6aaa0d906d38a48040425f82727aab4Santos Cordon                    mConnectTimeMillis = System.currentTimeMillis();
46040f9b179e6aaa0d906d38a48040425f82727aab4Santos Cordon                }
46140f9b179e6aaa0d906d38a48040425f82727aab4Santos Cordon
46240f9b179e6aaa0d906d38a48040425f82727aab4Santos Cordon                // We're clearly not disconnected, so reset the disconnected time.
46340f9b179e6aaa0d906d38a48040425f82727aab4Santos Cordon                mDisconnectTimeMillis = 0;
46440f9b179e6aaa0d906d38a48040425f82727aab4Santos Cordon            } else if (mState == CallState.DISCONNECTED) {
46540f9b179e6aaa0d906d38a48040425f82727aab4Santos Cordon                mDisconnectTimeMillis = System.currentTimeMillis();
4665dfd3800f15e9b0f1420813d8d7638e1cf9d621dSantos Cordon                setLocallyDisconnecting(false);
467672321e603555849831dd88d5c9f93d88143ee48Santos Cordon                fixParentAfterDisconnect();
468672321e603555849831dd88d5c9f93d88143ee48Santos Cordon            }
469810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal        }
4700b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon    }
4710b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon
4725be64bc46c23b614d5452ca398a6bb7a512f1887Andrew Lee    void setRingbackRequested(boolean ringbackRequested) {
4735be64bc46c23b614d5452ca398a6bb7a512f1887Andrew Lee        mRingbackRequested = ringbackRequested;
474cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad        for (Listener l : mListeners) {
4755be64bc46c23b614d5452ca398a6bb7a512f1887Andrew Lee            l.onRingbackRequested(this, mRingbackRequested);
476cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad        }
477cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad    }
478cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad
4795be64bc46c23b614d5452ca398a6bb7a512f1887Andrew Lee    boolean isRingbackRequested() {
4805be64bc46c23b614d5452ca398a6bb7a512f1887Andrew Lee        return mRingbackRequested;
481cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad    }
482cb387ac1bb278de62e352b363cb38339629a61f5Ihab Awad
483672321e603555849831dd88d5c9f93d88143ee48Santos Cordon    boolean isConference() {
484672321e603555849831dd88d5c9f93d88143ee48Santos Cordon        return mIsConference;
485672321e603555849831dd88d5c9f93d88143ee48Santos Cordon    }
486672321e603555849831dd88d5c9f93d88143ee48Santos Cordon
487ce704b9a5d9cf7db30a8c865975c70e5cbc0dc5cSailesh Nepal    Uri getHandle() {
4880bf5b912285e328a8f5eeec158d6caf17845b9f8Ben Gilad        return mHandle;
4890bf5b912285e328a8f5eeec158d6caf17845b9f8Ben Gilad    }
4900bf5b912285e328a8f5eeec158d6caf17845b9f8Ben Gilad
491e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    int getHandlePresentation() {
492e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        return mHandlePresentation;
493e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    }
494e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal
4950d3076c3dfa54f1102a843735ca774759e52d8b8Nancy Chen
4960d3076c3dfa54f1102a843735ca774759e52d8b8Nancy Chen    void setHandle(Uri handle) {
4977cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunn        setHandle(handle, TelecomManager.PRESENTATION_ALLOWED);
4980d3076c3dfa54f1102a843735ca774759e52d8b8Nancy Chen    }
4990d3076c3dfa54f1102a843735ca774759e52d8b8Nancy Chen
500e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    void setHandle(Uri handle, int presentation) {
501e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        if (!Objects.equals(handle, mHandle) || presentation != mHandlePresentation) {
502e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal            mHandlePresentation = presentation;
503ecaaeac225ada350b9b3acfb485583cc388050deSantos Cordon            if (mHandlePresentation == TelecomManager.PRESENTATION_RESTRICTED ||
504ecaaeac225ada350b9b3acfb485583cc388050deSantos Cordon                    mHandlePresentation == TelecomManager.PRESENTATION_UNKNOWN) {
505ecaaeac225ada350b9b3acfb485583cc388050deSantos Cordon                mHandle = null;
506ecaaeac225ada350b9b3acfb485583cc388050deSantos Cordon            } else {
507ecaaeac225ada350b9b3acfb485583cc388050deSantos Cordon                mHandle = handle;
50896e662d3811673f284da0f9d2deabe939918a3b1Yorke Lee                if (mHandle != null && !PhoneAccount.SCHEME_VOICEMAIL.equals(mHandle.getScheme())
50996e662d3811673f284da0f9d2deabe939918a3b1Yorke Lee                        && TextUtils.isEmpty(mHandle.getSchemeSpecificPart())) {
51096e662d3811673f284da0f9d2deabe939918a3b1Yorke Lee                    // If the number is actually empty, set it to null, unless this is a
51196e662d3811673f284da0f9d2deabe939918a3b1Yorke Lee                    // SCHEME_VOICEMAIL uri which always has an empty number.
512ecaaeac225ada350b9b3acfb485583cc388050deSantos Cordon                    mHandle = null;
513ecaaeac225ada350b9b3acfb485583cc388050deSantos Cordon                }
514ecaaeac225ada350b9b3acfb485583cc388050deSantos Cordon            }
515ecaaeac225ada350b9b3acfb485583cc388050deSantos Cordon
51691d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn            mIsEmergencyCall = mHandle != null && PhoneNumberUtils.isLocalEmergencyNumber(mContext,
51791d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn                    mHandle.getSchemeSpecificPart());
518fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon            startCallerInfoLookup();
519e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal            for (Listener l : mListeners) {
520e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal                l.onHandleChanged(this);
521e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal            }
522e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        }
523e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    }
524e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal
525e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    String getCallerDisplayName() {
526e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        return mCallerDisplayName;
527e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    }
528e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal
529e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    int getCallerDisplayNamePresentation() {
530e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        return mCallerDisplayNamePresentation;
531e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    }
532e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal
533e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal    void setCallerDisplayName(String callerDisplayName, int presentation) {
534e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        if (!TextUtils.equals(callerDisplayName, mCallerDisplayName) ||
535e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal                presentation != mCallerDisplayNamePresentation) {
536e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal            mCallerDisplayName = callerDisplayName;
537e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal            mCallerDisplayNamePresentation = presentation;
538e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal            for (Listener l : mListeners) {
539e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal                l.onCallerDisplayNameChanged(this);
540e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal            }
541fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon        }
5426aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal    }
5436aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal
54499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon    String getName() {
54599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon        return mCallerInfo == null ? null : mCallerInfo.name;
54699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon    }
54799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon
54899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon    Bitmap getPhotoIcon() {
54999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon        return mCallerInfo == null ? null : mCallerInfo.cachedPhotoIcon;
55099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon    }
55199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon
55299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon    Drawable getPhoto() {
55399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon        return mCallerInfo == null ? null : mCallerInfo.cachedPhoto;
55499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon    }
55599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon
55679ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon    /**
557701dc006ac11625b55d872f1639107b028933895Andrew Lee     * @param disconnectCause The reason for the disconnection, represented by
558701dc006ac11625b55d872f1639107b028933895Andrew Lee     *         {@link android.telecom.DisconnectCause}.
55979ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon     */
560701dc006ac11625b55d872f1639107b028933895Andrew Lee    void setDisconnectCause(DisconnectCause disconnectCause) {
56179ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon        // TODO: Consider combining this method with a setDisconnected() method that is totally
56279ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon        // separate from setState.
56379ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon        mDisconnectCause = disconnectCause;
56479ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon    }
56579ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon
566701dc006ac11625b55d872f1639107b028933895Andrew Lee    DisconnectCause getDisconnectCause() {
56779ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon        return mDisconnectCause;
56879ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon    }
56979ff2bcdbdf1c28f229f4acec9433beb1cd7a57eSantos Cordon
5706aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal    boolean isEmergencyCall() {
5716aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal        return mIsEmergencyCall;
57261d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    }
57361d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
57433501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee    /**
57533501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee     * @return The original handle this call is associated with. In-call services should use this
57633501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee     * handle when indicating in their UI the handle that is being called.
57733501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee     */
57833501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee    public Uri getOriginalHandle() {
57933501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee        if (mGatewayInfo != null && !mGatewayInfo.isEmpty()) {
580201b437535ebd07a3d8bf771920a4cb72d145ff3Nancy Chen            return mGatewayInfo.getOriginalAddress();
58133501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee        }
58233501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee        return getHandle();
58333501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee    }
58433501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee
58533501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee    GatewayInfo getGatewayInfo() {
58633501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee        return mGatewayInfo;
58733501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee    }
58833501635c2cd21f40793041eff3b8ce3a5710d49Yorke Lee
5890d3076c3dfa54f1102a843735ca774759e52d8b8Nancy Chen    void setGatewayInfo(GatewayInfo gatewayInfo) {
5900d3076c3dfa54f1102a843735ca774759e52d8b8Nancy Chen        mGatewayInfo = gatewayInfo;
5910d3076c3dfa54f1102a843735ca774759e52d8b8Nancy Chen    }
5920d3076c3dfa54f1102a843735ca774759e52d8b8Nancy Chen
593b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    PhoneAccountHandle getConnectionManagerPhoneAccount() {
594b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        return mConnectionManagerPhoneAccountHandle;
595b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    }
596b78b27693afbe9736f0a54ec473328955251f885Ihab Awad
597b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    void setConnectionManagerPhoneAccount(PhoneAccountHandle accountHandle) {
598b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        if (!Objects.equals(mConnectionManagerPhoneAccountHandle, accountHandle)) {
599b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            mConnectionManagerPhoneAccountHandle = accountHandle;
600b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            for (Listener l : mListeners) {
601b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                l.onConnectionManagerPhoneAccountChanged(this);
602b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            }
603b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        }
604b78b27693afbe9736f0a54ec473328955251f885Ihab Awad
605b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    }
606b78b27693afbe9736f0a54ec473328955251f885Ihab Awad
607b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    PhoneAccountHandle getTargetPhoneAccount() {
608b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        return mTargetPhoneAccountHandle;
60977d2d0e90bc2a67d526743b8e32f920a0d755fbaNancy Chen    }
61077d2d0e90bc2a67d526743b8e32f920a0d755fbaNancy Chen
611b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    void setTargetPhoneAccount(PhoneAccountHandle accountHandle) {
612b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        if (!Objects.equals(mTargetPhoneAccountHandle, accountHandle)) {
613b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            mTargetPhoneAccountHandle = accountHandle;
61469eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad            for (Listener l : mListeners) {
615b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                l.onTargetPhoneAccountChanged(this);
61669eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad            }
61769eb0f582babcedc1dc5e6613a27867be6e8d0e0Ihab Awad        }
61853ceedc1f5ae5a075c7a3186db8bb4db32cbe583Nancy Chen    }
61953ceedc1f5ae5a075c7a3186db8bb4db32cbe583Nancy Chen
620810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal    boolean isIncoming() {
621810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal        return mIsIncoming;
622810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal    }
623810735e3f0a4fe924a805981d32b6916ec834b38Sailesh Nepal
6240407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad    /**
6250407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad     * @return The "age" of this call object in milliseconds, which typically also represents the
6268c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal     *     period since this call was added to the set pending outgoing calls, see
6278c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal     *     mCreationTimeMillis.
6280407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad     */
6298c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal    long getAgeMillis() {
63040f9b179e6aaa0d906d38a48040425f82727aab4Santos Cordon        if (mState == CallState.DISCONNECTED &&
63140f9b179e6aaa0d906d38a48040425f82727aab4Santos Cordon                (mDisconnectCause.getCode() == DisconnectCause.REJECTED ||
63240f9b179e6aaa0d906d38a48040425f82727aab4Santos Cordon                 mDisconnectCause.getCode() == DisconnectCause.MISSED)) {
63340f9b179e6aaa0d906d38a48040425f82727aab4Santos Cordon            // Rejected and missed calls have no age. They're immortal!!
63440f9b179e6aaa0d906d38a48040425f82727aab4Santos Cordon            return 0;
63540f9b179e6aaa0d906d38a48040425f82727aab4Santos Cordon        } else if (mConnectTimeMillis == 0) {
63640f9b179e6aaa0d906d38a48040425f82727aab4Santos Cordon            // Age is measured in the amount of time the call was active. A zero connect time
63740f9b179e6aaa0d906d38a48040425f82727aab4Santos Cordon            // indicates that we never went active, so return 0 for the age.
63840f9b179e6aaa0d906d38a48040425f82727aab4Santos Cordon            return 0;
63940f9b179e6aaa0d906d38a48040425f82727aab4Santos Cordon        } else if (mDisconnectTimeMillis == 0) {
64040f9b179e6aaa0d906d38a48040425f82727aab4Santos Cordon            // We connected, but have not yet disconnected
64140f9b179e6aaa0d906d38a48040425f82727aab4Santos Cordon            return System.currentTimeMillis() - mConnectTimeMillis;
64240f9b179e6aaa0d906d38a48040425f82727aab4Santos Cordon        }
64340f9b179e6aaa0d906d38a48040425f82727aab4Santos Cordon
64440f9b179e6aaa0d906d38a48040425f82727aab4Santos Cordon        return mDisconnectTimeMillis - mConnectTimeMillis;
6450407fb2c5a8358cfae92bbd6f8cdc103d66c7b13Ben Gilad    }
6460b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon
647f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee    /**
648f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     * @return The time when this call object was created and added to the set of pending outgoing
649f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     *     calls.
650f98fb5790ed62a3d4893362554f8d251c74d0ecdYorke Lee     */
6518c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal    long getCreationTimeMillis() {
6528c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal        return mCreationTimeMillis;
6538c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal    }
6548c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal
6550c1e4f6713d04f193e211e0b3d25968c0ece8535Yorke Lee    void setCreationTimeMillis(long time) {
6560c1e4f6713d04f193e211e0b3d25968c0ece8535Yorke Lee        mCreationTimeMillis = time;
6570c1e4f6713d04f193e211e0b3d25968c0ece8535Yorke Lee    }
6580c1e4f6713d04f193e211e0b3d25968c0ece8535Yorke Lee
6598c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal    long getConnectTimeMillis() {
6608c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal        return mConnectTimeMillis;
6618c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal    }
6628c85dee84fbbd8c36cf1c7b061001c6129623f92Sailesh Nepal
66307bc5ee853bc9a0b4cd46e0c702888b2c7989392Ihab Awad    int getConnectionCapabilities() {
66407bc5ee853bc9a0b4cd46e0c702888b2c7989392Ihab Awad        return mConnectionCapabilities;
665a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    }
666a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
66707bc5ee853bc9a0b4cd46e0c702888b2c7989392Ihab Awad    void setConnectionCapabilities(int connectionCapabilities) {
66807bc5ee853bc9a0b4cd46e0c702888b2c7989392Ihab Awad        setConnectionCapabilities(connectionCapabilities, false /* forceUpdate */);
669604a90f596deb41998e021151b3ddc8019e28eacYorke Lee    }
670604a90f596deb41998e021151b3ddc8019e28eacYorke Lee
67107bc5ee853bc9a0b4cd46e0c702888b2c7989392Ihab Awad    void setConnectionCapabilities(int connectionCapabilities, boolean forceUpdate) {
67207bc5ee853bc9a0b4cd46e0c702888b2c7989392Ihab Awad        Log.v(this, "setConnectionCapabilities: %s", Connection.capabilitiesToString(
67307bc5ee853bc9a0b4cd46e0c702888b2c7989392Ihab Awad                connectionCapabilities));
67407bc5ee853bc9a0b4cd46e0c702888b2c7989392Ihab Awad        if (forceUpdate || mConnectionCapabilities != connectionCapabilities) {
67507bc5ee853bc9a0b4cd46e0c702888b2c7989392Ihab Awad           mConnectionCapabilities = connectionCapabilities;
676a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            for (Listener l : mListeners) {
67707bc5ee853bc9a0b4cd46e0c702888b2c7989392Ihab Awad                l.onConnectionCapabilitiesChanged(this);
678a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            }
679a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        }
680a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    }
681a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
682a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    Call getParentCall() {
683a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        return mParentCall;
684a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    }
685a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
686a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    List<Call> getChildCalls() {
687a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        return mChildCalls;
688a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    }
689a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
69088a4a60284de8e1222488667b810b098c16d22acSantos Cordon    boolean wasConferencePreviouslyMerged() {
69188a4a60284de8e1222488667b810b098c16d22acSantos Cordon        return mWasConferencePreviouslyMerged;
69288a4a60284de8e1222488667b810b098c16d22acSantos Cordon    }
69388a4a60284de8e1222488667b810b098c16d22acSantos Cordon
69488a4a60284de8e1222488667b810b098c16d22acSantos Cordon    Call getConferenceLevelActiveCall() {
69588a4a60284de8e1222488667b810b098c16d22acSantos Cordon        return mConferenceLevelActiveCall;
69688a4a60284de8e1222488667b810b098c16d22acSantos Cordon    }
69788a4a60284de8e1222488667b810b098c16d22acSantos Cordon
698c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal    ConnectionServiceWrapper getConnectionService() {
699c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        return mConnectionService;
700681663d17b6d92b604526a54b196fa88f25b6957Santos Cordon    }
701681663d17b6d92b604526a54b196fa88f25b6957Santos Cordon
70291d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn    /**
70391d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn     * Retrieves the {@link Context} for the call.
70491d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn     *
70591d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn     * @return The {@link Context}.
70691d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn     */
70791d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn    Context getContext() {
70891d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn        return mContext;
70991d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn    }
71091d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn
711c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal    void setConnectionService(ConnectionServiceWrapper service) {
712c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        Preconditions.checkNotNull(service);
7138e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad
714c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        clearConnectionService();
7158e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad
716c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        service.incrementAssociatedCallCount();
717c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        mConnectionService = service;
718c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        mConnectionService.addCall(this);
719681663d17b6d92b604526a54b196fa88f25b6957Santos Cordon    }
720681663d17b6d92b604526a54b196fa88f25b6957Santos Cordon
721681663d17b6d92b604526a54b196fa88f25b6957Santos Cordon    /**
722c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal     * Clears the associated connection service.
723681663d17b6d92b604526a54b196fa88f25b6957Santos Cordon     */
724c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal    void clearConnectionService() {
725c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        if (mConnectionService != null) {
726c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            ConnectionServiceWrapper serviceTemp = mConnectionService;
727c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            mConnectionService = null;
728c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            serviceTemp.removeCall(this);
729c499c1c0758dcb4b02048df96e7405994660ab3fSantos Cordon
730c499c1c0758dcb4b02048df96e7405994660ab3fSantos Cordon            // Decrementing the count can cause the service to unbind, which itself can trigger the
731c499c1c0758dcb4b02048df96e7405994660ab3fSantos Cordon            // service-death code.  Since the service death code tries to clean up any associated
732c499c1c0758dcb4b02048df96e7405994660ab3fSantos Cordon            // calls, we need to make sure to remove that information (e.g., removeCall()) before
733c499c1c0758dcb4b02048df96e7405994660ab3fSantos Cordon            // we decrement. Technically, invoking removeCall() prior to decrementing is all that is
734c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            // necessary, but cleaning up mConnectionService prior to triggering an unbind is good
735c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            // to do.
736c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            decrementAssociatedCallCount(serviceTemp);
737adee12dd6b3e85ce3ae419329226c9aa72c184fcYorke Lee        }
7388e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad    }
7398e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad
740664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    private void processDirectToVoicemail() {
741c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        if (mDirectToVoicemailQueryPending) {
7422174fb56907fddf5680355e097f4425f837983e2Santos Cordon            if (mCallerInfo != null && mCallerInfo.shouldSendToVoicemail) {
7432174fb56907fddf5680355e097f4425f837983e2Santos Cordon                Log.i(this, "Directing call to voicemail: %s.", this);
744df39986de36d40aaa45e61d19a21eca536765ca5Santos Cordon                // TODO: Once we move State handling from CallsManager to Call, we
7456fb37c87836b5245046bd3b14320823ab839a10cIhab Awad                // will not need to set STATE_RINGING state prior to calling reject.
7462174fb56907fddf5680355e097f4425f837983e2Santos Cordon                setState(CallState.RINGING);
747ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                reject(false, null);
7482174fb56907fddf5680355e097f4425f837983e2Santos Cordon            } else {
749df39986de36d40aaa45e61d19a21eca536765ca5Santos Cordon                // TODO: Make this class (not CallsManager) responsible for changing
7506fb37c87836b5245046bd3b14320823ab839a10cIhab Awad                // the call state to STATE_RINGING.
7512174fb56907fddf5680355e097f4425f837983e2Santos Cordon
7526fb37c87836b5245046bd3b14320823ab839a10cIhab Awad                // TODO: Replace this with state transition to STATE_RINGING.
7532174fb56907fddf5680355e097f4425f837983e2Santos Cordon                for (Listener l : mListeners) {
754c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal                    l.onSuccessfulIncomingCall(this);
7552174fb56907fddf5680355e097f4425f837983e2Santos Cordon                }
7562174fb56907fddf5680355e097f4425f837983e2Santos Cordon            }
757766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon
758c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            mDirectToVoicemailQueryPending = false;
759766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon        }
760766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    }
761766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon
762766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    /**
763664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal     * Starts the create connection sequence. Upon completion, there should exist an active
764664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal     * connection through a connection service (or the call will have failed).
76591d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn     *
76691d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn     * @param phoneAccountRegistrar The phone account registrar.
767766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon     */
76891d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn    void startCreateConnection(PhoneAccountRegistrar phoneAccountRegistrar) {
769664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        Preconditions.checkState(mCreateConnectionProcessor == null);
77091d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn        mCreateConnectionProcessor = new CreateConnectionProcessor(this, mRepository, this,
77191d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn                phoneAccountRegistrar, mContext);
772664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        mCreateConnectionProcessor.process();
773766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    }
774766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon
7755a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal    @Override
7768000845a81fd6a88ff69cb11e1b6dff5f47c2332Ihab Awad    public void handleCreateConnectionSuccess(
7778000845a81fd6a88ff69cb11e1b6dff5f47c2332Ihab Awad            CallIdMapper idMapper,
7788000845a81fd6a88ff69cb11e1b6dff5f47c2332Ihab Awad            ParcelableConnection connection) {
77912d61825cd0d6aa06272db3f77b5e30dce379951Santos Cordon        Log.v(this, "handleCreateConnectionSuccessful %s", connection);
780b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        setTargetPhoneAccount(connection.getPhoneAccount());
78172890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon        setHandle(connection.getHandle(), connection.getHandlePresentation());
78272890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon        setCallerDisplayName(
78372890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon                connection.getCallerDisplayName(), connection.getCallerDisplayNamePresentation());
78407bc5ee853bc9a0b4cd46e0c702888b2c7989392Ihab Awad        setConnectionCapabilities(connection.getConnectionCapabilities());
7856fb37c87836b5245046bd3b14320823ab839a10cIhab Awad        setVideoProvider(connection.getVideoProvider());
786b1a95a77522b2a1c98b378a2e538d819918b7f2cTyler Gunn        setVideoState(connection.getVideoState());
7875be64bc46c23b614d5452ca398a6bb7a512f1887Andrew Lee        setRingbackRequested(connection.isRingbackRequested());
7885be64bc46c23b614d5452ca398a6bb7a512f1887Andrew Lee        setIsVoipAudioMode(connection.getIsVoipAudioMode());
789604a4fe52c7de1347f40aadfba1964e9dcfb223cSailesh Nepal        setStatusHints(connection.getStatusHints());
790664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
7918000845a81fd6a88ff69cb11e1b6dff5f47c2332Ihab Awad        mConferenceableCalls.clear();
7928000845a81fd6a88ff69cb11e1b6dff5f47c2332Ihab Awad        for (String id : connection.getConferenceableConnectionIds()) {
7938000845a81fd6a88ff69cb11e1b6dff5f47c2332Ihab Awad            mConferenceableCalls.add(idMapper.getCall(id));
7948000845a81fd6a88ff69cb11e1b6dff5f47c2332Ihab Awad        }
7958000845a81fd6a88ff69cb11e1b6dff5f47c2332Ihab Awad
7969250e5fa9987c3ab80e11e1955657055f5866539Yorke Lee        if (mIsUnknown) {
7979250e5fa9987c3ab80e11e1955657055f5866539Yorke Lee            for (Listener l : mListeners) {
7989250e5fa9987c3ab80e11e1955657055f5866539Yorke Lee                l.onSuccessfulUnknownCall(this, getStateFromConnectionState(connection.getState()));
7999250e5fa9987c3ab80e11e1955657055f5866539Yorke Lee            }
8009250e5fa9987c3ab80e11e1955657055f5866539Yorke Lee        } else if (mIsIncoming) {
801664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            // We do not handle incoming calls immediately when they are verified by the connection
802664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            // service. We allow the caller-info-query code to execute first so that we can read the
803664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            // direct-to-voicemail property before deciding if we want to show the incoming call to
804664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            // the user or if we want to reject the call.
805664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            mDirectToVoicemailQueryPending = true;
806664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
807664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            // Timeout the direct-to-voicemail lookup execution so that we dont wait too long before
808664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            // showing the user the incoming call screen.
80991d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn            mHandler.postDelayed(mDirectToVoicemailRunnable, Timeouts.getDirectToVoicemailMillis(
81091d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn                    mContext.getContentResolver()));
811664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        } else {
812664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            for (Listener l : mListeners) {
813cde2e5062b1b1689cd8962e28763fa0a35e2476aTyler Gunn                l.onSuccessfulOutgoingCall(this,
814cde2e5062b1b1689cd8962e28763fa0a35e2476aTyler Gunn                        getStateFromConnectionState(connection.getState()));
815664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            }
816766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon        }
8175a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal    }
8185a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal
8195a73b03be0a2a929cf9974578445b90f773937b4Sailesh Nepal    @Override
820701dc006ac11625b55d872f1639107b028933895Andrew Lee    public void handleCreateConnectionFailure(DisconnectCause disconnectCause) {
821fb5560d634aef745466e8869f8acf496447da17bIhab Awad        clearConnectionService();
822701dc006ac11625b55d872f1639107b028933895Andrew Lee        setDisconnectCause(disconnectCause);
823701dc006ac11625b55d872f1639107b028933895Andrew Lee        CallsManager.getInstance().markCallAsDisconnected(this, disconnectCause);
824664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal
8259250e5fa9987c3ab80e11e1955657055f5866539Yorke Lee        if (mIsUnknown) {
8269250e5fa9987c3ab80e11e1955657055f5866539Yorke Lee            for (Listener listener : mListeners) {
8279250e5fa9987c3ab80e11e1955657055f5866539Yorke Lee                listener.onFailedUnknownCall(this);
8289250e5fa9987c3ab80e11e1955657055f5866539Yorke Lee            }
8299250e5fa9987c3ab80e11e1955657055f5866539Yorke Lee        } else if (mIsIncoming) {
830a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shrauner            for (Listener listener : mListeners) {
831a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shrauner                listener.onFailedIncomingCall(this);
832664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            }
833664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        } else {
834a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shrauner            for (Listener listener : mListeners) {
835701dc006ac11625b55d872f1639107b028933895Andrew Lee                listener.onFailedOutgoingCall(this, disconnectCause);
836664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            }
837766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon        }
838766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    }
839766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon
840766d04f7cad00b0b09e39db6835676354acd2cdaSantos Cordon    /**
84174549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad     * Plays the specified DTMF tone.
84274549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad     */
84374549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad    void playDtmfTone(char digit) {
844c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        if (mConnectionService == null) {
845c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            Log.w(this, "playDtmfTone() request on a call without a connection service.");
84674549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad        } else {
847c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            Log.i(this, "Send playDtmfTone to connection service for call %s", this);
848c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            mConnectionService.playDtmfTone(this, digit);
84974549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad        }
85074549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad    }
85174549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad
85274549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad    /**
85374549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad     * Stops playing any currently playing DTMF tone.
85474549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad     */
85574549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad    void stopDtmfTone() {
856c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        if (mConnectionService == null) {
857fd4d7b5c86bb3ae9fc78b6dd820654ab977b7092Jay Shrauner            Log.w(this, "stopDtmfTone() request on a call without a connection service.");
85874549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad        } else {
859c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            Log.i(this, "Send stopDtmfTone to connection service for call %s", this);
860c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            mConnectionService.stopDtmfTone(this);
86174549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad        }
86274549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad    }
86374549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad
864cf5b2918ca58b155911a66222ae5b4d21cb5b8ecSantos Cordon    void disconnect() {
865cf5b2918ca58b155911a66222ae5b4d21cb5b8ecSantos Cordon        disconnect(false);
866cf5b2918ca58b155911a66222ae5b4d21cb5b8ecSantos Cordon    }
867cf5b2918ca58b155911a66222ae5b4d21cb5b8ecSantos Cordon
86874549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad    /**
869c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal     * Attempts to disconnect the call through the connection service.
870049b7b6a8d0cf44d687d827cb57a18fa23358206Santos Cordon     */
871cf5b2918ca58b155911a66222ae5b4d21cb5b8ecSantos Cordon    void disconnect(boolean wasViaNewOutgoingCallBroadcaster) {
872aa47937652d80d8bd19860ec521d28ffea745e63Tyler Gunn        // Track that the call is now locally disconnecting.
873aa47937652d80d8bd19860ec521d28ffea745e63Tyler Gunn        setLocallyDisconnecting(true);
874aa47937652d80d8bd19860ec521d28ffea745e63Tyler Gunn
875fd4d7b5c86bb3ae9fc78b6dd820654ab977b7092Jay Shrauner        if (mState == CallState.NEW || mState == CallState.PRE_DIAL_WAIT ||
876fd4d7b5c86bb3ae9fc78b6dd820654ab977b7092Jay Shrauner                mState == CallState.CONNECTING) {
877682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon            Log.v(this, "Aborting call %s", this);
878cf5b2918ca58b155911a66222ae5b4d21cb5b8ecSantos Cordon            abort(wasViaNewOutgoingCallBroadcaster);
87974d420be72fa30735fe9b7a25715f6db046c0398Santos Cordon        } else if (mState != CallState.ABORTED && mState != CallState.DISCONNECTED) {
880fd4d7b5c86bb3ae9fc78b6dd820654ab977b7092Jay Shrauner            if (mConnectionService == null) {
881fd4d7b5c86bb3ae9fc78b6dd820654ab977b7092Jay Shrauner                Log.e(this, new Exception(), "disconnect() request on a call without a"
882fd4d7b5c86bb3ae9fc78b6dd820654ab977b7092Jay Shrauner                        + " connection service.");
883fd4d7b5c86bb3ae9fc78b6dd820654ab977b7092Jay Shrauner            } else {
884fd4d7b5c86bb3ae9fc78b6dd820654ab977b7092Jay Shrauner                Log.i(this, "Send disconnect to connection service for call: %s", this);
885fd4d7b5c86bb3ae9fc78b6dd820654ab977b7092Jay Shrauner                // The call isn't officially disconnected until the connection service
886fd4d7b5c86bb3ae9fc78b6dd820654ab977b7092Jay Shrauner                // confirms that the call was actually disconnected. Only then is the
887fd4d7b5c86bb3ae9fc78b6dd820654ab977b7092Jay Shrauner                // association between call and connection service severed, see
888fd4d7b5c86bb3ae9fc78b6dd820654ab977b7092Jay Shrauner                // {@link CallsManager#markCallAsDisconnected}.
889fd4d7b5c86bb3ae9fc78b6dd820654ab977b7092Jay Shrauner                mConnectionService.disconnect(this);
890fd4d7b5c86bb3ae9fc78b6dd820654ab977b7092Jay Shrauner            }
891049b7b6a8d0cf44d687d827cb57a18fa23358206Santos Cordon        }
892049b7b6a8d0cf44d687d827cb57a18fa23358206Santos Cordon    }
893049b7b6a8d0cf44d687d827cb57a18fa23358206Santos Cordon
894cf5b2918ca58b155911a66222ae5b4d21cb5b8ecSantos Cordon    void abort(boolean wasViaNewOutgoingCallBroadcaster) {
895752cacbc0b88b9b4cb4ab7bd547e17b5d2690693Sailesh Nepal        if (mCreateConnectionProcessor != null &&
896752cacbc0b88b9b4cb4ab7bd547e17b5d2690693Sailesh Nepal                !mCreateConnectionProcessor.isProcessingComplete()) {
897664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            mCreateConnectionProcessor.abort();
89843df90f875f867e1e5cfd32b0cbc45440606c946Yorke Lee        } else if (mState == CallState.NEW || mState == CallState.PRE_DIAL_WAIT
89943df90f875f867e1e5cfd32b0cbc45440606c946Yorke Lee                || mState == CallState.CONNECTING) {
900cf5b2918ca58b155911a66222ae5b4d21cb5b8ecSantos Cordon            if (wasViaNewOutgoingCallBroadcaster) {
901cf5b2918ca58b155911a66222ae5b4d21cb5b8ecSantos Cordon                // If the cancelation was from NEW_OUTGOING_CALL, then we do not automatically
902cf5b2918ca58b155911a66222ae5b4d21cb5b8ecSantos Cordon                // destroy the call.  Instead, we announce the cancelation and CallsManager handles
903cf5b2918ca58b155911a66222ae5b4d21cb5b8ecSantos Cordon                // it through a timer. Since apps often cancel calls through NEW_OUTGOING_CALL and
904cf5b2918ca58b155911a66222ae5b4d21cb5b8ecSantos Cordon                // then re-dial them quickly using a gateway, allowing the first call to end
905cf5b2918ca58b155911a66222ae5b4d21cb5b8ecSantos Cordon                // causes jank. This timeout allows CallsManager to transition the first call into
906cf5b2918ca58b155911a66222ae5b4d21cb5b8ecSantos Cordon                // the second call so that in-call only ever sees a single call...eliminating the
907cf5b2918ca58b155911a66222ae5b4d21cb5b8ecSantos Cordon                // jank altogether.
908cf5b2918ca58b155911a66222ae5b4d21cb5b8ecSantos Cordon                for (Listener listener : mListeners) {
909cf5b2918ca58b155911a66222ae5b4d21cb5b8ecSantos Cordon                    if (listener.onCanceledViaNewOutgoingCallBroadcast(this)) {
910cf5b2918ca58b155911a66222ae5b4d21cb5b8ecSantos Cordon                        // The first listener to handle this wins. A return value of true means that
911cf5b2918ca58b155911a66222ae5b4d21cb5b8ecSantos Cordon                        // the listener will handle the disconnection process later and so we
912cf5b2918ca58b155911a66222ae5b4d21cb5b8ecSantos Cordon                        // should not continue it here.
913cf5b2918ca58b155911a66222ae5b4d21cb5b8ecSantos Cordon                        setLocallyDisconnecting(false);
914cf5b2918ca58b155911a66222ae5b4d21cb5b8ecSantos Cordon                        return;
915cf5b2918ca58b155911a66222ae5b4d21cb5b8ecSantos Cordon                    }
916cf5b2918ca58b155911a66222ae5b4d21cb5b8ecSantos Cordon                }
917cf5b2918ca58b155911a66222ae5b4d21cb5b8ecSantos Cordon            }
918cf5b2918ca58b155911a66222ae5b4d21cb5b8ecSantos Cordon
919504eb83ea06f4c737a4f4fdbd65aa2450505420cTyler Gunn            handleCreateConnectionFailure(new DisconnectCause(DisconnectCause.CANCELED));
9202d0b331f659e4e95621e738bbddaa38a80a70d4cSantos Cordon        } else {
9212d0b331f659e4e95621e738bbddaa38a80a70d4cSantos Cordon            Log.v(this, "Cannot abort a call which isn't either PRE_DIAL_WAIT or CONNECTING");
922682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon        }
923682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon    }
924682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon
9250b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon    /**
92661d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon     * Answers the call if it is ringing.
92738931d0ad60f00a9f50c90cef446166731f0b871Andrew Lee     *
92838931d0ad60f00a9f50c90cef446166731f0b871Andrew Lee     * @param videoState The video state in which to answer the call.
92961d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon     */
93038931d0ad60f00a9f50c90cef446166731f0b871Andrew Lee    void answer(int videoState) {
931c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        Preconditions.checkNotNull(mConnectionService);
93261d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
93361d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon        // Check to verify that the call is still in the ringing state. A call can change states
9347cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunn        // between the time the user hits 'answer' and Telecom receives the command.
93561d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon        if (isRinging("answer")) {
936c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            // At this point, we are asking the connection service to answer but we don't assume
937c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            // that it will work. Instead, we wait until confirmation from the connectino service
9386fb37c87836b5245046bd3b14320823ab839a10cIhab Awad            // that the call is in a non-STATE_RINGING state before changing the UI. See
939c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            // {@link ConnectionServiceAdapter#setActive} and other set* methods.
94038931d0ad60f00a9f50c90cef446166731f0b871Andrew Lee            mConnectionService.answer(this, videoState);
94161d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon        }
94261d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    }
94361d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
94461d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    /**
94561d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon     * Rejects the call if it is ringing.
946ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     *
947ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * @param rejectWithMessage Whether to send a text message as part of the call rejection.
948ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * @param textMessage An optional text message to send as part of the rejection.
94961d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon     */
950ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    void reject(boolean rejectWithMessage, String textMessage) {
951c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        Preconditions.checkNotNull(mConnectionService);
95261d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
95361d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon        // Check to verify that the call is still in the ringing state. A call can change states
95461d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon        // between the time the user hits 'reject' and Telecomm receives the command.
95561d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon        if (isRinging("reject")) {
956c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            mConnectionService.reject(this);
95761d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon        }
95861d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    }
95961d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
96061d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    /**
961cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee     * Puts the call on hold if it is currently active.
962cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee     */
963cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee    void hold() {
964c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        Preconditions.checkNotNull(mConnectionService);
965cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee
966cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee        if (mState == CallState.ACTIVE) {
967c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            mConnectionService.hold(this);
968cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee        }
969cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee    }
970cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee
971cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee    /**
972cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee     * Releases the call from hold if it is currently active.
973cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee     */
974cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee    void unhold() {
975c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        Preconditions.checkNotNull(mConnectionService);
976cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee
977cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee        if (mState == CallState.ON_HOLD) {
978c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            mConnectionService.unhold(this);
979571f0737002251f09b9ef696dc8b4c9ce02abbaeSantos Cordon        }
9800b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon    }
9810b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon
9826aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal    /** Checks if this is a live call or not. */
9836aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal    boolean isAlive() {
9846aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal        switch (mState) {
9856fb37c87836b5245046bd3b14320823ab839a10cIhab Awad            case CallState.NEW:
9866fb37c87836b5245046bd3b14320823ab839a10cIhab Awad            case CallState.RINGING:
9876fb37c87836b5245046bd3b14320823ab839a10cIhab Awad            case CallState.DISCONNECTED:
9886fb37c87836b5245046bd3b14320823ab839a10cIhab Awad            case CallState.ABORTED:
9896aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal                return false;
9906aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal            default:
9916aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal                return true;
9926aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal        }
9936aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal    }
9946aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal
99540f78c210512570f14cdfde9613dd85c510a1c0cSantos Cordon    boolean isActive() {
99684bfe47a2447c4983bcc58468000f04683eec55bIhab Awad        return mState == CallState.ACTIVE;
99740f78c210512570f14cdfde9613dd85c510a1c0cSantos Cordon    }
99840f78c210512570f14cdfde9613dd85c510a1c0cSantos Cordon
99984fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal    Bundle getExtras() {
100084fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal        return mExtras;
100184fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal    }
100284fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal
100384fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal    void setExtras(Bundle extras) {
100484fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal        mExtras = extras;
100584fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal    }
100684fa5f8c59a1cd3c5716c239fb19c58244fc81feSailesh Nepal
10078a736a887b50d4d042c008b2073e24e1b4681dfbYorke Lee    /**
10088a736a887b50d4d042c008b2073e24e1b4681dfbYorke Lee     * @return the uri of the contact associated with this call.
10098a736a887b50d4d042c008b2073e24e1b4681dfbYorke Lee     */
10108a736a887b50d4d042c008b2073e24e1b4681dfbYorke Lee    Uri getContactUri() {
10118a736a887b50d4d042c008b2073e24e1b4681dfbYorke Lee        if (mCallerInfo == null || !mCallerInfo.contactExists) {
1012a7fa743f76242e9f039eea2fea0911f59255522eYorke Lee            return getHandle();
10138a736a887b50d4d042c008b2073e24e1b4681dfbYorke Lee        }
10148a736a887b50d4d042c008b2073e24e1b4681dfbYorke Lee        return Contacts.getLookupUri(mCallerInfo.contactIdOrZero, mCallerInfo.lookupKey);
10158a736a887b50d4d042c008b2073e24e1b4681dfbYorke Lee    }
10168a736a887b50d4d042c008b2073e24e1b4681dfbYorke Lee
10175ba7f27491e287f39a999ddd3d1ed6a7bad78272Santos Cordon    Uri getRingtone() {
10185ba7f27491e287f39a999ddd3d1ed6a7bad78272Santos Cordon        return mCallerInfo == null ? null : mCallerInfo.contactRingtoneUri;
10195ba7f27491e287f39a999ddd3d1ed6a7bad78272Santos Cordon    }
10205ba7f27491e287f39a999ddd3d1ed6a7bad78272Santos Cordon
1021352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton    void onPostDialWait(String remaining) {
1022352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton        for (Listener l : mListeners) {
1023352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton            l.onPostDialWait(this, remaining);
1024352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton        }
1025352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton    }
1026352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton
1027a469f76c1710a945933910840f11f9fda0445d82Nancy Chen    void onPostDialChar(char nextChar) {
1028a469f76c1710a945933910840f11f9fda0445d82Nancy Chen        for (Listener l : mListeners) {
1029a469f76c1710a945933910840f11f9fda0445d82Nancy Chen            l.onPostDialChar(this, nextChar);
1030a469f76c1710a945933910840f11f9fda0445d82Nancy Chen        }
1031a469f76c1710a945933910840f11f9fda0445d82Nancy Chen    }
1032a469f76c1710a945933910840f11f9fda0445d82Nancy Chen
1033352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton    void postDialContinue(boolean proceed) {
1034c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        mConnectionService.onPostDialContinue(this, proceed);
1035352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton    }
1036352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton
10370fbe6321e341ddce186634266dba2db3fa426b88Santos Cordon    void conferenceWith(Call otherCall) {
1038c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        if (mConnectionService == null) {
1039c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            Log.w(this, "conference requested on a call without a connection service.");
1040a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        } else {
10410fbe6321e341ddce186634266dba2db3fa426b88Santos Cordon            mConnectionService.conference(this, otherCall);
1042a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        }
1043a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    }
1044a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
1045a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    void splitFromConference() {
1046672321e603555849831dd88d5c9f93d88143ee48Santos Cordon        if (mConnectionService == null) {
1047672321e603555849831dd88d5c9f93d88143ee48Santos Cordon            Log.w(this, "splitting from conference call without a connection service");
1048672321e603555849831dd88d5c9f93d88143ee48Santos Cordon        } else {
1049672321e603555849831dd88d5c9f93d88143ee48Santos Cordon            mConnectionService.splitFromConference(this);
1050672321e603555849831dd88d5c9f93d88143ee48Santos Cordon        }
1051a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    }
1052a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
10536805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon    void mergeConference() {
10546805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon        if (mConnectionService == null) {
10556805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon            Log.w(this, "merging conference calls without a connection service.");
105607bc5ee853bc9a0b4cd46e0c702888b2c7989392Ihab Awad        } else if (can(Connection.CAPABILITY_MERGE_CONFERENCE)) {
10576805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon            mConnectionService.mergeConference(this);
105888a4a60284de8e1222488667b810b098c16d22acSantos Cordon            mWasConferencePreviouslyMerged = true;
10596805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon        }
10606805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon    }
10616805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon
10626805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon    void swapConference() {
10636805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon        if (mConnectionService == null) {
10646805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon            Log.w(this, "swapping conference calls without a connection service.");
106507bc5ee853bc9a0b4cd46e0c702888b2c7989392Ihab Awad        } else if (can(Connection.CAPABILITY_SWAP_CONFERENCE)) {
10666805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon            mConnectionService.swapConference(this);
106788a4a60284de8e1222488667b810b098c16d22acSantos Cordon            switch (mChildCalls.size()) {
106888a4a60284de8e1222488667b810b098c16d22acSantos Cordon                case 1:
106988a4a60284de8e1222488667b810b098c16d22acSantos Cordon                    mConferenceLevelActiveCall = mChildCalls.get(0);
107088a4a60284de8e1222488667b810b098c16d22acSantos Cordon                    break;
107188a4a60284de8e1222488667b810b098c16d22acSantos Cordon                case 2:
107288a4a60284de8e1222488667b810b098c16d22acSantos Cordon                    // swap
107388a4a60284de8e1222488667b810b098c16d22acSantos Cordon                    mConferenceLevelActiveCall = mChildCalls.get(0) == mConferenceLevelActiveCall ?
107488a4a60284de8e1222488667b810b098c16d22acSantos Cordon                            mChildCalls.get(1) : mChildCalls.get(0);
107588a4a60284de8e1222488667b810b098c16d22acSantos Cordon                    break;
107688a4a60284de8e1222488667b810b098c16d22acSantos Cordon                default:
107788a4a60284de8e1222488667b810b098c16d22acSantos Cordon                    // For anything else 0, or 3+, set it to null since it is impossible to tell.
107888a4a60284de8e1222488667b810b098c16d22acSantos Cordon                    mConferenceLevelActiveCall = null;
107988a4a60284de8e1222488667b810b098c16d22acSantos Cordon                    break;
108088a4a60284de8e1222488667b810b098c16d22acSantos Cordon            }
10816805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon        }
10826805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon    }
10836805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon
1084a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    void setParentCall(Call parentCall) {
1085a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        if (parentCall == this) {
1086a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            Log.e(this, new Exception(), "setting the parent to self");
1087a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            return;
1088a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        }
10890fbe6321e341ddce186634266dba2db3fa426b88Santos Cordon        if (parentCall == mParentCall) {
10900fbe6321e341ddce186634266dba2db3fa426b88Santos Cordon            // nothing to do
10910fbe6321e341ddce186634266dba2db3fa426b88Santos Cordon            return;
10920fbe6321e341ddce186634266dba2db3fa426b88Santos Cordon        }
1093a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        Preconditions.checkState(parentCall == null || mParentCall == null);
1094a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
1095a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        Call oldParent = mParentCall;
1096a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        if (mParentCall != null) {
1097a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            mParentCall.removeChildCall(this);
1098a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        }
1099a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        mParentCall = parentCall;
1100a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        if (mParentCall != null) {
1101a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            mParentCall.addChildCall(this);
1102a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        }
1103a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
1104a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        for (Listener l : mListeners) {
1105a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            l.onParentChanged(this);
1106a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        }
1107a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    }
1108a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
110912d61825cd0d6aa06272db3f77b5e30dce379951Santos Cordon    void setConferenceableCalls(List<Call> conferenceableCalls) {
111012d61825cd0d6aa06272db3f77b5e30dce379951Santos Cordon        mConferenceableCalls.clear();
111112d61825cd0d6aa06272db3f77b5e30dce379951Santos Cordon        mConferenceableCalls.addAll(conferenceableCalls);
1112703d7cfdab59f84221fd803dd5810bea0e26cc56Tyler Gunn
1113703d7cfdab59f84221fd803dd5810bea0e26cc56Tyler Gunn        for (Listener l : mListeners) {
1114703d7cfdab59f84221fd803dd5810bea0e26cc56Tyler Gunn            l.onConferenceableCallsChanged(this);
1115703d7cfdab59f84221fd803dd5810bea0e26cc56Tyler Gunn        }
111612d61825cd0d6aa06272db3f77b5e30dce379951Santos Cordon    }
111712d61825cd0d6aa06272db3f77b5e30dce379951Santos Cordon
111812d61825cd0d6aa06272db3f77b5e30dce379951Santos Cordon    List<Call> getConferenceableCalls() {
111912d61825cd0d6aa06272db3f77b5e30dce379951Santos Cordon        return mConferenceableCalls;
112012d61825cd0d6aa06272db3f77b5e30dce379951Santos Cordon    }
112112d61825cd0d6aa06272db3f77b5e30dce379951Santos Cordon
1122f193ba45fae5bc87e6a57779e4f5b56be59d08b0Santos Cordon    boolean can(int capability) {
112307bc5ee853bc9a0b4cd46e0c702888b2c7989392Ihab Awad        return (mConnectionCapabilities & capability) == capability;
11246805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon    }
11256805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon
1126a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    private void addChildCall(Call call) {
1127a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        if (!mChildCalls.contains(call)) {
112888a4a60284de8e1222488667b810b098c16d22acSantos Cordon            // Set the pseudo-active call to the latest child added to the conference.
112988a4a60284de8e1222488667b810b098c16d22acSantos Cordon            // See definition of mConferenceLevelActiveCall for more detail.
113088a4a60284de8e1222488667b810b098c16d22acSantos Cordon            mConferenceLevelActiveCall = call;
1131a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            mChildCalls.add(call);
1132a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
1133a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            for (Listener l : mListeners) {
1134a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon                l.onChildrenChanged(this);
1135a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            }
1136a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        }
1137a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    }
1138a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
1139a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    private void removeChildCall(Call call) {
1140a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        if (mChildCalls.remove(call)) {
1141a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            for (Listener l : mListeners) {
1142a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon                l.onChildrenChanged(this);
1143a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            }
1144a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        }
1145a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    }
1146a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
11470b03b4b143234302f098ea18de3c32658b455ecaSantos Cordon    /**
1148ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * Return whether the user can respond to this {@code Call} via an SMS message.
1149ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     *
1150ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * @return true if the "Respond via SMS" feature should be enabled
1151ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * for this incoming call.
1152ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     *
1153ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * The general rule is that we *do* allow "Respond via SMS" except for
1154ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * the few (relatively rare) cases where we know for sure it won't
1155ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * work, namely:
1156ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     *   - a bogus or blank incoming number
1157ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     *   - a call from a SIP address
1158ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     *   - a "call presentation" that doesn't allow the number to be revealed
1159ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     *
1160ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * In all other cases, we allow the user to respond via SMS.
1161ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     *
1162ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * Note that this behavior isn't perfect; for example we have no way
1163ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * to detect whether the incoming call is from a landline (with most
1164ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * networks at least), so we still enable this feature even though
1165ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     * SMSes to that number will silently fail.
1166ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad     */
1167ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    boolean isRespondViaSmsCapable() {
1168ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        if (mState != CallState.RINGING) {
1169ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            return false;
1170ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        }
1171ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad
1172ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        if (getHandle() == null) {
1173ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            // No incoming number known or call presentation is "PRESENTATION_RESTRICTED", in
1174ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            // other words, the user should not be able to see the incoming phone number.
1175ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            return false;
1176ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        }
1177ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad
1178ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        if (PhoneNumberUtils.isUriNumber(getHandle().toString())) {
1179ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            // The incoming number is actually a URI (i.e. a SIP address),
1180ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            // not a regular PSTN phone number, and we can't send SMSes to
1181ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            // SIP addresses.
1182ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            // (TODO: That might still be possible eventually, though. Is
1183ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            // there some SIP-specific equivalent to sending a text message?)
1184ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            return false;
1185ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        }
1186ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad
1187ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        // Is there a valid SMS application on the phone?
118891d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn        if (SmsApplication.getDefaultRespondViaMessageApplication(mContext,
1189ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                true /*updateIfNeeded*/) == null) {
1190ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            return false;
1191ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        }
1192ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad
1193ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        // TODO: with some carriers (in certain countries) you *can* actually
1194ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        // tell whether a given number is a mobile phone or not. So in that
1195ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        // case we could potentially return false here if the incoming call is
1196ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        // from a land line.
1197ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad
1198ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        // If none of the above special cases apply, it's OK to enable the
1199ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        // "Respond via SMS" feature.
1200ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        return true;
1201ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    }
1202ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad
1203ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    List<String> getCannedSmsResponses() {
1204ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        return mCannedSmsResponses;
1205ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    }
1206ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad
1207ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    /**
1208672321e603555849831dd88d5c9f93d88143ee48Santos Cordon     * We need to make sure that before we move a call to the disconnected state, it no
1209672321e603555849831dd88d5c9f93d88143ee48Santos Cordon     * longer has any parent/child relationships.  We want to do this to ensure that the InCall
12107cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunn     * Service always has the right data in the right order.  We also want to do it in telecom so
1211672321e603555849831dd88d5c9f93d88143ee48Santos Cordon     * that the insurance policy lives in the framework side of things.
1212672321e603555849831dd88d5c9f93d88143ee48Santos Cordon     */
1213672321e603555849831dd88d5c9f93d88143ee48Santos Cordon    private void fixParentAfterDisconnect() {
1214672321e603555849831dd88d5c9f93d88143ee48Santos Cordon        setParentCall(null);
1215672321e603555849831dd88d5c9f93d88143ee48Santos Cordon    }
1216672321e603555849831dd88d5c9f93d88143ee48Santos Cordon
1217672321e603555849831dd88d5c9f93d88143ee48Santos Cordon    /**
121861d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon     * @return True if the call is ringing, else logs the action name.
121961d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon     */
122061d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    private boolean isRinging(String actionName) {
122161d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon        if (mState == CallState.RINGING) {
122261d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon            return true;
122361d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon        }
122461d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
1225f1c191d3974fed3f57680c63571ae0212c4622e7Sailesh Nepal        Log.i(this, "Request to %s a non-ringing call %s", actionName, this);
122661d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon        return false;
122761d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    }
122861d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
12298e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad    @SuppressWarnings("rawtypes")
12308e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad    private void decrementAssociatedCallCount(ServiceBinder binder) {
12318e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad        if (binder != null) {
12328e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad            binder.decrementAssociatedCallCount();
12338e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad        }
12348e55d1d7ea86f768acb90f88dc9e5b5368d3398aBen Gilad    }
1235fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon
1236fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    /**
1237fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon     * Looks up contact information based on the current handle.
1238fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon     */
1239fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    private void startCallerInfoLookup() {
1240fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon        String number = mHandle == null ? null : mHandle.getSchemeSpecificPart();
1241fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon
1242fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon        mQueryToken++;  // Updated so that previous queries can no longer set the information.
1243fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon        mCallerInfo = null;
1244fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon        if (!TextUtils.isEmpty(number)) {
12455ba7f27491e287f39a999ddd3d1ed6a7bad78272Santos Cordon            Log.v(this, "Looking up information for: %s.", Log.piiHandle(number));
1246fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon            CallerInfoAsyncQuery.startQuery(
1247fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon                    mQueryToken,
124891d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn                    mContext,
1249fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon                    number,
1250fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon                    sCallerInfoQueryListener,
1251fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon                    this);
1252fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon        }
1253fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    }
1254fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon
1255fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    /**
125699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon     * Saves the specified caller info if the specified token matches that of the last query
1257fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon     * that was made.
1258fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon     *
1259fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon     * @param callerInfo The new caller information to set.
1260fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon     * @param token The token used with this query.
1261fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon     */
1262fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    private void setCallerInfo(CallerInfo callerInfo, int token) {
1263e4a9c412f5c6f76f006659f0b4e171ef4547dc45Yorke Lee        Trace.beginSection("setCallerInfo");
126499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon        Preconditions.checkNotNull(callerInfo);
126599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon
1266fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon        if (mQueryToken == token) {
1267fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon            mCallerInfo = callerInfo;
12685ba7f27491e287f39a999ddd3d1ed6a7bad78272Santos Cordon            Log.i(this, "CallerInfo received for %s: %s", Log.piiHandle(mHandle), callerInfo);
126999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon
1270a1662d0ae89d9fb514a5ac68cbc76660e34dae00Makoto Onuki            if (mCallerInfo.contactDisplayPhotoUri != null) {
1271a1662d0ae89d9fb514a5ac68cbc76660e34dae00Makoto Onuki                Log.d(this, "Searching person uri %s for call %s",
1272a1662d0ae89d9fb514a5ac68cbc76660e34dae00Makoto Onuki                        mCallerInfo.contactDisplayPhotoUri, this);
127399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                ContactsAsyncHelper.startObtainPhotoAsync(
127499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                        token,
127591d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn                        mContext,
1276a1662d0ae89d9fb514a5ac68cbc76660e34dae00Makoto Onuki                        mCallerInfo.contactDisplayPhotoUri,
127799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                        sPhotoLoadListener,
127899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon                        this);
1279a1662d0ae89d9fb514a5ac68cbc76660e34dae00Makoto Onuki                // Do not call onCallerInfoChanged yet in this case.  We call it in setPhoto().
128064c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon            } else {
128164c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon                for (Listener l : mListeners) {
128264c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon                    l.onCallerInfoChanged(this);
128364c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon                }
128499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon            }
12852174fb56907fddf5680355e097f4425f837983e2Santos Cordon
12862174fb56907fddf5680355e097f4425f837983e2Santos Cordon            processDirectToVoicemail();
128799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon        }
1288e4a9c412f5c6f76f006659f0b4e171ef4547dc45Yorke Lee        Trace.endSection();
128999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon    }
129099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon
12916f3f7affb13e93cb70868d3114f02f1ed593194eYorke Lee    CallerInfo getCallerInfo() {
12926f3f7affb13e93cb70868d3114f02f1ed593194eYorke Lee        return mCallerInfo;
12936f3f7affb13e93cb70868d3114f02f1ed593194eYorke Lee    }
12946f3f7affb13e93cb70868d3114f02f1ed593194eYorke Lee
129599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon    /**
129699c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon     * Saves the specified photo information if the specified token matches that of the last query.
129799c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon     *
129899c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon     * @param photo The photo as a drawable.
129999c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon     * @param photoIcon The photo as a small icon.
130099c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon     * @param token The token used with this query.
130199c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon     */
130299c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon    private void setPhoto(Drawable photo, Bitmap photoIcon, int token) {
130399c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon        if (mQueryToken == token) {
130499c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon            mCallerInfo.cachedPhoto = photo;
130599c8a6fc0ae4c50878a748280a0ae2d8dd6b040eSantos Cordon            mCallerInfo.cachedPhotoIcon = photoIcon;
130664c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon
130764c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon            for (Listener l : mListeners) {
130864c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon                l.onCallerInfoChanged(this);
130964c7e965de50c6321415942ab4a84d22514b39a1Santos Cordon            }
1310fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon        }
1311fd71f4adb6f04ab485563133f5ccf541de04b002Santos Cordon    }
1312ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad
1313ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    private void maybeLoadCannedSmsResponses() {
1314ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        if (mIsIncoming && isRespondViaSmsCapable() && !mCannedSmsResponsesLoadingStarted) {
1315ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            Log.d(this, "maybeLoadCannedSmsResponses: starting task to load messages");
1316ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            mCannedSmsResponsesLoadingStarted = true;
1317ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            RespondViaSmsManager.getInstance().loadCannedTextMessages(
1318ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                    new Response<Void, List<String>>() {
1319ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                        @Override
1320ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                        public void onResult(Void request, List<String>... result) {
1321ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                            if (result.length > 0) {
1322ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                                Log.d(this, "maybeLoadCannedSmsResponses: got %s", result[0]);
1323ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                                mCannedSmsResponses = result[0];
1324ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                                for (Listener l : mListeners) {
1325ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                                    l.onCannedSmsResponsesLoaded(Call.this);
1326ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                                }
1327ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                            }
1328ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                        }
1329ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad
1330ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                        @Override
1331ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                        public void onError(Void request, int code, String msg) {
1332ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                            Log.w(Call.this, "Error obtaining canned SMS responses: %d %s", code,
1333ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                                    msg);
1334ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad                        }
133591d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn                    },
133691d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn                    mContext
1337ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            );
1338ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        } else {
1339ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad            Log.d(this, "maybeLoadCannedSmsResponses: doing nothing");
1340ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad        }
1341ff7493a8f620509d41dd8a5106c1d0dcd27cd274Ihab Awad    }
1342b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati
1343b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati    /**
1344b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati     * Sets speakerphone option on when call begins.
1345b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati     */
1346b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati    public void setStartWithSpeakerphoneOn(boolean startWithSpeakerphone) {
1347b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati        mSpeakerphoneOn = startWithSpeakerphone;
1348b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati    }
1349b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati
1350b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati    /**
1351b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati     * Returns speakerphone option.
1352b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati     *
1353b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati     * @return Whether or not speakerphone should be set automatically when call begins.
1354b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati     */
1355b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati    public boolean getStartWithSpeakerphoneOn() {
1356b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati        return mSpeakerphoneOn;
1357b7157e9f7dbf151c4c6ff4ebcc171632af00616eSai Cheemalapati    }
1358e9a776560dfe6f000cfc0dc1ea36c0f37d937f53Andrew Lee
1359e9a776560dfe6f000cfc0dc1ea36c0f37d937f53Andrew Lee    /**
13603bcf935b25470e94c8c6855862434d15b785c54aAndrew Lee     * Sets a video call provider for the call.
1361e9a776560dfe6f000cfc0dc1ea36c0f37d937f53Andrew Lee     */
13626fb37c87836b5245046bd3b14320823ab839a10cIhab Awad    public void setVideoProvider(IVideoProvider videoProvider) {
13636fb37c87836b5245046bd3b14320823ab839a10cIhab Awad        mVideoProvider = videoProvider;
1364a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen        for (Listener l : mListeners) {
13653bcf935b25470e94c8c6855862434d15b785c54aAndrew Lee            l.onVideoCallProviderChanged(Call.this);
1366a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen        }
1367a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen    }
1368a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen
1369a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen    /**
13706fb37c87836b5245046bd3b14320823ab839a10cIhab Awad     * @return Return the {@link Connection.VideoProvider} binder.
1371a65d41fb134e323ab43c3f9454313b262959b1d0Nancy Chen     */
13726fb37c87836b5245046bd3b14320823ab839a10cIhab Awad    public IVideoProvider getVideoProvider() {
13736fb37c87836b5245046bd3b14320823ab839a10cIhab Awad        return mVideoProvider;
1374e9a776560dfe6f000cfc0dc1ea36c0f37d937f53Andrew Lee    }
1375e19cc005ddbff5313d6f7288587630b2410d005cTyler Gunn
1376e19cc005ddbff5313d6f7288587630b2410d005cTyler Gunn    /**
1377c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn     * The current video state for the call.
13786fb37c87836b5245046bd3b14320823ab839a10cIhab Awad     * Valid values: see {@link VideoProfile.VideoState}.
1379c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn     */
1380c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn    public int getVideoState() {
1381c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn        return mVideoState;
1382c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn    }
1383c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn
1384c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn    /**
13850a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn     * Returns the video states which were applicable over the duration of a call.
13866fb37c87836b5245046bd3b14320823ab839a10cIhab Awad     * See {@link VideoProfile} for a list of valid video states.
13870a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn     *
13880a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn     * @return The video states applicable over the duration of the call.
13890a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn     */
13900a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn    public int getVideoStateHistory() {
13910a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn        return mVideoStateHistory;
13920a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn    }
13930a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn
13940a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn    /**
13950a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn     * Determines the current video state for the call.
13960a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn     * For an outgoing call determines the desired video state for the call.
13976fb37c87836b5245046bd3b14320823ab839a10cIhab Awad     * Valid values: see {@link VideoProfile.VideoState}
1398c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn     *
13990a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn     * @param videoState The video state for the call.
1400c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn     */
1401c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn    public void setVideoState(int videoState) {
14020a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn        // Track which video states were applicable over the duration of the call.
14030a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn        mVideoStateHistory = mVideoStateHistory | videoState;
14040a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn
1405c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn        mVideoState = videoState;
14064a79660c984d54679ad4d2bdc89e224d9c8c375bAndrew Lee        for (Listener l : mListeners) {
14074a79660c984d54679ad4d2bdc89e224d9c8c375bAndrew Lee            l.onVideoStateChanged(this);
14084a79660c984d54679ad4d2bdc89e224d9c8c375bAndrew Lee        }
1409c4abd91cd8a67b530ebafe146af10136db8e6605Tyler Gunn    }
14107e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal
14115be64bc46c23b614d5452ca398a6bb7a512f1887Andrew Lee    public boolean getIsVoipAudioMode() {
14125be64bc46c23b614d5452ca398a6bb7a512f1887Andrew Lee        return mIsVoipAudioMode;
14137e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal    }
14147e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal
14155be64bc46c23b614d5452ca398a6bb7a512f1887Andrew Lee    public void setIsVoipAudioMode(boolean audioModeIsVoip) {
14165be64bc46c23b614d5452ca398a6bb7a512f1887Andrew Lee        mIsVoipAudioMode = audioModeIsVoip;
14177e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal        for (Listener l : mListeners) {
14185be64bc46c23b614d5452ca398a6bb7a512f1887Andrew Lee            l.onIsVoipAudioModeChanged(this);
141935faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal        }
142035faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal    }
142135faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal
142235faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal    public StatusHints getStatusHints() {
142335faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal        return mStatusHints;
142435faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal    }
142535faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal
142635faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal    public void setStatusHints(StatusHints statusHints) {
142735faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal        mStatusHints = statusHints;
142835faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal        for (Listener l : mListeners) {
142935faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal            l.onStatusHintsChanged(this);
14307e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal        }
14317e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal    }
14329d58de5df05d0358fc8ae57ab7e9a0c45337c602Sailesh Nepal
14339250e5fa9987c3ab80e11e1955657055f5866539Yorke Lee    public boolean isUnknown() {
14349250e5fa9987c3ab80e11e1955657055f5866539Yorke Lee        return mIsUnknown;
14359250e5fa9987c3ab80e11e1955657055f5866539Yorke Lee    }
14369250e5fa9987c3ab80e11e1955657055f5866539Yorke Lee
14379250e5fa9987c3ab80e11e1955657055f5866539Yorke Lee    public void setIsUnknown(boolean isUnknown) {
14389250e5fa9987c3ab80e11e1955657055f5866539Yorke Lee        mIsUnknown = isUnknown;
14399250e5fa9987c3ab80e11e1955657055f5866539Yorke Lee    }
14409250e5fa9987c3ab80e11e1955657055f5866539Yorke Lee
1441aa47937652d80d8bd19860ec521d28ffea745e63Tyler Gunn    /**
1442aa47937652d80d8bd19860ec521d28ffea745e63Tyler Gunn     * Determines if this call is in a disconnecting state.
1443aa47937652d80d8bd19860ec521d28ffea745e63Tyler Gunn     *
1444aa47937652d80d8bd19860ec521d28ffea745e63Tyler Gunn     * @return {@code true} if this call is locally disconnecting.
1445aa47937652d80d8bd19860ec521d28ffea745e63Tyler Gunn     */
1446aa47937652d80d8bd19860ec521d28ffea745e63Tyler Gunn    public boolean isLocallyDisconnecting() {
1447aa47937652d80d8bd19860ec521d28ffea745e63Tyler Gunn        return mIsLocallyDisconnecting;
1448aa47937652d80d8bd19860ec521d28ffea745e63Tyler Gunn    }
1449aa47937652d80d8bd19860ec521d28ffea745e63Tyler Gunn
1450aa47937652d80d8bd19860ec521d28ffea745e63Tyler Gunn    /**
1451aa47937652d80d8bd19860ec521d28ffea745e63Tyler Gunn     * Sets whether this call is in a disconnecting state.
1452aa47937652d80d8bd19860ec521d28ffea745e63Tyler Gunn     *
1453aa47937652d80d8bd19860ec521d28ffea745e63Tyler Gunn     * @param isLocallyDisconnecting {@code true} if this call is locally disconnecting.
1454aa47937652d80d8bd19860ec521d28ffea745e63Tyler Gunn     */
1455aa47937652d80d8bd19860ec521d28ffea745e63Tyler Gunn    private void setLocallyDisconnecting(boolean isLocallyDisconnecting) {
1456aa47937652d80d8bd19860ec521d28ffea745e63Tyler Gunn        mIsLocallyDisconnecting = isLocallyDisconnecting;
1457aa47937652d80d8bd19860ec521d28ffea745e63Tyler Gunn    }
1458aa47937652d80d8bd19860ec521d28ffea745e63Tyler Gunn
14590fbe6321e341ddce186634266dba2db3fa426b88Santos Cordon    static int getStateFromConnectionState(int state) {
146072890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon        switch (state) {
1461a02bef5d67f261d7457d0dab9e51595f1960128bIhab Awad            case Connection.STATE_INITIALIZING:
1462a02bef5d67f261d7457d0dab9e51595f1960128bIhab Awad                return CallState.CONNECTING;
14636fb37c87836b5245046bd3b14320823ab839a10cIhab Awad            case Connection.STATE_ACTIVE:
146472890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon                return CallState.ACTIVE;
14656fb37c87836b5245046bd3b14320823ab839a10cIhab Awad            case Connection.STATE_DIALING:
146672890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon                return CallState.DIALING;
14676fb37c87836b5245046bd3b14320823ab839a10cIhab Awad            case Connection.STATE_DISCONNECTED:
146872890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon                return CallState.DISCONNECTED;
14696fb37c87836b5245046bd3b14320823ab839a10cIhab Awad            case Connection.STATE_HOLDING:
147072890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon                return CallState.ON_HOLD;
14716fb37c87836b5245046bd3b14320823ab839a10cIhab Awad            case Connection.STATE_NEW:
147272890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon                return CallState.NEW;
14736fb37c87836b5245046bd3b14320823ab839a10cIhab Awad            case Connection.STATE_RINGING:
147472890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon                return CallState.RINGING;
147572890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon        }
147672890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon        return CallState.DISCONNECTED;
147772890ce844f92f45c56f3cccd1f2fd03ff12c3c2Santos Cordon    }
14789f2bed31374a56487f370be01224baf6ce97e8adBen Gilad}
1479