ImsCall.java revision 1463174fa4bab35f04dfa71196c277dfeb603717
1ef36ef67e009449300b0150c60c9f637e205d79eWink Saville/*
2ef36ef67e009449300b0150c60c9f637e205d79eWink Saville * Copyright (c) 2013 The Android Open Source Project
3ef36ef67e009449300b0150c60c9f637e205d79eWink Saville *
4ef36ef67e009449300b0150c60c9f637e205d79eWink Saville * Licensed under the Apache License, Version 2.0 (the "License");
5ef36ef67e009449300b0150c60c9f637e205d79eWink Saville * you may not use this file except in compliance with the License.
6ef36ef67e009449300b0150c60c9f637e205d79eWink Saville * You may obtain a copy of the License at
7ef36ef67e009449300b0150c60c9f637e205d79eWink Saville *
8ef36ef67e009449300b0150c60c9f637e205d79eWink Saville *      http://www.apache.org/licenses/LICENSE-2.0
9ef36ef67e009449300b0150c60c9f637e205d79eWink Saville *
10ef36ef67e009449300b0150c60c9f637e205d79eWink Saville * Unless required by applicable law or agreed to in writing, software
11ef36ef67e009449300b0150c60c9f637e205d79eWink Saville * distributed under the License is distributed on an "AS IS" BASIS,
12ef36ef67e009449300b0150c60c9f637e205d79eWink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ef36ef67e009449300b0150c60c9f637e205d79eWink Saville * See the License for the specific language governing permissions and
14ef36ef67e009449300b0150c60c9f637e205d79eWink Saville * limitations under the License.
15ef36ef67e009449300b0150c60c9f637e205d79eWink Saville */
16ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
17ef36ef67e009449300b0150c60c9f637e205d79eWink Savillepackage com.android.ims;
18ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
19ca45f58a57eb782153c034ae067f59c0018799caUma Maheswari Ramalingamimport com.android.internal.R;
20ca45f58a57eb782153c034ae067f59c0018799caUma Maheswari Ramalingam
211c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunnimport java.util.ArrayList;
22ef36ef67e009449300b0150c60c9f637e205d79eWink Savilleimport java.util.Iterator;
231c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunnimport java.util.List;
24ef36ef67e009449300b0150c60c9f637e205d79eWink Savilleimport java.util.Map.Entry;
25ef36ef67e009449300b0150c60c9f637e205d79eWink Savilleimport java.util.Set;
26ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
27ef36ef67e009449300b0150c60c9f637e205d79eWink Savilleimport android.content.Context;
285965614f5b813f2739722589f84cec69c572b0a2Tyler Gunnimport android.net.Uri;
29ef36ef67e009449300b0150c60c9f637e205d79eWink Savilleimport android.os.Bundle;
30ef36ef67e009449300b0150c60c9f637e205d79eWink Savilleimport android.os.Message;
315965614f5b813f2739722589f84cec69c572b0a2Tyler Gunnimport android.telecom.ConferenceParticipant;
32ef36ef67e009449300b0150c60c9f637e205d79eWink Savilleimport android.telephony.Rlog;
339bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunnimport android.util.Log;
34ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
35ef36ef67e009449300b0150c60c9f637e205d79eWink Savilleimport com.android.ims.internal.ICall;
36ef36ef67e009449300b0150c60c9f637e205d79eWink Savilleimport com.android.ims.internal.ImsCallSession;
37ef36ef67e009449300b0150c60c9f637e205d79eWink Savilleimport com.android.ims.internal.ImsStreamMediaSession;
38938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunnimport com.android.internal.annotations.VisibleForTesting;
39ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
40ef36ef67e009449300b0150c60c9f637e205d79eWink Saville/**
41ef36ef67e009449300b0150c60c9f637e205d79eWink Saville * Handles an IMS voice / video call over LTE. You can instantiate this class with
42ef36ef67e009449300b0150c60c9f637e205d79eWink Saville * {@link ImsManager}.
43ef36ef67e009449300b0150c60c9f637e205d79eWink Saville *
44ef36ef67e009449300b0150c60c9f637e205d79eWink Saville * @hide
45ef36ef67e009449300b0150c60c9f637e205d79eWink Saville */
46ef36ef67e009449300b0150c60c9f637e205d79eWink Savillepublic class ImsCall implements ICall {
47ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // Mode of USSD message
48ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public static final int USSD_MODE_NOTIFY = 0;
49ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public static final int USSD_MODE_REQUEST = 1;
50ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
51ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final String TAG = "ImsCall";
526cb99be298f8b1b4363fdacc1cc631c3671380ecTyler Gunn    private static final boolean FORCE_DEBUG = false; /* STOPSHIP if true */
539bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    private static final boolean DBG = FORCE_DEBUG || Rlog.isLoggable(TAG, Log.DEBUG);
549bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    private static final boolean VDBG = FORCE_DEBUG || Rlog.isLoggable(TAG, Log.VERBOSE);
55ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
56ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
57ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Listener for events relating to an IMS call, such as when a call is being
58c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * received ("on ringing") or a call is outgoing ("on calling").
59ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * <p>Many of these events are also received by {@link ImsCallSession.Listener}.</p>
60ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
61ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public static class Listener {
62ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
63ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when a request is sent out to initiate a new call
64ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * and 1xx response is received from the network.
65ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
66ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
67ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
68ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
69ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallProgressing(ImsCall call) {
70ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallStateChanged(call);
71ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
72ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
73ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
74ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call is established.
75ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
76ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
77ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
78ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
79ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallStarted(ImsCall call) {
80ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallStateChanged(call);
81ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
82ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
83ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
84ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call setup is failed.
85ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallError}.
86ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
87ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
88ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the call setup failure
89ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
90ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallStartFailed(ImsCall call, ImsReasonInfo reasonInfo) {
91ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallError(call, reasonInfo);
92ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
93ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
94ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
95ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call is terminated.
96ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
97ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
98ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
99ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the call termination
100ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
101ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallTerminated(ImsCall call, ImsReasonInfo reasonInfo) {
102ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // Store the call termination reason
103ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
104ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallStateChanged(call);
105ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
106ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
107ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
108ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call is in hold.
109ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
110ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
111ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
112ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
113ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallHeld(ImsCall call) {
114ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallStateChanged(call);
115ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
116ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
117ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
118ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call hold is failed.
119ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallError}.
120ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
121ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
122ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the call hold failure
123ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
124ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallHoldFailed(ImsCall call, ImsReasonInfo reasonInfo) {
125ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallError(call, reasonInfo);
126ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
127ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
128ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
129ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call hold is received from the remote user.
130ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
131ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
132ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
133ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
134ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallHoldReceived(ImsCall call) {
135ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallStateChanged(call);
136ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
137ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
138ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
139ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call is in call.
140ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
141ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
142ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
143ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
144ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallResumed(ImsCall call) {
145ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallStateChanged(call);
146ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
147ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
148ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
149ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call resume is failed.
150ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallError}.
151ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
152ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
153ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the call resume failure
154ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
155ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallResumeFailed(ImsCall call, ImsReasonInfo reasonInfo) {
156ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallError(call, reasonInfo);
157ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
158ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
159ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
160ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call resume is received from the remote user.
161ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
162ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
163ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
164ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
165ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallResumeReceived(ImsCall call) {
166ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallStateChanged(call);
167ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
168ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
169ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
170ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call is in call.
171ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
172ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
173ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
174047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn         * @param swapCalls {@code true} if the foreground and background calls should be swapped
175047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn         *                              now that the merge has completed.
176ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
177047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        public void onCallMerged(ImsCall call, boolean swapCalls) {
17871382693cbc81b1d131085f52d97879976706f55Anthony Lee            onCallStateChanged(call);
179ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
180ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
181ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
182ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call merge is failed.
183ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallError}.
184ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
185ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
186ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the call merge failure
187ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
188ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallMergeFailed(ImsCall call, ImsReasonInfo reasonInfo) {
189ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallError(call, reasonInfo);
190ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
191ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
192ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
193ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call is updated (except for hold/unhold).
194ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
195ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
196ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
197ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
198ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallUpdated(ImsCall call) {
199ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallStateChanged(call);
200ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
201ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
202ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
203ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call update is failed.
204ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallError}.
205ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
206ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
207ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the call update failure
208ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
209ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallUpdateFailed(ImsCall call, ImsReasonInfo reasonInfo) {
210ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallError(call, reasonInfo);
211ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
212ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
213ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
214ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call update is received from the remote user.
215ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
216ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
217ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
218ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallUpdateReceived(ImsCall call) {
219ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
220ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
221ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
222ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
223ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call is extended to the conference call.
224ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
225ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
226ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
227ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param newCall the call object that is extended to the conference from the active call
228ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
229ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallConferenceExtended(ImsCall call, ImsCall newCall) {
23071382693cbc81b1d131085f52d97879976706f55Anthony Lee            onCallStateChanged(call);
231ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
232ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
233ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
234ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the conference extension is failed.
235ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallError}.
236ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
237ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
238ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the conference extension failure
239ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
240ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallConferenceExtendFailed(ImsCall call,
241ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsReasonInfo reasonInfo) {
242ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallError(call, reasonInfo);
243ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
244ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
245ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
246ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the conference extension is received from the remote user.
247ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
248ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
249ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param newCall the call object that is extended to the conference from the active call
250ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
251ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallConferenceExtendReceived(ImsCall call, ImsCall newCall) {
25271382693cbc81b1d131085f52d97879976706f55Anthony Lee            onCallStateChanged(call);
253ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
254ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
255ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
256ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the invitation request of the participants is delivered to
257ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * the conference server.
258ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
259ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
260ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
261ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallInviteParticipantsRequestDelivered(ImsCall call) {
262ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
263ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
264ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
265ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
266ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the invitation request of the participants is failed.
267ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
268ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
269ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the conference invitation failure
270ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
271ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallInviteParticipantsRequestFailed(ImsCall call,
272ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsReasonInfo reasonInfo) {
273ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
274ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
275ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
276ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
277ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the removal request of the participants is delivered to
278ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * the conference server.
279ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
280ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
281ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
282ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallRemoveParticipantsRequestDelivered(ImsCall call) {
283ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
284ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
285ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
286ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
287ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the removal request of the participants is failed.
288ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
289ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
290ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the conference removal failure
291ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
292ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallRemoveParticipantsRequestFailed(ImsCall call,
293ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsReasonInfo reasonInfo) {
294ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
295ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
296ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
297ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
298ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the conference state is updated.
299ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
300ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
301ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param state state of the participant who is participated in the conference call
302ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
303ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallConferenceStateUpdated(ImsCall call, ImsConferenceState state) {
304ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
305ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
306ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
307ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
3081c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn         * Called when the state of IMS conference participant(s) has changed.
3095965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn         *
3105965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn         * @param call the call object that carries out the IMS call.
3111c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn         * @param participants the participant(s) and their new state information.
3125965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn         */
3131c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn        public void onConferenceParticipantsStateChanged(ImsCall call,
3141c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn                List<ConferenceParticipant> participants) {
3155965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn            // no-op
3165965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn        }
3175965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn
3185965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn        /**
319ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the USSD message is received from the network.
320ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
321ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param mode mode of the USSD message (REQUEST / NOTIFY)
322ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param ussdMessage USSD message
323ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
324ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallUssdMessageReceived(ImsCall call,
325ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                int mode, String ussdMessage) {
326ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
327ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
328ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
329ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
330ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when an error occurs. The default implementation is no op.
331ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * overridden. The default implementation is no op. Error events are
332ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * not re-directed to this callback and are handled in {@link #onCallError}.
333ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
334ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
335ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of this error
336ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @see ImsReasonInfo
337ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
338ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallError(ImsCall call, ImsReasonInfo reasonInfo) {
339ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
340ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
341ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
342ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
343ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when an event occurs and the corresponding callback is not
344ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * overridden. The default implementation is no op. Error events are
345ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * not re-directed to this callback and are handled in {@link #onCallError}.
346ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
347ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
348ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
349ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallStateChanged(ImsCall call) {
350ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
351ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
352ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
353ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
354ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call moves the hold state to the conversation state.
355ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * For example, when merging the active & hold call, the state of all the hold call
356ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * will be changed from hold state to conversation state.
357ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * This callback method can be invoked even though the application does not trigger
358ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * any operations.
359ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
360ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
361ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param state the detailed state of call state changes;
362ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *      Refer to CALL_STATE_* in {@link ImsCall}
363ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
364ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallStateChanged(ImsCall call, int state) {
365ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
366ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
367a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak
368a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak        /**
369a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak         * Called when TTY mode of remote party changed
370a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak         *
371a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak         * @param call the call object that carries out the IMS call
372a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak         * @param mode TTY mode of remote party
373a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak         */
374a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak        public void onCallSessionTtyModeReceived(ImsCall call, int mode) {
375a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak            // no-op
376a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak        }
3771463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar
3781463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar        /**
3791463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         * Called when handover occurs from one access technology to another.
3801463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         *
3811463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         * @param session IMS session object
3821463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         * @param srcAccessTech original access technology
3831463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         * @param targetAccessTech new access technology
3841463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         * @param reasonInfo
3851463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         */
3861463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar        public void onCallHandover(ImsCall imsCall, int srcAccessTech, int targetAccessTech,
3871463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            ImsReasonInfo reasonInfo) {
3881463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar        }
3891463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar
3901463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar        /**
3911463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         * Called when handover from one access technology to another fails.
3921463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         *
3931463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         * @param session IMS session object
3941463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         * @param srcAccessTech original access technology
3951463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         * @param targetAccessTech new access technology
3961463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         * @param reasonInfo
3971463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         */
3981463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar        public void onCallHandoverFailed(ImsCall imsCall, int srcAccessTech, int targetAccessTech,
3991463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            ImsReasonInfo reasonInfo) {
4001463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar        }
401ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
402ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
403ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
404ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
405ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // List of update operation for IMS call control
406ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_NONE = 0;
407ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_HOLD = 1;
408ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_HOLD_MERGE = 2;
409ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_RESUME = 3;
410ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_MERGE = 4;
411ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_EXTEND_TO_CONFERENCE = 5;
412ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_UNSPECIFIED = 6;
413ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
414ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // For synchronization of private variables
415ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private Object mLockObj = new Object();
416ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private Context mContext;
417ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
418ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // true if the call is established & in the conversation state
419ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private boolean mInCall = false;
420ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // true if the call is on hold
421ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // If it is triggered by the local, mute the call. Otherwise, play local hold tone
422ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // or network generated media.
423ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private boolean mHold = false;
424ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // true if the call is on mute
425ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private boolean mMute = false;
426ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // It contains the exclusive call update request. Refer to UPDATE_*.
427ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private int mUpdateRequest = UPDATE_NONE;
428ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
429ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsCall.Listener mListener = null;
4309bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
4319bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    // When merging two calls together, the "peer" call that will merge into this call.
4329bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    private ImsCall mMergePeer = null;
4339bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    // When merging two calls together, the "host" call we are merging into.
4349bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    private ImsCall mMergeHost = null;
435ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
436ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // Wrapper call session to interworking the IMS service (server).
437ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsCallSession mSession = null;
438ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // Call profile of the current session.
439ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // It can be changed at anytime when the call is updated.
440ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsCallProfile mCallProfile = null;
441ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // Call profile to be updated after the application's action (accept/reject)
442ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // to the call update. After the application's action (accept/reject) is done,
443ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // it will be set to null.
444ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsCallProfile mProposedCallProfile = null;
445ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsReasonInfo mLastReasonInfo = null;
446ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
447ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // Media session to control media (audio/video) operations for an IMS call
448ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsStreamMediaSession mMediaSession = null;
449ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
450b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // The temporary ImsCallSession that could represent the merged call once
451b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // we receive notification that the merge was successful.
45271382693cbc81b1d131085f52d97879976706f55Anthony Lee    private ImsCallSession mTransientConferenceSession = null;
453b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // While a merge is progressing, we bury any session termination requests
454b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // made on the original ImsCallSession until we have closure on the merge request
455b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // If the request ultimately fails, we need to act on the termination request
456b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // that we buried temporarily. We do this because we feel that timing issues could
457b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // cause the termination request to occur just because the merge is succeeding.
458b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    private boolean mSessionEndDuringMerge = false;
459b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // Just like mSessionEndDuringMerge, we need to keep track of the reason why the
460b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // termination request was made on the original session in case we need to act
461b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // on it in the case of a merge failure.
462b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    private ImsReasonInfo mSessionEndDuringMergeReasonInfo = null;
463c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    // This flag is used to indicate if this ImsCall was merged into a conference
464c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    // or not.  It is used primarily to determine if a disconnect sound should
465c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    // be heard when the call is terminated.
4668ae59492156d9cef275f559c5ee09a44315989beAndrew Lee    private boolean mIsMerged = false;
467c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    // If true, this flag means that this ImsCall is in the process of merging
468c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    // into a conference but it does not yet have closure on if it was
469c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    // actually added to the conference or not. false implies that it either
470c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    // is not part of a merging conference or already knows if it was
471c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    // successfully added.
472047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    private boolean mCallSessionMergePending = false;
473047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
474ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
475ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Create an IMS call object.
476ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
477ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param context the context for accessing system services
478ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param profile the call profile to make/take a call
479ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
480ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsCall(Context context, ImsCallProfile profile) {
481ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mContext = context;
482ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mCallProfile = profile;
483ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
484ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
485ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
486ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Closes this object. This object is not usable after being closed.
487ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
488ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    @Override
489ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void close() {
490ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
491ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession != null) {
492ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mSession.close();
493ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mSession = null;
494ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
495ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
496ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mCallProfile = null;
497ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mProposedCallProfile = null;
498ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mLastReasonInfo = null;
499ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mMediaSession = null;
500ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
501ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
502ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
503ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
504ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Checks if the call has a same remote user identity or not.
505ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
506ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param userId the remote user identity
507ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return true if the remote user identity is equal; otherwise, false
508ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
509ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    @Override
510ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public boolean checkIfRemoteUserIsSame(String userId) {
511ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (userId == null) {
512ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return false;
513ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
514ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
515ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        return userId.equals(mCallProfile.getCallExtra(ImsCallProfile.EXTRA_REMOTE_URI, ""));
516ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
517ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
518ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
519ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Checks if the call is equal or not.
520ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
521ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param call the call to be compared
522ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return true if the call is equal; otherwise, false
523ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
524ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    @Override
525ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public boolean equalsTo(ICall call) {
526ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (call == null) {
527ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return false;
528ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
529ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
530ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (call instanceof ImsCall) {
53116b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen            return this.equals(call);
532ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
533ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
534ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        return false;
535ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
536ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
537c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    public static boolean isSessionAlive(ImsCallSession session) {
538c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        return session != null && session.isAlive();
539c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    }
540c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
541ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
542ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the negotiated (local & remote) call profile.
543ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
544ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return a {@link ImsCallProfile} object that has the negotiated call profile
545ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
546ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsCallProfile getCallProfile() {
547ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
548ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mCallProfile;
549ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
550ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
551ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
552ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
553ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the local call profile (local capabilities).
554ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
555ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return a {@link ImsCallProfile} object that has the local call profile
556ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
557ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsCallProfile getLocalCallProfile() throws ImsException {
558ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
559ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
560ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
561ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
562ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
563ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
564ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            try {
565ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return mSession.getLocalCallProfile();
566ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } catch (Throwable t) {
567ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("getLocalCallProfile :: ", t);
568ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("getLocalCallProfile()", t, 0);
569ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
570ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
571ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
572ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
573ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
574e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh     * Gets the remote call profile (remote capabilities).
575e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh     *
576e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh     * @return a {@link ImsCallProfile} object that has the remote call profile
577e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh     */
578e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh    public ImsCallProfile getRemoteCallProfile() throws ImsException {
579e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh        synchronized(mLockObj) {
580e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh            if (mSession == null) {
581e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh                throw new ImsException("No call session",
582e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
583e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh            }
584e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh
585e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh            try {
586e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh                return mSession.getRemoteCallProfile();
587e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh            } catch (Throwable t) {
588e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh                loge("getRemoteCallProfile :: ", t);
589e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh                throw new ImsException("getRemoteCallProfile()", t, 0);
590e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh            }
591e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh        }
592e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh    }
593e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh
594e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh    /**
595ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the call profile proposed by the local/remote user.
596ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
597ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return a {@link ImsCallProfile} object that has the proposed call profile
598ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
599ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsCallProfile getProposedCallProfile() {
600ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
601ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (!isInCall()) {
602ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return null;
603ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
604ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
605ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mProposedCallProfile;
606ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
607ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
608ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
609ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
610ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the state of the {@link ImsCallSession} that carries this call.
611ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * The value returned must be one of the states in {@link ImsCallSession#State}.
612ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
613ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return the session state
614ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
615ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public int getState() {
616ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
617ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
618ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return ImsCallSession.State.IDLE;
619ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
620ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
621ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mSession.getState();
622ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
623ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
624ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
625ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
626ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the {@link ImsCallSession} that carries this call.
627ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
628ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return the session object that carries this call
629ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @hide
630ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
631ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsCallSession getCallSession() {
632ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
633ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mSession;
634ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
635ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
636ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
637ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
638ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the {@link ImsStreamMediaSession} that handles the media operation of this call.
639ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Almost interface APIs are for the VT (Video Telephony).
640ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
641ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return the media session object that handles the media operation of this call
642ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @hide
643ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
644ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsStreamMediaSession getMediaSession() {
645ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
646ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mMediaSession;
647ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
648ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
649ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
650ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
651ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the specified property of this call.
652ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
653ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param name key to get the extra call information defined in {@link ImsCallProfile}
654ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return the extra call information as string
655ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
656ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public String getCallExtra(String name) throws ImsException {
657ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        // Lookup the cache
658ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
659ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
660ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // If not found, try to get the property from the remote
661ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
662ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
663ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
664ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
665ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
666ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            try {
667ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return mSession.getProperty(name);
668ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } catch (Throwable t) {
669ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("getCallExtra :: ", t);
670ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("getCallExtra()", t, 0);
671ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
672ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
673ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
674ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
675ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
676ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the last reason information when the call is not established, cancelled or terminated.
677ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
678ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return the last reason information
679ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
680ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsReasonInfo getLastReasonInfo() {
681ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
682ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mLastReasonInfo;
683ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
684ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
685ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
686ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
687ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Checks if the call has a pending update operation.
688ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
689ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return true if the call has a pending update operation
690ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
691ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public boolean hasPendingUpdate() {
692ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
693ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return (mUpdateRequest != UPDATE_NONE);
694ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
695ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
696ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
697ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
698ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Checks if the call is established.
699ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
700ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return true if the call is established
701ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
702ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public boolean isInCall() {
703ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
704ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mInCall;
705ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
706ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
707ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
708ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
709ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Checks if the call is muted.
710ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
711ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return true if the call is muted
712ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
713ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public boolean isMuted() {
714ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
715ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mMute;
716ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
717ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
718ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
719ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
720ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Checks if the call is on hold.
721ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
722ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return true if the call is on hold
723ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
724ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public boolean isOnHold() {
725ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
726ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mHold;
727ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
728ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
729ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
730ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
731725ad373383798c1516348475b1f6304484e031eTyler Gunn     * Determines if the call is a multiparty call.
732725ad373383798c1516348475b1f6304484e031eTyler Gunn     *
733725ad373383798c1516348475b1f6304484e031eTyler Gunn     * @return {@code True} if the call is a multiparty call.
734725ad373383798c1516348475b1f6304484e031eTyler Gunn     */
735725ad373383798c1516348475b1f6304484e031eTyler Gunn    public boolean isMultiparty() {
73616b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen        synchronized(mLockObj) {
73716b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen            if (mSession == null) {
73816b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen                return false;
73916b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen            }
74016b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen
74171382693cbc81b1d131085f52d97879976706f55Anthony Lee            return mSession.isMultiparty();
74216b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen        }
743725ad373383798c1516348475b1f6304484e031eTyler Gunn    }
744725ad373383798c1516348475b1f6304484e031eTyler Gunn
745725ad373383798c1516348475b1f6304484e031eTyler Gunn    /**
7469bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * Marks whether an IMS call is merged. This should be set {@code true} when the call merges
7479bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * into a conference.
7488ae59492156d9cef275f559c5ee09a44315989beAndrew Lee     *
7498ae59492156d9cef275f559c5ee09a44315989beAndrew Lee     * @param isMerged Whether the call is merged.
7508ae59492156d9cef275f559c5ee09a44315989beAndrew Lee     */
7518ae59492156d9cef275f559c5ee09a44315989beAndrew Lee    public void setIsMerged(boolean isMerged) {
7528ae59492156d9cef275f559c5ee09a44315989beAndrew Lee        mIsMerged = isMerged;
7538ae59492156d9cef275f559c5ee09a44315989beAndrew Lee    }
7548ae59492156d9cef275f559c5ee09a44315989beAndrew Lee
7558ae59492156d9cef275f559c5ee09a44315989beAndrew Lee    /**
7569bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * @return {@code true} if the call recently merged into a conference call.
7578ae59492156d9cef275f559c5ee09a44315989beAndrew Lee     */
7588ae59492156d9cef275f559c5ee09a44315989beAndrew Lee    public boolean isMerged() {
7598ae59492156d9cef275f559c5ee09a44315989beAndrew Lee        return mIsMerged;
7608ae59492156d9cef275f559c5ee09a44315989beAndrew Lee    }
7618ae59492156d9cef275f559c5ee09a44315989beAndrew Lee
7628ae59492156d9cef275f559c5ee09a44315989beAndrew Lee    /**
763ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Sets the listener to listen to the IMS call events.
764ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * The method calls {@link #setListener setListener(listener, false)}.
765ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
766ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param listener to listen to the IMS call events of this object; null to remove listener
767ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see #setListener(Listener, boolean)
768ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
769ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void setListener(ImsCall.Listener listener) {
770ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        setListener(listener, false);
771ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
772ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
773ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
774ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Sets the listener to listen to the IMS call events.
775ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * A {@link ImsCall} can only hold one listener at a time. Subsequent calls
776ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * to this method override the previous listener.
777ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
778ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param listener to listen to the IMS call events of this object; null to remove listener
779ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param callbackImmediately set to true if the caller wants to be called
780ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *        back immediately on the current state
781ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
782ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void setListener(ImsCall.Listener listener, boolean callbackImmediately) {
783ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        boolean inCall;
784ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        boolean onHold;
785ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        int state;
786ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        ImsReasonInfo lastReasonInfo;
787ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
788ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
789ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mListener = listener;
790ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
791ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if ((listener == null) || !callbackImmediately) {
792ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return;
793ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
794ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
795ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            inCall = mInCall;
796ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onHold = mHold;
797ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            state = getState();
798ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            lastReasonInfo = mLastReasonInfo;
799ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
800ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
801ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        try {
802ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (lastReasonInfo != null) {
803ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener.onCallError(this, lastReasonInfo);
804ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } else if (inCall) {
805ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (onHold) {
806ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallHeld(this);
807ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } else {
808ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallStarted(this);
809ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
810ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } else {
811ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                switch (state) {
812ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    case ImsCallSession.State.ESTABLISHING:
813ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        listener.onCallProgressing(this);
814ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        break;
815ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    case ImsCallSession.State.TERMINATED:
816ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        listener.onCallTerminated(this, lastReasonInfo);
817ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        break;
818ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    default:
819ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        // Ignore it. There is no action in the other state.
820ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        break;
821ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
822ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
823ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        } catch (Throwable t) {
824ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            loge("setListener()", t);
825ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
826ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
827ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
828ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
829ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Mutes or unmutes the mic for the active call.
830ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
831ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param muted true if the call is muted, false otherwise
832ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
833ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void setMute(boolean muted) throws ImsException {
834ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
835ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mMute != muted) {
836ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mMute = muted;
837ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
838ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
839ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    mSession.setMute(muted);
840ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
841ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("setMute :: ", t);
842ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    throwImsException(t, 0);
843ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
844ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
845ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
846ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
847ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
848ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     /**
849ef36ef67e009449300b0150c60c9f637e205d79eWink Saville      * Attaches an incoming call to this call object.
850ef36ef67e009449300b0150c60c9f637e205d79eWink Saville      *
851ef36ef67e009449300b0150c60c9f637e205d79eWink Saville      * @param session the session that receives the incoming call
852ef36ef67e009449300b0150c60c9f637e205d79eWink Saville      * @throws ImsException if the IMS service fails to attach this object to the session
853ef36ef67e009449300b0150c60c9f637e205d79eWink Saville      */
854ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     public void attachSession(ImsCallSession session) throws ImsException {
855ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         if (DBG) {
856ef36ef67e009449300b0150c60c9f637e205d79eWink Saville             log("attachSession :: session=" + session);
857ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         }
858ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
859ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         synchronized(mLockObj) {
860ef36ef67e009449300b0150c60c9f637e205d79eWink Saville             mSession = session;
861ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
862ef36ef67e009449300b0150c60c9f637e205d79eWink Saville             try {
863ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                 mSession.setListener(createCallSessionListener());
864ef36ef67e009449300b0150c60c9f637e205d79eWink Saville             } catch (Throwable t) {
865ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                 loge("attachSession :: ", t);
866ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                 throwImsException(t, 0);
867ef36ef67e009449300b0150c60c9f637e205d79eWink Saville             }
868ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         }
869ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     }
870ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
871ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
872ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Initiates an IMS call with the call profile which is provided
873ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * when creating a {@link ImsCall}.
874ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
875ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param session the {@link ImsCallSession} for carrying out the call
876ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param callee callee information to initiate an IMS call
877ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to initiate the call
878ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
879ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void start(ImsCallSession session, String callee)
880ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            throws ImsException {
881ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (DBG) {
882ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            log("start(1) :: session=" + session + ", callee=" + callee);
883ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
884ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
885ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
886ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession = session;
887ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
888ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            try {
889ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                session.setListener(createCallSessionListener());
890ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                session.start(callee, mCallProfile);
891ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } catch (Throwable t) {
892ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("start(1) :: ", t);
893ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("start(1)", t, 0);
894ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
895ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
896ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
897ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
898ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
899ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Initiates an IMS conferenca call with the call profile which is provided
900ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * when creating a {@link ImsCall}.
901ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
902ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param session the {@link ImsCallSession} for carrying out the call
903ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param participants participant list to initiate an IMS conference call
904ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to initiate the call
905ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
906ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void start(ImsCallSession session, String[] participants)
907ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            throws ImsException {
908ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (DBG) {
909ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            log("start(n) :: session=" + session + ", callee=" + participants);
910ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
911ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
912ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
913ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession = session;
914ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
915ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            try {
916ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                session.setListener(createCallSessionListener());
917ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                session.start(participants, mCallProfile);
918ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } catch (Throwable t) {
919ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("start(n) :: ", t);
920ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("start(n)", t, 0);
921ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
922ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
923ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
924ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
925ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
926ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Accepts a call.
927ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
928ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallStarted
929d1edfd8cf9ffeb191a84e08522bb570cd8cd4381Tyler Gunn     *
930d1edfd8cf9ffeb191a84e08522bb570cd8cd4381Tyler Gunn     * @param callType The call type the user agreed to for accepting the call.
931ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to accept the call
932ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
933d1edfd8cf9ffeb191a84e08522bb570cd8cd4381Tyler Gunn    public void accept(int callType) throws ImsException {
9349bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (VDBG) {
935c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            log("accept ::");
936ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
937ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
938d1edfd8cf9ffeb191a84e08522bb570cd8cd4381Tyler Gunn        accept(callType, new ImsStreamMediaProfile());
939ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
940ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
941ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
942ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Accepts a call.
943ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
944ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param callType call type to be answered in {@link ImsCallProfile}
945ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param profile a media profile to be answered (audio/audio & video, direction, ...)
946ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallStarted
947ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to accept the call
948ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
949ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void accept(int callType, ImsStreamMediaProfile profile) throws ImsException {
9509bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (VDBG) {
951c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            log("accept :: callType=" + callType + ", profile=" + profile);
952ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
953ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
954ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
955ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
956ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call to answer",
957ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
958ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
959ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
960ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            try {
961ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mSession.accept(callType, profile);
962ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } catch (Throwable t) {
963ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("accept :: ", t);
964ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("accept()", t, 0);
965ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
966ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
967ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mInCall && (mProposedCallProfile != null)) {
968ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (DBG) {
969ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    log("accept :: call profile will be updated");
970ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
971ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
972ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallProfile = mProposedCallProfile;
973ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mProposedCallProfile = null;
974ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
975ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
976ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // Other call update received
977ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mInCall && (mUpdateRequest == UPDATE_UNSPECIFIED)) {
978ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
979ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
980ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
981ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
982ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
983ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
984ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Rejects a call.
985ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
986ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param reason reason code to reject an incoming call
987ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallStartFailed
988ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to accept the call
989ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
990ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void reject(int reason) throws ImsException {
9919bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (VDBG) {
992c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            log("reject :: reason=" + reason);
993ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
994ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
995ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
996ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession != null) {
997ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mSession.reject(reason);
998ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
999ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1000ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mInCall && (mProposedCallProfile != null)) {
1001ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (DBG) {
1002ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    log("reject :: call profile is not updated; destroy it...");
1003ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1004ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1005ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mProposedCallProfile = null;
1006ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1007ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1008ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // Other call update received
1009ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mInCall && (mUpdateRequest == UPDATE_UNSPECIFIED)) {
1010ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
1011ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1012ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1013ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1014ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1015ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1016ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Terminates an IMS call.
1017ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1018ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param reason reason code to terminate a call
1019ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to terminate the call
1020ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1021ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void terminate(int reason) throws ImsException {
10229bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (VDBG) {
1023c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            log("terminate :: ImsCall=" + this +" reason=" + reason);
1024ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1025ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1026ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1027ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mHold = false;
1028ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mInCall = false;
1029ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1030ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession != null) {
1031c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // TODO: Fix the fact that user invoked call terminations during
1032c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // the process of establishing a conference call needs to be handled
1033c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // as a special case.
1034c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // Currently, any terminations (both invoked by the user or
1035c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // by the network results in a callSessionTerminated() callback
1036c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // from the network.  When establishing a conference call we bury
1037c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // these callbacks until we get closure on all participants of the
1038c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // conference. In some situations, we will throw away the callback
1039c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // (when the underlying session of the host of the new conference
1040c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // is terminated) or will will unbury it when the conference has been
1041c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // established, like when the peer of the new conference goes away
1042c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // after the conference has been created.  The UI relies on the callback
1043c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // to reflect the fact that the call is gone.
1044c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // So if a user decides to terminated a call while it is merging, it
1045c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // could take a long time to reflect in the UI due to the conference
1046c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // processing but we should probably cancel that and just terminate
1047c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // the call immediately and clean up.  This is not a huge issue right
1048c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // now because we have not seen instances where establishing a
1049c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // conference takes a long time (more than a second or two).
1050ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mSession.terminate(reason);
1051ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1052ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1053ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1054ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1055d43b5302d8edf4df90a28055f043786f542df219Uma Maheswari Ramalingam
1056ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1057ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Puts a call on hold. When succeeds, {@link Listener#onCallHeld} is called.
1058ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1059ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallHeld, Listener#onCallHoldFailed
1060ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to hold the call
1061ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1062ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void hold() throws ImsException {
10639bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (VDBG) {
1064c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            log("hold :: ImsCall=" + this);
1065111eecc9845826e985c48133b754e453fb3aca84Etan Cohen        }
1066111eecc9845826e985c48133b754e453fb3aca84Etan Cohen
1067ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (isOnHold()) {
1068ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
1069ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("hold :: call is already on hold");
1070ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1071ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return;
1072ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1073ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1074ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1075ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mUpdateRequest != UPDATE_NONE) {
10769bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                loge("hold :: update is in progress; request=" +
10779bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                        updateRequestToString(mUpdateRequest));
1078ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("Call update is in progress",
1079ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
1080ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1081ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1082ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1083ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("hold :: ");
1084ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1085ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1086ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1087ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1088ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession.hold(createHoldMediaProfile());
1089ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // FIXME: update the state on the callback?
1090ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mHold = true;
1091ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mUpdateRequest = UPDATE_HOLD;
1092ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1093ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1094ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1095ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1096ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Continues a call that's on hold. When succeeds, {@link Listener#onCallResumed} is called.
1097ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1098ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallResumed, Listener#onCallResumeFailed
1099ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to resume the call
1100ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1101ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void resume() throws ImsException {
11029bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (VDBG) {
1103c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            log("resume :: ImsCall=" + this);
1104111eecc9845826e985c48133b754e453fb3aca84Etan Cohen        }
1105111eecc9845826e985c48133b754e453fb3aca84Etan Cohen
1106ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (!isOnHold()) {
1107ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
1108ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("resume :: call is in conversation");
1109ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1110ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return;
1111ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1112ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1113ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1114ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mUpdateRequest != UPDATE_NONE) {
11159bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                loge("resume :: update is in progress; request=" +
11169bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                        updateRequestToString(mUpdateRequest));
1117ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("Call update is in progress",
1118ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
1119ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1120ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1121ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1122ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("resume :: ");
1123ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1124ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1125ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1126ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1127c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // mHold is set to false in confirmation callback that the
1128c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // ImsCall was resumed.
1129ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mUpdateRequest = UPDATE_RESUME;
1130c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            mSession.resume(createResumeMediaProfile());
1131ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1132ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1133ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1134ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1135ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Merges the active & hold call.
1136ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1137ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallMerged, Listener#onCallMergeFailed
1138ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to merge the call
1139ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1140047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    private void merge() throws ImsException {
11419bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (VDBG) {
1142c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            log("merge :: ImsCall=" + this);
1143ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1144ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1145ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1146ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mUpdateRequest != UPDATE_NONE) {
11479bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                loge("merge :: update is in progress; request=" +
11489bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                        updateRequestToString(mUpdateRequest));
1149ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("Call update is in progress",
1150ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
1151ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1152ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1153ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1154c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                loge("merge :: no call session");
1155ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1156ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1157ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1158ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1159ca45f58a57eb782153c034ae067f59c0018799caUma Maheswari Ramalingam            // if skipHoldBeforeMerge = true, IMS service implementation will
1160ca45f58a57eb782153c034ae067f59c0018799caUma Maheswari Ramalingam            // merge without explicitly holding the call.
1161ca45f58a57eb782153c034ae067f59c0018799caUma Maheswari Ramalingam            if (mHold || (mContext.getResources().getBoolean(
1162ca45f58a57eb782153c034ae067f59c0018799caUma Maheswari Ramalingam                    com.android.internal.R.bool.skipHoldBeforeMerge))) {
1163b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee
11649bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                if (mMergePeer != null && !mMergePeer.isMultiparty() && !isMultiparty()) {
11659bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                    // We only set UPDATE_MERGE when we are adding the first
11669bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                    // calls to the Conference.  If there is already a conference
1167047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                    // no special handling is needed. The existing conference
11689bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                    // session will just go active and any other sessions will be terminated
11699bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                    // if needed.  There will be no merge failed callback.
1170047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                    // Mark both the host and peer UPDATE_MERGE to ensure both are aware that a
1171047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                    // merge is pending.
11729bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                    mUpdateRequest = UPDATE_MERGE;
1173047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                    mMergePeer.mUpdateRequest = UPDATE_MERGE;
1174b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                }
11759bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
11769bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                mSession.merge();
1177ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } else {
117871382693cbc81b1d131085f52d97879976706f55Anthony Lee                // This code basically says, we need to explicitly hold before requesting a merge
117971382693cbc81b1d131085f52d97879976706f55Anthony Lee                // when we get the callback that the hold was successful (or failed), we should
118071382693cbc81b1d131085f52d97879976706f55Anthony Lee                // automatically request a merge.
1181ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mSession.hold(createHoldMediaProfile());
1182ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mHold = true;
1183ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_HOLD_MERGE;
1184ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1185ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1186ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1187ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1188ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1189ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Merges the active & hold call.
1190ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1191ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param bgCall the background (holding) call
1192ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallMerged, Listener#onCallMergeFailed
1193ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to merge the call
1194ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1195ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void merge(ImsCall bgCall) throws ImsException {
11969bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (VDBG) {
1197c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            log("merge(1) :: bgImsCall=" + bgCall);
1198ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1199ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1200ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (bgCall == null) {
1201ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            throw new ImsException("No background call",
1202ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
1203ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1204ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1205ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1206047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            // Mark both sessions as pending merge.
1207047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            this.setCallSessionMergePending(true);
1208047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            bgCall.setCallSessionMergePending(true);
1209047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
121087466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn            if ((!isMultiparty() && !bgCall.isMultiparty()) || isMultiparty()) {
121187466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                // If neither call is multiparty, the current call is the merge host and the bg call
121287466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                // is the merge peer (ie we're starting a new conference).
121387466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                // OR
121487466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                // If this call is multiparty, it is the merge host and the other call is the merge
121587466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                // peer.
121687466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                setMergePeer(bgCall);
121787466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn            } else {
121887466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                // If the bg call is multiparty, it is the merge host.
121987466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                setMergeHost(bgCall);
122087466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn            }
1221ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1222ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        merge();
1223ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1224ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1225ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1226ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Updates the current call's properties (ex. call mode change: video upgrade / downgrade).
1227ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1228ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void update(int callType, ImsStreamMediaProfile mediaProfile) throws ImsException {
12299bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (VDBG) {
1230c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            log("update ::");
1231ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1232ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1233ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (isOnHold()) {
1234ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
1235ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("update :: call is on hold");
1236ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1237ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            throw new ImsException("Not in a call to update call",
1238ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
1239ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1240ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1241ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1242ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mUpdateRequest != UPDATE_NONE) {
1243ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (DBG) {
12449bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                    log("update :: update is in progress; request=" +
12459bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                            updateRequestToString(mUpdateRequest));
1246ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1247ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("Call update is in progress",
1248ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
1249ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1250ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1251ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1252ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("update :: ");
1253ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1254ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1255ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1256ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1257ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession.update(callType, mediaProfile);
1258ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mUpdateRequest = UPDATE_UNSPECIFIED;
1259ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1260ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1261ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1262ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1263ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Extends this call (1-to-1 call) to the conference call
1264ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * inviting the specified participants to.
1265ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1266ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1267ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void extendToConference(String[] participants) throws ImsException {
12689bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (VDBG) {
1269c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            log("extendToConference ::");
1270ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1271ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1272ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (isOnHold()) {
1273ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
1274ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("extendToConference :: call is on hold");
1275ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1276ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            throw new ImsException("Not in a call to extend a call to conference",
1277ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
1278ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1279ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1280ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1281ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mUpdateRequest != UPDATE_NONE) {
1282ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (DBG) {
12839bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                    log("extendToConference :: update is in progress; request=" +
12849bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                            updateRequestToString(mUpdateRequest));
1285ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1286ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("Call update is in progress",
1287ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
1288ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1289ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1290ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1291ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("extendToConference :: ");
1292ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1293ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1294ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1295ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1296ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession.extendToConference(participants);
1297ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mUpdateRequest = UPDATE_EXTEND_TO_CONFERENCE;
1298ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1299ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1300ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1301ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1302ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Requests the conference server to invite an additional participants to the conference.
1303ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1304ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1305ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void inviteParticipants(String[] participants) throws ImsException {
13069bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (VDBG) {
1307c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            log("inviteParticipants ::");
1308ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1309ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1310ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1311ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1312ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("inviteParticipants :: ");
1313ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1314ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1315ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1316ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1317ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession.inviteParticipants(participants);
1318ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1319ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1320ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1321ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1322ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Requests the conference server to remove the specified participants from the conference.
1323ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1324ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1325ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void removeParticipants(String[] participants) throws ImsException {
1326ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (DBG) {
13279bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            log("removeParticipants ::");
1328ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1329ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1330ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1331ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1332ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("removeParticipants :: ");
1333ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1334ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1335ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1336ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1337ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession.removeParticipants(participants);
1338ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1339ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1340ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1341ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1342ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Sends a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2833</a>,
1343ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * event 0 ~ 9 maps to decimal value 0 ~ 9, '*' to 10, '#' to 11, event 'A' ~ 'D' to 12 ~ 15,
1344ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * and event flash to 16. Currently, event flash is not supported.
1345ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
13462f92daf76a66d7d2fe6fb7b1a28fc1b5888a7b7cLibin.Tang@motorola.com     * @param c that represents the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs.
13472f92daf76a66d7d2fe6fb7b1a28fc1b5888a7b7cLibin.Tang@motorola.com     * @param result the result message to send when done.
1348ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
13492f92daf76a66d7d2fe6fb7b1a28fc1b5888a7b7cLibin.Tang@motorola.com    public void sendDtmf(char c, Message result) {
13509bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (VDBG) {
1351c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            log("sendDtmf :: code=" + c);
1352ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1353ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1354ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1355ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession != null) {
1356a4710d5d926d8112179acece620f49cb79257e98Andrew Lee                mSession.sendDtmf(c, result);
1357ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1358ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1359ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1360ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1361ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1362a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam     * Start a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2833</a>,
1363a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam     * event 0 ~ 9 maps to decimal value 0 ~ 9, '*' to 10, '#' to 11, event 'A' ~ 'D' to 12 ~ 15,
1364a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam     * and event flash to 16. Currently, event flash is not supported.
1365a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam     *
1366a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam     * @param c that represents the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs.
1367a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam     */
1368a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam    public void startDtmf(char c) {
1369a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam        if (DBG) {
1370a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam            log("startDtmf :: session=" + mSession + ", code=" + c);
1371a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam        }
1372a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam
1373a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam        synchronized(mLockObj) {
1374a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam            if (mSession != null) {
1375a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam                mSession.startDtmf(c);
1376a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam            }
1377a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam        }
1378a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam    }
1379a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam
1380a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam    /**
1381a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam     * Stop a DTMF code.
1382a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam     */
1383a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam    public void stopDtmf() {
1384a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam        if (DBG) {
1385a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam            log("stopDtmf :: session=" + mSession);
1386a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam        }
1387a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam
1388a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam        synchronized(mLockObj) {
1389a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam            if (mSession != null) {
1390a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam                mSession.stopDtmf();
1391a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam            }
1392a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam        }
1393a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam    }
1394a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam
1395a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam    /**
1396ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Sends an USSD message.
1397ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1398ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param ussdMessage USSD message to send
1399ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1400ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void sendUssd(String ussdMessage) throws ImsException {
14019bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (VDBG) {
1402c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            log("sendUssd :: ussdMessage=" + ussdMessage);
1403ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1404ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1405ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1406ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1407ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("sendUssd :: ");
1408ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1409ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1410ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1411ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1412ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession.sendUssd(ussdMessage);
1413ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1414ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1415ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1416ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void clear(ImsReasonInfo lastReasonInfo) {
1417ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mInCall = false;
1418ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mHold = false;
1419ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mUpdateRequest = UPDATE_NONE;
1420ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mLastReasonInfo = lastReasonInfo;
1421ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1422ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1423ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1424ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Creates an IMS call session listener.
1425ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1426ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsCallSession.Listener createCallSessionListener() {
1427ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        return new ImsCallSessionListenerProxy();
1428ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1429ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1430ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsCall createNewCall(ImsCallSession session, ImsCallProfile profile) {
1431ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        ImsCall call = new ImsCall(mContext, profile);
1432ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1433ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        try {
1434ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            call.attachSession(session);
1435ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        } catch (ImsException e) {
1436ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (call != null) {
1437ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                call.close();
1438ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                call = null;
1439ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1440ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1441ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1442ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        // Do additional operations...
1443ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1444ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        return call;
1445ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1446ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1447ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsStreamMediaProfile createHoldMediaProfile() {
1448ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        ImsStreamMediaProfile mediaProfile = new ImsStreamMediaProfile();
1449ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1450ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (mCallProfile == null) {
1451ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mediaProfile;
1452ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1453ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1454ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mediaProfile.mAudioQuality = mCallProfile.mMediaProfile.mAudioQuality;
1455ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mediaProfile.mVideoQuality = mCallProfile.mMediaProfile.mVideoQuality;
1456ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mediaProfile.mAudioDirection = ImsStreamMediaProfile.DIRECTION_SEND;
1457ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1458ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (mediaProfile.mVideoQuality != ImsStreamMediaProfile.VIDEO_QUALITY_NONE) {
1459ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mediaProfile.mVideoDirection = ImsStreamMediaProfile.DIRECTION_SEND;
1460ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1461ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1462ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        return mediaProfile;
1463ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1464ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1465ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsStreamMediaProfile createResumeMediaProfile() {
1466ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        ImsStreamMediaProfile mediaProfile = new ImsStreamMediaProfile();
1467ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1468ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (mCallProfile == null) {
1469ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mediaProfile;
1470ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1471ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1472ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mediaProfile.mAudioQuality = mCallProfile.mMediaProfile.mAudioQuality;
1473ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mediaProfile.mVideoQuality = mCallProfile.mMediaProfile.mVideoQuality;
1474ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mediaProfile.mAudioDirection = ImsStreamMediaProfile.DIRECTION_SEND_RECEIVE;
1475ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1476ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (mediaProfile.mVideoQuality != ImsStreamMediaProfile.VIDEO_QUALITY_NONE) {
1477ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mediaProfile.mVideoDirection = ImsStreamMediaProfile.DIRECTION_SEND_RECEIVE;
1478ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1479ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1480ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        return mediaProfile;
1481ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1482ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1483ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void enforceConversationMode() {
1484ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (mInCall) {
1485ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mHold = false;
1486ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mUpdateRequest = UPDATE_NONE;
1487ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1488ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1489ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1490ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void mergeInternal() {
14919bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (VDBG) {
1492c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            log("mergeInternal :: ImsCall=" + this);
1493ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1494ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1495ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mSession.merge();
1496ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mUpdateRequest = UPDATE_MERGE;
1497ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1498ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1499ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void notifyConferenceSessionTerminated(ImsReasonInfo reasonInfo) {
15009bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        ImsCall.Listener listener = mListener;
1501ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        clear(reasonInfo);
1502ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1503ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (listener != null) {
1504ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            try {
1505ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener.onCallTerminated(this, reasonInfo);
1506ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } catch (Throwable t) {
1507ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("notifyConferenceSessionTerminated :: ", t);
1508ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1509ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1510ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1511ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1512ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void notifyConferenceStateUpdated(ImsConferenceState state) {
15131c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn        Set<Entry<String, Bundle>> participants = state.mParticipants.entrySet();
1514ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
15151c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn        if (participants == null) {
1516ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return;
1517ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1518ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
15191c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn        Iterator<Entry<String, Bundle>> iterator = participants.iterator();
15201c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn        List<ConferenceParticipant> conferenceParticipants = new ArrayList<>(participants.size());
1521ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        while (iterator.hasNext()) {
1522ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            Entry<String, Bundle> entry = iterator.next();
1523ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1524ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            String key = entry.getKey();
1525ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            Bundle confInfo = entry.getValue();
1526ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            String status = confInfo.getString(ImsConferenceState.STATUS);
1527ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            String user = confInfo.getString(ImsConferenceState.USER);
15285965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn            String displayName = confInfo.getString(ImsConferenceState.DISPLAY_TEXT);
1529ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            String endpoint = confInfo.getString(ImsConferenceState.ENDPOINT);
1530ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1531ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
1532ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("notifyConferenceStateUpdated :: key=" + key +
1533ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ", status=" + status +
1534ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ", user=" + user +
15355965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn                        ", displayName= " + displayName +
1536ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ", endpoint=" + endpoint);
1537ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1538ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
15399bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            Uri handle = Uri.parse(user);
15409bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            Uri endpointUri = Uri.parse(endpoint);
15419bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            int connectionState = ImsConferenceState.getConnectionStateForStatus(status);
1542ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
15439bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            ConferenceParticipant conferenceParticipant = new ConferenceParticipant(handle,
15449bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                    displayName, endpointUri, connectionState);
15459bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            conferenceParticipants.add(conferenceParticipant);
1546ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
15471c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn
15481c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn        if (!conferenceParticipants.isEmpty() && mListener != null) {
15491c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn            try {
15501c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn                mListener.onConferenceParticipantsStateChanged(this, conferenceParticipants);
15511c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn            } catch (Throwable t) {
15521c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn                loge("notifyConferenceStateUpdated :: ", t);
15531c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn            }
15541c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn        }
1555ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1556ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1557b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    /**
1558b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee     * Perform all cleanup and notification around the termination of a session.
1559b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee     * Note that there are 2 distinct modes of operation.  The first is when
1560b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee     * we receive a session termination on the primary session when we are
1561b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee     * in the processing of merging.  The second is when we are not merging anything
1562b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee     * and the call is terminated.
1563b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee     *
1564b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee     * @param reasonInfo The reason for the session termination
1565b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee     */
1566b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    private void processCallTerminated(ImsReasonInfo reasonInfo) {
15679bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (VDBG) {
1568b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee            String reasonString = reasonInfo != null ? reasonInfo.toString() : "null";
1569c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            log("processCallTerminated :: ImsCall=" + this + " reason=" + reasonString);
1570b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee        }
1571b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee
1572b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee        ImsCall.Listener listener = null;
1573b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee
1574b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee        synchronized(ImsCall.this) {
1575047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            // If we are in the midst of establishing a conference, we will bury the termination
1576047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            // until the merge has completed.  If necessary we can surface the termination at this
1577047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            // point.
1578c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            if (isCallSessionMergePending()) {
1579b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                // Since we are in the process of a merge, this trigger means something
1580b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                // else because it is probably due to the merge happening vs. the
1581b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                // session is really terminated. Let's flag this and revisit if
1582b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                // the merge() ends up failing because we will need to take action on the
1583b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                // mSession in that case since the termination was not due to the merge
1584b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                // succeeding.
1585b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                if (DBG) {
1586b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                    log("processCallTerminated :: burying termination during ongoing merge.");
1587b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                }
1588b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                mSessionEndDuringMerge = true;
1589b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                mSessionEndDuringMergeReasonInfo = reasonInfo;
1590b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                return;
1591b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee            }
1592b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee
15939bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            // If we are terminating the conference call, notify using conference listeners.
15949bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (isMultiparty()) {
1595b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                notifyConferenceSessionTerminated(reasonInfo);
15969bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                return;
1597b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee            } else {
1598b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                listener = mListener;
1599b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                clear(reasonInfo);
1600b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee            }
1601b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee        }
1602b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee
1603b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee        if (listener != null) {
1604b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee            try {
1605b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                listener.onCallTerminated(ImsCall.this, reasonInfo);
1606b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee            } catch (Throwable t) {
1607c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                loge("processCallTerminated :: ", t);
1608b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee            }
1609b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee        }
1610b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    }
161171382693cbc81b1d131085f52d97879976706f55Anthony Lee
161271382693cbc81b1d131085f52d97879976706f55Anthony Lee    /**
161371382693cbc81b1d131085f52d97879976706f55Anthony Lee     * This function determines if the ImsCallSession is our actual ImsCallSession or if is
161471382693cbc81b1d131085f52d97879976706f55Anthony Lee     * the transient session used in the process of creating a conference. This function should only
161571382693cbc81b1d131085f52d97879976706f55Anthony Lee     * be called within  callbacks that are not directly related to conference merging but might
161671382693cbc81b1d131085f52d97879976706f55Anthony Lee     * potentially still be called on the transient ImsCallSession sent to us from
161771382693cbc81b1d131085f52d97879976706f55Anthony Lee     * callSessionMergeStarted() when we don't really care. In those situations, we probably don't
161871382693cbc81b1d131085f52d97879976706f55Anthony Lee     * want to take any action so we need to know that we can return early.
161971382693cbc81b1d131085f52d97879976706f55Anthony Lee     *
162071382693cbc81b1d131085f52d97879976706f55Anthony Lee     * @param session - The {@link ImsCallSession} that the function needs to analyze
162171382693cbc81b1d131085f52d97879976706f55Anthony Lee     * @return true if this is the transient {@link ImsCallSession}, false otherwise.
162271382693cbc81b1d131085f52d97879976706f55Anthony Lee     */
162371382693cbc81b1d131085f52d97879976706f55Anthony Lee    private boolean isTransientConferenceSession(ImsCallSession session) {
162471382693cbc81b1d131085f52d97879976706f55Anthony Lee        if (session != null && session != mSession && session == mTransientConferenceSession) {
162571382693cbc81b1d131085f52d97879976706f55Anthony Lee            return true;
162671382693cbc81b1d131085f52d97879976706f55Anthony Lee        }
162771382693cbc81b1d131085f52d97879976706f55Anthony Lee        return false;
162871382693cbc81b1d131085f52d97879976706f55Anthony Lee    }
162971382693cbc81b1d131085f52d97879976706f55Anthony Lee
1630c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    private void setTransientSessionAsPrimary(ImsCallSession transientSession) {
1631c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        synchronized (ImsCall.this) {
1632c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            mSession.setListener(null);
1633c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            mSession = transientSession;
1634c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            mSession.setListener(createCallSessionListener());
1635c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        }
1636c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    }
1637c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
163871382693cbc81b1d131085f52d97879976706f55Anthony Lee    /**
1639c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * This function will determine if there is a pending conference and if
1640c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * we are ready to finalize processing it.
1641047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     */
1642c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    private void tryProcessConferenceResult() {
1643c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        if (shouldProcessConferenceResult()) {
1644c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            if (isMergeHost()) {
1645c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                processMergeComplete();
1646c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            } else if (mMergeHost != null) {
1647c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                mMergeHost.processMergeComplete();
1648c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            } else {
1649c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // There must be a merge host at this point.
1650c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                loge("tryProcessConferenceResult :: No merge host for this conference!");
1651c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            }
1652c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        }
1653047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    }
1654047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
1655047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    /**
1656c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * We have detected that a initial conference call has been fully configured. The internal
1657c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * state of both {@code ImsCall} objects need to be cleaned up to reflect the new state.
1658c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * This function should only be called in the context of the merge host to simplify logic
165971382693cbc81b1d131085f52d97879976706f55Anthony Lee     *
166071382693cbc81b1d131085f52d97879976706f55Anthony Lee     */
1661b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    private void processMergeComplete() {
16629bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (VDBG) {
1663c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            log("processMergeComplete :: ImsCall=" + this);
1664c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        }
1665c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
1666c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        // The logic simplifies if we can assume that this function is only called on
1667c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        // the merge host.
1668c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        if (!isMergeHost()) {
1669c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            loge("processMergeComplete :: We are not the merge host!");
1670c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            return;
1671b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee        }
1672b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee
167371382693cbc81b1d131085f52d97879976706f55Anthony Lee        ImsCall.Listener listener;
1674047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        boolean swapRequired = false;
167571382693cbc81b1d131085f52d97879976706f55Anthony Lee        synchronized(ImsCall.this) {
1676c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            ImsCall finalHostCall = this;
1677c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            ImsCall finalPeerCall = mMergePeer;
16789bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
1679c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            if (isMultiparty()) {
1680c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // The only clean up that we need to do for a merge into an existing conference
1681c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // is to deal with the disconnect of the peer if it was successfully added to
1682c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // the conference.
1683c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                setIsMerged(false);
1684c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                if (!isSessionAlive(mMergePeer.mSession)) {
1685c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // If the peer is dead, let's not play a disconnect sound for it when we
1686c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // unbury the termination callback.
1687c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    mMergePeer.setIsMerged(true);
1688c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                } else {
1689c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    mMergePeer.setIsMerged(false);
1690047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                }
1691047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            } else {
1692c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // If we are here, we are not trying to merge a new call into an existing
1693c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // conference.  That means that there is a transient session on the merge
1694c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // host that represents the future conference once all the parties
1695c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // have been added to it.  So make sure that it exists or else something
1696c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // very wrong is going on.
1697c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                if (mTransientConferenceSession == null) {
1698c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    loge("processMergeComplete :: No transient session!");
1699c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    return;
1700047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                }
1701c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                if (mMergePeer == null) {
1702c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    loge("processMergeComplete :: No merge peer!");
1703c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    return;
1704047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                }
1705047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
1706c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // Since we are the host, we have the transient session attached to us. Let's detach
1707c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // it and figure out where we need to set it for the final conference configuration.
1708c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                ImsCallSession transientConferenceSession = mTransientConferenceSession;
1709c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                mTransientConferenceSession = null;
1710c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
1711c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // Clear the listener for this transient session, we'll create a new listener
1712c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // when it is attached to the final ImsCall that it should live on.
1713c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                transientConferenceSession.setListener(null);
1714c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
1715c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // Determine which call the transient session should be moved to.  If the current
1716c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // call session is still alive and the merge peer's session is not, we have a
1717c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // situation where the current call failed to merge into the conference but the
1718c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // merge peer did merge in to the conference.  In this type of scenario the current
1719c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // call will continue as a single party call, yet the background call will become
1720c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // the conference.
1721c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
1722c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                if (isSessionAlive(mSession) && !isSessionAlive(mMergePeer.getCallSession())) {
1723c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // I'm the host but we are moving the transient session to the peer since its
1724c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // session was disconnected and my session is still alive.  This signifies that
1725c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // their session was properly added to the conference but mine was not because
1726c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // it is probably in the held state as opposed to part of the final conference.
1727c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // In this case, we need to set isMerged to false on both calls so the
1728c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // disconnect sound is called when either call disconnects.
1729c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // Note that this case is only valid if this is an initial conference being
1730c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // brought up.
1731c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    finalHostCall = mMergePeer;
1732c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    finalPeerCall = this;
1733c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    swapRequired = true;
1734c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    setIsMerged(false);
1735c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    mMergePeer.setIsMerged(false);
1736047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                    if (VDBG) {
1737c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                        log("processMergeComplete :: transient will transfer to merge peer");
1738047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                    }
1739c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                } else if (!isSessionAlive(mSession) && isSessionAlive(mMergePeer.getCallSession())) {
1740c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // The transient session stays with us and the disconnect sound should be played
1741c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // when the merge peer eventually disconnects since it was not actually added to
1742c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // the conference and is probably sitting in the held state.
1743c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    finalHostCall = this;
1744c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    finalPeerCall = mMergePeer;
1745c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    swapRequired = false;
1746c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    setIsMerged(false);
1747c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    mMergePeer.setIsMerged(false); // Play the disconnect sound
1748047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                    if (VDBG) {
1749c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                        log("processMergeComplete :: transient will stay with the merge host");
1750c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    }
1751c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                } else {
1752c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // The transient session stays with us and the disconnect sound should not be
1753c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // played when we ripple up the disconnect for the merge peer because it was
1754c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // only disconnected to be added to the conference.
1755c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    finalHostCall = this;
1756c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    finalPeerCall = mMergePeer;
1757c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    swapRequired = false;
1758c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    setIsMerged(false);
1759c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    mMergePeer.setIsMerged(true);
1760c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    if (VDBG) {
1761c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                        log("processMergeComplete :: transient will stay with us (I'm the host).");
1762047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                    }
1763047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                }
1764047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
1765c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                if (VDBG) {
1766c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    log("processMergeComplete :: call=" + finalHostCall + " is the final host");
1767c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                }
1768c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
1769c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // Add the transient session to the ImsCall that ended up being the host for the
1770c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // conference.
1771c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                finalHostCall.setTransientSessionAsPrimary(transientConferenceSession);
1772047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            }
1773047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
1774c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            listener = finalHostCall.mListener;
1775c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
1776c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // Clear all the merge related flags.
1777c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            clearMergeInfo();
1778c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
1779c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // For the final peer...let's bubble up any possible disconnects that we had
1780c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // during the merge process
1781c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            finalPeerCall.notifySessionTerminatedDuringMerge();
1782c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // For the final host, let's just bury the disconnects that we my have received
1783c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // during the merge process since we are now the host of the conference call.
1784c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            finalHostCall.clearSessionTerminationFlags();
178571382693cbc81b1d131085f52d97879976706f55Anthony Lee        }
178671382693cbc81b1d131085f52d97879976706f55Anthony Lee        if (listener != null) {
178771382693cbc81b1d131085f52d97879976706f55Anthony Lee            try {
1788047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                listener.onCallMerged(ImsCall.this, swapRequired);
178971382693cbc81b1d131085f52d97879976706f55Anthony Lee            } catch (Throwable t) {
1790b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                loge("processMergeComplete :: ", t);
179171382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
179271382693cbc81b1d131085f52d97879976706f55Anthony Lee        }
179371382693cbc81b1d131085f52d97879976706f55Anthony Lee        return;
179471382693cbc81b1d131085f52d97879976706f55Anthony Lee    }
179571382693cbc81b1d131085f52d97879976706f55Anthony Lee
179671382693cbc81b1d131085f52d97879976706f55Anthony Lee    /**
1797047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * Handles the case where the session has ended during a merge by reporting the termination
1798047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * reason to listeners.
1799047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     */
1800047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    private void notifySessionTerminatedDuringMerge() {
1801047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        ImsCall.Listener listener;
1802047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        boolean notifyFailure = false;
1803047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        ImsReasonInfo notifyFailureReasonInfo = null;
1804047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
1805047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        synchronized(ImsCall.this) {
1806047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            listener = mListener;
1807047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            if (mSessionEndDuringMerge) {
1808047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                // Set some local variables that will send out a notification about a
1809047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                // previously buried termination callback for our primary session now that
1810047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                // we know that this is not due to the conference call merging successfully.
1811047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                if (DBG) {
1812047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                    log("notifySessionTerminatedDuringMerge ::reporting terminate during merge");
1813047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                }
1814047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                notifyFailure = true;
1815047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                notifyFailureReasonInfo = mSessionEndDuringMergeReasonInfo;
1816047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            }
1817c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            clearSessionTerminationFlags();
1818047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        }
1819047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
1820047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        if (listener != null && notifyFailure) {
1821047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            try {
1822047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                processCallTerminated(notifyFailureReasonInfo);
1823047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            } catch (Throwable t) {
1824047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                loge("notifySessionTerminatedDuringMerge :: ", t);
1825047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            }
1826047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        }
1827047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    }
1828047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
1829c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    private void clearSessionTerminationFlags() {
1830c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        mSessionEndDuringMerge = false;
1831c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        mSessionEndDuringMergeReasonInfo = null;
1832c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    }
1833c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
1834047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    /**
183571382693cbc81b1d131085f52d97879976706f55Anthony Lee     * We received a callback from ImsCallSession that a merge failed. Clean up all
1836c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * internal state to represent this state change.  The calling function is a callback
1837c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * and should have been called on the session that was in the foreground
1838c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * when merge() was originally called.  It is assumed that this function will be called
1839c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * on the merge host.
184071382693cbc81b1d131085f52d97879976706f55Anthony Lee     *
184171382693cbc81b1d131085f52d97879976706f55Anthony Lee     * @param reasonInfo The {@link ImsReasonInfo} why the merge failed.
184271382693cbc81b1d131085f52d97879976706f55Anthony Lee     */
1843b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    private void processMergeFailed(ImsReasonInfo reasonInfo) {
18449bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (VDBG) {
1845c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            log("processMergeFailed :: this=" + this + "reason=" + reasonInfo);
1846047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        }
1847047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
1848047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        ImsCall.Listener listener;
184971382693cbc81b1d131085f52d97879976706f55Anthony Lee        synchronized(ImsCall.this) {
1850c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // The logic simplifies if we can assume that this function is only called on
1851c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // the merge host.
1852c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            if (!isMergeHost()) {
1853c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                loge("processMergeFailed :: We are not the merge host!");
1854c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                return;
1855c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            }
1856c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
1857c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            if (mMergePeer == null) {
1858c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                loge("processMergeFailed :: No merge peer!");
1859c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                return;
1860c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            }
1861c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
1862c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            if (!isMultiparty()) {
1863c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                if (mTransientConferenceSession == null) {
1864c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    loge("processMergeFailed :: No transient session!");
1865c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    return;
1866c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                }
186771382693cbc81b1d131085f52d97879976706f55Anthony Lee                // Clean up any work that we performed on the transient session.
186871382693cbc81b1d131085f52d97879976706f55Anthony Lee                mTransientConferenceSession.setListener(null);
186971382693cbc81b1d131085f52d97879976706f55Anthony Lee                mTransientConferenceSession = null;
1870b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee            }
1871047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
1872c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // Ensure the calls being conferenced into the conference has isMerged = false.
1873c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            setIsMerged(false);
1874c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            mMergePeer.setIsMerged(false);
18759bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
1876c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            listener = mListener;
1877c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
1878c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // Ensure any terminations are surfaced from this session.
1879c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            notifySessionTerminatedDuringMerge();
1880c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            mMergePeer.notifySessionTerminatedDuringMerge();
1881c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
1882c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // Clear all the various flags around coordinating this merge.
1883c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            clearMergeInfo();
188471382693cbc81b1d131085f52d97879976706f55Anthony Lee        }
188571382693cbc81b1d131085f52d97879976706f55Anthony Lee        if (listener != null) {
188671382693cbc81b1d131085f52d97879976706f55Anthony Lee            try {
188771382693cbc81b1d131085f52d97879976706f55Anthony Lee                listener.onCallMergeFailed(ImsCall.this, reasonInfo);
188871382693cbc81b1d131085f52d97879976706f55Anthony Lee            } catch (Throwable t) {
1889b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                loge("processMergeFailed :: ", t);
189071382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
189171382693cbc81b1d131085f52d97879976706f55Anthony Lee        }
1892c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
189371382693cbc81b1d131085f52d97879976706f55Anthony Lee        return;
189471382693cbc81b1d131085f52d97879976706f55Anthony Lee    }
189571382693cbc81b1d131085f52d97879976706f55Anthony Lee
1896ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void notifyError(int reason, int statusCode, String message) {
1897ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1898ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1899ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void throwImsException(Throwable t, int code) throws ImsException {
1900ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (t instanceof ImsException) {
1901ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            throw (ImsException) t;
1902ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        } else {
1903ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            throw new ImsException(String.valueOf(code), t, code);
1904ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1905ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1906ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1907ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void log(String s) {
1908ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        Rlog.d(TAG, s);
1909ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1910ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
19119bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    /**
19129bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * Logs the specified message, as well as the current instance of {@link ImsCall}.
19139bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     *
19149bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * @param s The message to log.
19159bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     */
19169bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    private void logv(String s) {
19179bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        StringBuilder sb = new StringBuilder();
19189bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        sb.append(s);
19199bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        sb.append(" imsCall=");
19209bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        sb.append(ImsCall.this);
19219bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        Rlog.v(TAG, sb.toString());
19229bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    }
19239bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
1924ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void loge(String s) {
1925ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        Rlog.e(TAG, s);
1926ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1927ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1928ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void loge(String s, Throwable t) {
1929ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        Rlog.e(TAG, s, t);
1930ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1931ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1932ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private class ImsCallSessionListenerProxy extends ImsCallSession.Listener {
1933ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
193471382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionProgressing(ImsCallSession session, ImsStreamMediaProfile profile) {
193571382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
1936c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // If it is a transient (conference) session, there is no action for this signal.
1937b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                log("callSessionProgressing :: not supported for transient conference session=" +
1938b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
193971382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
194071382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
194171382693cbc81b1d131085f52d97879976706f55Anthony Lee
19429bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
1943c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                log("callSessionProgressing :: session=" + session + " profile=" + profile);
1944ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1945ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1946ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
1947ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1948ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
1949ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
1950ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallProfile.mMediaProfile.copyFrom(profile);
1951ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1952ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1953ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
1954ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
1955ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallProgressing(ImsCall.this);
1956ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
1957ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionProgressing :: ", t);
1958ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1959ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1960ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1961ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1962ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
196371382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionStarted(ImsCallSession session, ImsCallProfile profile) {
19649bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
1965c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                log("callSessionStarted :: session=" + session + " profile=" + profile);
1966c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            }
1967c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
1968c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            if (!isTransientConferenceSession(session)) {
1969c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // In the case that we are in the middle of a merge (either host or peer), we have
1970c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // closure as far as this call's primary session is concerned.  If we are not
1971c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // merging...its a NOOP.
1972c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                setCallSessionMergePending(false);
1973c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            } else {
1974c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                if (VDBG) {
1975c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    log("callSessionStarted :: on transient session=" + session);
1976c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                }
1977c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                return;
1978ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1979ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1980047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            // Check if there is an ongoing conference merge which has completed.  If there is
1981047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            // we can process the merge completion now.
1982c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            tryProcessConferenceResult();
1983c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
1984c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            if (isTransientConferenceSession(session)) {
1985c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // No further processing is needed if this is the transient session.
1986b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                return;
1987b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee            }
1988b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee
1989ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
1990ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1991ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
1992ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
1993ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallProfile = profile;
1994ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1995ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1996ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
1997ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
1998ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallStarted(ImsCall.this);
1999ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2000ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionStarted :: ", t);
2001ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2002ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2003ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2004ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2005ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
200671382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionStartFailed(ImsCallSession session, ImsReasonInfo reasonInfo) {
200771382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2008c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // We should not get this callback for a transient session.
2009b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                log("callSessionStartFailed :: not supported for transient conference session=" +
2010b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
201171382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
201271382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
201371382693cbc81b1d131085f52d97879976706f55Anthony Lee
20149bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2015c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                log("callSessionStartFailed :: session=" + session + " reasonInfo=" + reasonInfo);
2016ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2017ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2018ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2019ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2020ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2021ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2022ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mLastReasonInfo = reasonInfo;
2023ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2024ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2025ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2026ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2027ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallStartFailed(ImsCall.this, reasonInfo);
2028ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2029ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionStarted :: ", t);
2030ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2031ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2032ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2033ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2034ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
203571382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionTerminated(ImsCallSession session, ImsReasonInfo reasonInfo) {
2036c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            if (isTransientConferenceSession(session)) {
2037c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                log("callSessionTerminated :: on transient session=" + session);
2038c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // This is bad, it should be treated much a callSessionMergeFailed since the
2039c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // transient session only exists when in the process of a merge and the
2040c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // termination of this session is effectively the end of the merge.
2041c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                processMergeFailed(reasonInfo);
204271382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
204371382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
204471382693cbc81b1d131085f52d97879976706f55Anthony Lee
2045c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            if (VDBG) {
2046c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                log("callSessionTerminated :: session=" + session + " reasonInfo=" + reasonInfo);
2047c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            }
2048c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
2049c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // Process the termination first.  If we are in the midst of establishing a conference
2050c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // call, we may bury this callback until we are done.  If there so no conference
2051c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // call, the code after this function will be a NOOP.
2052c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            processCallTerminated(reasonInfo);
2053c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
2054047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            // If session has terminated, it is no longer pending merge.
2055047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            setCallSessionMergePending(false);
2056047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
2057047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            // Check if there is an ongoing conference merge which has completed.  If there is
2058047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            // we can process the merge completion now.
2059c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            tryProcessConferenceResult();
2060ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2061ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2062ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
206371382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionHeld(ImsCallSession session, ImsCallProfile profile) {
206471382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2065c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // We should not get this callback for a transient session.
2066b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                log("callSessionHeld :: not supported for transient conference session=" + session);
206771382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
206871382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
206971382693cbc81b1d131085f52d97879976706f55Anthony Lee
20709bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2071c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                log("callSessionHeld :: session=" + session + "profile=" + profile);
2072ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2073ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2074ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2075ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2076ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2077047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                // If the session was held, it is no longer pending a merge -- this means it could
2078047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                // not be merged into the conference and was held instead.
2079047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                setCallSessionMergePending(false);
2080047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
2081ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallProfile = profile;
2082ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2083ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (mUpdateRequest == UPDATE_HOLD_MERGE) {
2084c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // This hold request was made to set the stage for a merge.
2085ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    mergeInternal();
2086ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    return;
2087ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2088ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2089047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                // Check if there is an ongoing conference merge which has completed.  If there is
2090c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // we can process the merge completion now.  processMergeComplete needs to be
2091c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // called on the merge host.
2092c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                tryProcessConferenceResult();
2093047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
2094ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2095ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2096ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2097ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2098ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2099ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2100ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallHeld(ImsCall.this);
2101ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2102ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionHeld :: ", t);
2103ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2104ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2105ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2106ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2107ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
210871382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionHoldFailed(ImsCallSession session, ImsReasonInfo reasonInfo) {
210971382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2110c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // We should not get this callback for a transient session.
2111b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                log("callSessionHoldFailed :: not supported for transient conference session=" +
2112b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
211371382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
211471382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
211571382693cbc81b1d131085f52d97879976706f55Anthony Lee
21169bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2117c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                log("callSessionHoldFailed :: session" + session + "reasonInfo=" + reasonInfo);
2118ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2119ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2120ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            boolean isHoldForMerge = false;
2121ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2122ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2123ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2124ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (mUpdateRequest == UPDATE_HOLD_MERGE) {
2125ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    isHoldForMerge = true;
2126ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2127ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2128ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2129ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2130ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2131ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2132ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2133ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2134ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallHoldFailed(ImsCall.this, reasonInfo);
2135ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2136ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionHoldFailed :: ", t);
2137ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2138ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2139ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2140ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2141ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
214271382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionHoldReceived(ImsCallSession session, ImsCallProfile profile) {
214371382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2144c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // We should not get this callback for a transient session.
2145b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                log("callSessionHoldReceived :: not supported for transient conference session=" +
2146b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
214771382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
214871382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
214971382693cbc81b1d131085f52d97879976706f55Anthony Lee
21509bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2151c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                log("callSessionHoldReceived :: session=" + session + "profile=" + profile);
2152ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2153ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2154ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2155ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2156ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2157ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2158ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallProfile = profile;
2159ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2160ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2161ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2162ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2163ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallHoldReceived(ImsCall.this);
2164ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2165ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionHoldReceived :: ", t);
2166ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2167ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2168ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2169ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2170ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
217171382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionResumed(ImsCallSession session, ImsCallProfile profile) {
217271382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2173b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                log("callSessionResumed :: not supported for transient conference session=" +
2174b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
217571382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
217671382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
217771382693cbc81b1d131085f52d97879976706f55Anthony Lee
21789bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2179c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                log("callSessionResumed :: session=" + session + "profile=" + profile);
2180ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2181ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2182c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // If this call was pending a merge, it is not anymore. This is the case when we
2183c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // are merging in a new call into an existing conference.
2184c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            setCallSessionMergePending(false);
2185c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
2186c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // Check if there is an ongoing conference merge which has completed.  If there is
2187c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // we can process the merge completion now.
2188c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            tryProcessConferenceResult();
2189c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
2190c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // TOOD: When we are merging a new call into an existing conference we are waiting
2191c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // for 2 triggers to let us know that the conference has been established, the first
2192c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // is a termination for the new calls (since it is added to the conference) the second
2193c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // would be a resume on the existing conference.  If the resume comes first, then
2194c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // we will make the onCallResumed() callback and its unclear how this will behave if
2195c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // the termination has not come yet.
2196ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2197c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            ImsCall.Listener listener;
2198ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2199ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2200ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallProfile = profile;
2201ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2202095839a66699a128c76cd5002459fcba7c3a9a0dUma Maheswari Ramalingam                mHold = false;
2203ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2204ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2205ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2206ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2207ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallResumed(ImsCall.this);
2208ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2209ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionResumed :: ", t);
2210ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2211ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2212ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2213ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2214ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
221571382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionResumeFailed(ImsCallSession session, ImsReasonInfo reasonInfo) {
221671382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2217b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                log("callSessionResumeFailed :: not supported for transient conference session=" +
2218b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
221971382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
222071382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
222171382693cbc81b1d131085f52d97879976706f55Anthony Lee
22229bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2223c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                log("callSessionResumeFailed :: session=" + session + "reasonInfo=" + reasonInfo);
2224ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2225ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2226ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2227ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2228ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2229ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2230ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2231ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2232ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2233ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2234ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2235ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallResumeFailed(ImsCall.this, reasonInfo);
2236ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2237ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionResumeFailed :: ", t);
2238ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2239ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2240ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2241ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2242ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
224371382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionResumeReceived(ImsCallSession session, ImsCallProfile profile) {
224471382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2245b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                log("callSessionResumeReceived :: not supported for transient conference session=" +
2246b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
224771382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
224871382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
224971382693cbc81b1d131085f52d97879976706f55Anthony Lee
22509bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2251c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                log("callSessionResumeReceived :: session=" + session + "profile=" + profile);
2252ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2253ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2254ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2255ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2256ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2257ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2258ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallProfile = profile;
2259ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2260ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2261ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2262ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2263ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallResumeReceived(ImsCall.this);
2264ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2265ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionResumeReceived :: ", t);
2266ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2267ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2268ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2269ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2270ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
22713f2b0aaa277545886571cbf90fc90fd5d304e714Tyler Gunn        public void callSessionMergeStarted(ImsCallSession session,
2272ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsCallSession newSession, ImsCallProfile profile) {
22739bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2274c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                log("callSessionMergeStarted :: session=" + session + " newSession=" + newSession +
22759bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                        ", profile=" + profile);
2276ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2277ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2278c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            if (!isCallSessionMergePending()) {
227971382693cbc81b1d131085f52d97879976706f55Anthony Lee                // Odd, we are not in the midst of merging anything.
22809bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                log("callSessionMergeStarted :: no merge in progress.");
2281ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return;
2282ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2283ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
228471382693cbc81b1d131085f52d97879976706f55Anthony Lee            // There are 2 ways that we can go here.  If the session that supplied the params
228571382693cbc81b1d131085f52d97879976706f55Anthony Lee            // is not null, then it is the new session that represents the new conference
228671382693cbc81b1d131085f52d97879976706f55Anthony Lee            // if the merge succeeds. If it is null, the merge is happening on our current
228771382693cbc81b1d131085f52d97879976706f55Anthony Lee            // ImsCallSession.
228871382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (session == null) {
228971382693cbc81b1d131085f52d97879976706f55Anthony Lee                // Everything is already set up and we just need to make sure
229071382693cbc81b1d131085f52d97879976706f55Anthony Lee                // that we properly respond to all the future callbacks about
229171382693cbc81b1d131085f52d97879976706f55Anthony Lee                // this merge.
229271382693cbc81b1d131085f52d97879976706f55Anthony Lee                if (DBG) {
229371382693cbc81b1d131085f52d97879976706f55Anthony Lee                    log("callSessionMergeStarted :: merging into existing ImsCallSession");
229471382693cbc81b1d131085f52d97879976706f55Anthony Lee                }
229571382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
229671382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
2297ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
229871382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (DBG) {
229971382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionMergeStarted ::  setting our transient ImsCallSession");
2300ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2301ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
230271382693cbc81b1d131085f52d97879976706f55Anthony Lee            // If we are here, this means that we are creating a new conference and
230371382693cbc81b1d131085f52d97879976706f55Anthony Lee            // we need to do some extra work around managing a new ImsCallSession that
230471382693cbc81b1d131085f52d97879976706f55Anthony Lee            // could represent our new ImsCallSession if the merge succeeds.
230571382693cbc81b1d131085f52d97879976706f55Anthony Lee            synchronized(ImsCall.this) {
230671382693cbc81b1d131085f52d97879976706f55Anthony Lee                // Keep track of this session for future callbacks to indicate success
230771382693cbc81b1d131085f52d97879976706f55Anthony Lee                // or failure of this merge.
230871382693cbc81b1d131085f52d97879976706f55Anthony Lee                mTransientConferenceSession = newSession;
230971382693cbc81b1d131085f52d97879976706f55Anthony Lee                mTransientConferenceSession.setListener(createCallSessionListener());
2310ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
231171382693cbc81b1d131085f52d97879976706f55Anthony Lee
231271382693cbc81b1d131085f52d97879976706f55Anthony Lee            return;
2313ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2314ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2315ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
23163f2b0aaa277545886571cbf90fc90fd5d304e714Tyler Gunn        public void callSessionMergeComplete(ImsCallSession session) {
23179bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2318c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                log("callSessionMergeComplete :: session=" + session);
23193f2b0aaa277545886571cbf90fc90fd5d304e714Tyler Gunn            }
2320047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
2321c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            setCallSessionMergePending(false);
2322c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
2323047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            // Check if there is an ongoing conference merge which has completed.  If there is
2324047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            // we can process the merge completion now.
2325c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            tryProcessConferenceResult();
23263f2b0aaa277545886571cbf90fc90fd5d304e714Tyler Gunn        }
23273f2b0aaa277545886571cbf90fc90fd5d304e714Tyler Gunn
23283f2b0aaa277545886571cbf90fc90fd5d304e714Tyler Gunn        @Override
232971382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionMergeFailed(ImsCallSession session, ImsReasonInfo reasonInfo) {
23309bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2331c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                log("callSessionMergeFailed :: session=" + session + "reasonInfo=" + reasonInfo);
2332ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2333c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
2334c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // Its possible that there could be threading issues with the other thread handling
2335c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // the other call. This could affect our state.
2336c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            synchronized (ImsCall.this) {
2337c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                if (!isCallSessionMergePending()) {
2338c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // Odd, we are not in the midst of merging anything.
2339c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    log("callSessionMergeFailed :: no merge in progress.");
2340c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    return;
2341c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                }
2342c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // Let's tell our parent ImsCall that the merge has failed and we need to clean
2343c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // up any temporary, transient state.  Note this only gets called for an initial
2344c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // conference.  If a merge into an existing conference fails, the two sessions will
2345c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // just go back to their original state (ACTIVE or HELD).
2346c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                if (isMergeHost()) {
2347c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    processMergeFailed(reasonInfo);
2348c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                } else if (mMergeHost != null) {
2349c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    mMergeHost.processMergeFailed(reasonInfo);
2350c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                } else {
2351c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    loge("callSessionMergeFailed :: No merge host for this conference!");
2352c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                }
2353ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2354ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2355ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2356ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
235771382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionUpdated(ImsCallSession session, ImsCallProfile profile) {
235871382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2359b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                log("callSessionUpdated :: not supported for transient conference session=" +
2360b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
236171382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
236271382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
236371382693cbc81b1d131085f52d97879976706f55Anthony Lee
23649bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2365c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                log("callSessionUpdated :: session=" + session + " profile=" + profile);
2366ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2367ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2368ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2369ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2370ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2371ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2372ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallProfile = profile;
2373ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2374ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2375ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2376ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2377ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2378ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallUpdated(ImsCall.this);
2379ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2380ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionUpdated :: ", t);
2381ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2382ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2383ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2384ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2385ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
238671382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionUpdateFailed(ImsCallSession session, ImsReasonInfo reasonInfo) {
238771382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2388b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                log("callSessionUpdateFailed :: not supported for transient conference session=" +
2389b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
239071382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
239171382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
239271382693cbc81b1d131085f52d97879976706f55Anthony Lee
23939bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2394c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                log("callSessionUpdateFailed :: session=" + session + " reasonInfo=" + reasonInfo);
2395ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2396ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2397ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2398ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2399ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2400ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2401ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2402ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2403ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2404ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2405ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2406ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallUpdateFailed(ImsCall.this, reasonInfo);
2407ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2408ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionUpdateFailed :: ", t);
2409ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2410ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2411ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2412ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2413ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
241471382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionUpdateReceived(ImsCallSession session, ImsCallProfile profile) {
241571382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2416b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                log("callSessionUpdateReceived :: not supported for transient conference " +
2417b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        "session=" + session);
241871382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
241971382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
242071382693cbc81b1d131085f52d97879976706f55Anthony Lee
24219bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2422c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                log("callSessionUpdateReceived :: session=" + session + " profile=" + profile);
2423ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2424ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2425ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2426ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2427ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2428ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2429ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mProposedCallProfile = profile;
2430ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_UNSPECIFIED;
2431ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2432ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2433ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2434ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2435ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallUpdateReceived(ImsCall.this);
2436ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2437ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionUpdateReceived :: ", t);
2438ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2439ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2440ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2441ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2442ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
244371382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionConferenceExtended(ImsCallSession session, ImsCallSession newSession,
244471382693cbc81b1d131085f52d97879976706f55Anthony Lee                ImsCallProfile profile) {
244571382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2446b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                log("callSessionConferenceExtended :: not supported for transient conference " +
2447b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        "session=" + session);
244871382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
244971382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
245071382693cbc81b1d131085f52d97879976706f55Anthony Lee
24519bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2452c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                log("callSessionConferenceExtended :: session=" + session  + " newSession=" +
2453c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                        newSession + ", profile=" + profile);
2454ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2455ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2456ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall newCall = createNewCall(newSession, profile);
2457ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2458ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (newCall == null) {
2459ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                callSessionConferenceExtendFailed(session, new ImsReasonInfo());
2460ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return;
2461ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2462ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2463ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2464ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2465ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2466ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2467ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2468ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2469ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2470ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2471ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2472ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallConferenceExtended(ImsCall.this, newCall);
2473ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2474ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionConferenceExtended :: ", t);
2475ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2476ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2477ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2478ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2479ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2480ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionConferenceExtendFailed(ImsCallSession session,
2481ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsReasonInfo reasonInfo) {
248271382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2483b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                log("callSessionConferenceExtendFailed :: not supported for transient " +
2484b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        "conference session=" + session);
248571382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
248671382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
248771382693cbc81b1d131085f52d97879976706f55Anthony Lee
2488ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
24899bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                log("callSessionConferenceExtendFailed :: imsCall=" + ImsCall.this +
2490ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ", reasonInfo=" + reasonInfo);
2491ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2492ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2493ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2494ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2495ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2496ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2497ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2498ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2499ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2500ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2501ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2502ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallConferenceExtendFailed(ImsCall.this, reasonInfo);
2503ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2504ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionConferenceExtendFailed :: ", t);
2505ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2506ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2507ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2508ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2509ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2510ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionConferenceExtendReceived(ImsCallSession session,
2511ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsCallSession newSession, ImsCallProfile profile) {
251271382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2513b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                log("callSessionConferenceExtendReceived :: not supported for transient " +
25149bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                        "conference session" + session);
251571382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
251671382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
251771382693cbc81b1d131085f52d97879976706f55Anthony Lee
25189bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2519c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                log("callSessionConferenceExtendReceived :: newSession=" + newSession +
25209bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                        ", profile=" + profile);
2521ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2522ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2523ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall newCall = createNewCall(newSession, profile);
2524ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2525ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (newCall == null) {
2526ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                // Should all the calls be terminated...???
2527ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return;
2528ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2529ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2530ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2531ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2532ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2533ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2534ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2535ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2536ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2537ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2538ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallConferenceExtendReceived(ImsCall.this, newCall);
2539ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2540ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionConferenceExtendReceived :: ", t);
2541ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2542ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2543ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2544ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2545ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2546ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionInviteParticipantsRequestDelivered(ImsCallSession session) {
254771382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
254871382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionInviteParticipantsRequestDelivered :: not supported for " +
254971382693cbc81b1d131085f52d97879976706f55Anthony Lee                        "conference session=" + session);
255071382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
255171382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
255271382693cbc81b1d131085f52d97879976706f55Anthony Lee
25539bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2554c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                log("callSessionInviteParticipantsRequestDelivered ::");
2555ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2556ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2557ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2558ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2559ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2560ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2561ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2562ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2563ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2564ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2565ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallInviteParticipantsRequestDelivered(ImsCall.this);
2566ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2567ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionInviteParticipantsRequestDelivered :: ", t);
2568ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2569ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2570ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2571ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2572ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2573ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionInviteParticipantsRequestFailed(ImsCallSession session,
2574ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsReasonInfo reasonInfo) {
257571382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
257671382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionInviteParticipantsRequestFailed :: not supported for " +
257771382693cbc81b1d131085f52d97879976706f55Anthony Lee                        "conference session=" + session);
257871382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
257971382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
258071382693cbc81b1d131085f52d97879976706f55Anthony Lee
25819bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2582c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                log("callSessionInviteParticipantsRequestFailed :: reasonInfo=" + reasonInfo);
2583ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2584ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2585ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2586ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2587ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2588ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2589ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2590ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2591ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2592ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2593ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallInviteParticipantsRequestFailed(ImsCall.this, reasonInfo);
2594ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2595ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionInviteParticipantsRequestFailed :: ", t);
2596ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2597ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2598ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2599ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2600ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2601ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionRemoveParticipantsRequestDelivered(ImsCallSession session) {
260271382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
260371382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionRemoveParticipantsRequestDelivered :: not supported for " +
260471382693cbc81b1d131085f52d97879976706f55Anthony Lee                        "conference session=" + session);
260571382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
260671382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
260771382693cbc81b1d131085f52d97879976706f55Anthony Lee
26089bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2609c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                log("callSessionRemoveParticipantsRequestDelivered ::");
2610ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2611ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2612ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2613ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2614ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2615ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2616ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2617ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2618ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2619ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2620ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallRemoveParticipantsRequestDelivered(ImsCall.this);
2621ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2622ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionRemoveParticipantsRequestDelivered :: ", t);
2623ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2624ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2625ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2626ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2627ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2628ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionRemoveParticipantsRequestFailed(ImsCallSession session,
2629ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsReasonInfo reasonInfo) {
263071382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
263171382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionRemoveParticipantsRequestFailed :: not supported for " +
26329bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                        "conference session=" + session);
263371382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
263471382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
263571382693cbc81b1d131085f52d97879976706f55Anthony Lee
26369bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2637c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                log("callSessionRemoveParticipantsRequestFailed :: reasonInfo=" + reasonInfo);
2638ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2639ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2640ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2641ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2642ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2643ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2644ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2645ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2646ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2647ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2648ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallRemoveParticipantsRequestFailed(ImsCall.this, reasonInfo);
2649ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2650ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionRemoveParticipantsRequestFailed :: ", t);
2651ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2652ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2653ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2654ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2655ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2656ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionConferenceStateUpdated(ImsCallSession session,
2657ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsConferenceState state) {
265871382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2659b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                log("callSessionConferenceStateUpdated :: not supported for transient " +
2660b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        "conference session=" + session);
266171382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
266271382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
266371382693cbc81b1d131085f52d97879976706f55Anthony Lee
26649bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2665c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                log("callSessionConferenceStateUpdated :: state=" + state);
2666ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2667ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2668938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn            conferenceStateUpdated(state);
2669ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2670ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2671ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
267271382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionUssdMessageReceived(ImsCallSession session, int mode,
267371382693cbc81b1d131085f52d97879976706f55Anthony Lee                String ussdMessage) {
267471382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2675b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                log("callSessionUssdMessageReceived :: not supported for transient " +
2676b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        "conference session=" + session);
267771382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
267871382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
267971382693cbc81b1d131085f52d97879976706f55Anthony Lee
26809bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2681c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                log("callSessionUssdMessageReceived :: mode=" + mode + ", ussdMessage=" +
26829bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                        ussdMessage);
2683ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2684ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2685ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2686ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2687ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2688ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2689ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2690ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2691ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2692ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2693ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallUssdMessageReceived(ImsCall.this, mode, ussdMessage);
2694ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2695ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionUssdMessageReceived :: ", t);
2696ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2697ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2698ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2699987bab859324396c0d1fc00c375f98f3f74c9067Pavel Zhamaitsiak
2700987bab859324396c0d1fc00c375f98f3f74c9067Pavel Zhamaitsiak        @Override
2701987bab859324396c0d1fc00c375f98f3f74c9067Pavel Zhamaitsiak        public void callSessionTtyModeReceived(ImsCallSession session, int mode) {
27029bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2703c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                log("callSessionTtyModeReceived :: mode=" + mode);
2704987bab859324396c0d1fc00c375f98f3f74c9067Pavel Zhamaitsiak            }
2705987bab859324396c0d1fc00c375f98f3f74c9067Pavel Zhamaitsiak
2706a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak            ImsCall.Listener listener;
2707a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak
2708a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak            synchronized(ImsCall.this) {
2709a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak                listener = mListener;
2710a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak            }
2711a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak
2712a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak            if (listener != null) {
2713a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak                try {
2714a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak                    listener.onCallSessionTtyModeReceived(ImsCall.this, mode);
2715a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak                } catch (Throwable t) {
2716a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak                    loge("callSessionTtyModeReceived :: ", t);
2717987bab859324396c0d1fc00c375f98f3f74c9067Pavel Zhamaitsiak                }
2718987bab859324396c0d1fc00c375f98f3f74c9067Pavel Zhamaitsiak            }
2719987bab859324396c0d1fc00c375f98f3f74c9067Pavel Zhamaitsiak        }
27201463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar
27211463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar        public void callSessionHandover(ImsCallSession session, int srcAccessTech,
27221463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            int targetAccessTech, ImsReasonInfo reasonInfo) {
27231463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            if (DBG) {
27241463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                log("callSessionHandover :: session=" + session + ", srcAccessTech=" +
27251463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                    srcAccessTech + ", targetAccessTech=" + targetAccessTech + ", reasonInfo=" +
27261463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                    reasonInfo);
27271463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            }
27281463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar
27291463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            ImsCall.Listener listener;
27301463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar
27311463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            synchronized(ImsCall.this) {
27321463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                listener = mListener;
27331463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            }
27341463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar
27351463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            if (listener != null) {
27361463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                try {
27371463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                    listener.onCallHandover(ImsCall.this, srcAccessTech, targetAccessTech,
27381463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                        reasonInfo);
27391463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                } catch (Throwable t) {
27401463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                    loge("callSessionHandover :: ", t);
27411463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                }
27421463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            }
27431463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar        }
27441463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar
27451463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar        @Override
27461463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar        public void callSessionHandoverFailed(ImsCallSession session, int srcAccessTech,
27471463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            int targetAccessTech, ImsReasonInfo reasonInfo) {
27481463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            if (DBG) {
27491463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                log("callSessionHandoverFailed :: session=" + session + ", srcAccessTech=" +
27501463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                    srcAccessTech + ", targetAccessTech=" + targetAccessTech + ", reasonInfo=" +
27511463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                    reasonInfo);
27521463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            }
27531463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar
27541463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            ImsCall.Listener listener;
27551463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar
27561463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            synchronized(ImsCall.this) {
27571463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                listener = mListener;
27581463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            }
27591463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar
27601463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            if (listener != null) {
27611463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                try {
27621463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                    listener.onCallHandoverFailed(ImsCall.this, srcAccessTech, targetAccessTech,
27631463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                        reasonInfo);
27641463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                } catch (Throwable t) {
27651463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                    loge("callSessionHandoverFailed :: ", t);
27661463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                }
27671463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            }
27681463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar        }
2769ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
2770938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn
2771938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn    /**
2772938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     * Report a new conference state to the current {@link ImsCall} and inform listeners of the
2773938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     * change.  Marked as {@code VisibleForTesting} so that the
2774938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     * {@code com.android.internal.telephony.TelephonyTester} class can inject a test conference
2775938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     * event package into a regular ongoing IMS call.
2776938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     *
2777938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     * @param state The {@link ImsConferenceState}.
2778938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     */
2779938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn    @VisibleForTesting
2780938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn    public void conferenceStateUpdated(ImsConferenceState state) {
2781938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn        Listener listener;
2782938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn
2783938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn        synchronized(this) {
2784938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn            notifyConferenceStateUpdated(state);
2785938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn            listener = mListener;
2786938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn        }
2787938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn
2788938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn        if (listener != null) {
2789938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn            try {
2790938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn                listener.onCallConferenceStateUpdated(this, state);
2791938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn            } catch (Throwable t) {
2792938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn                loge("callSessionConferenceStateUpdated :: ", t);
2793938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn            }
2794938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn        }
2795938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn    }
2796168c634eef29f21c73129164207d04b8cce23738Tyler Gunn
2797168c634eef29f21c73129164207d04b8cce23738Tyler Gunn    /**
2798168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     * Provides a human-readable string representation of an update request.
2799168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     *
2800168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     * @param updateRequest The update request.
2801168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     * @return The string representation.
2802168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     */
2803168c634eef29f21c73129164207d04b8cce23738Tyler Gunn    private String updateRequestToString(int updateRequest) {
2804168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        switch (updateRequest) {
2805168c634eef29f21c73129164207d04b8cce23738Tyler Gunn            case UPDATE_NONE:
2806168c634eef29f21c73129164207d04b8cce23738Tyler Gunn                return "NONE";
2807168c634eef29f21c73129164207d04b8cce23738Tyler Gunn            case UPDATE_HOLD:
2808168c634eef29f21c73129164207d04b8cce23738Tyler Gunn                return "HOLD";
2809168c634eef29f21c73129164207d04b8cce23738Tyler Gunn            case UPDATE_HOLD_MERGE:
2810168c634eef29f21c73129164207d04b8cce23738Tyler Gunn                return "HOLD_MERGE";
2811168c634eef29f21c73129164207d04b8cce23738Tyler Gunn            case UPDATE_RESUME:
2812168c634eef29f21c73129164207d04b8cce23738Tyler Gunn                return "RESUME";
2813168c634eef29f21c73129164207d04b8cce23738Tyler Gunn            case UPDATE_MERGE:
2814168c634eef29f21c73129164207d04b8cce23738Tyler Gunn                return "MERGE";
2815168c634eef29f21c73129164207d04b8cce23738Tyler Gunn            case UPDATE_EXTEND_TO_CONFERENCE:
2816168c634eef29f21c73129164207d04b8cce23738Tyler Gunn                return "EXTEND_TO_CONFERENCE";
2817168c634eef29f21c73129164207d04b8cce23738Tyler Gunn            case UPDATE_UNSPECIFIED:
2818168c634eef29f21c73129164207d04b8cce23738Tyler Gunn                return "UNSPECIFIED";
2819168c634eef29f21c73129164207d04b8cce23738Tyler Gunn            default:
2820168c634eef29f21c73129164207d04b8cce23738Tyler Gunn                return "UNKNOWN";
2821168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        }
2822168c634eef29f21c73129164207d04b8cce23738Tyler Gunn    }
2823168c634eef29f21c73129164207d04b8cce23738Tyler Gunn
2824168c634eef29f21c73129164207d04b8cce23738Tyler Gunn    /**
28259bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * Clears the merge peer for this call, ensuring that the peer's connection to this call is also
28269bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * severed at the same time.
28279bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     */
2828c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    private void clearMergeInfo() {
2829c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        if (VDBG) {
2830c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            log("clearMergeInfo :: clearing all merge info");
2831c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        }
2832047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
2833c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        // First clear out the merge partner then clear ourselves out.
28349bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (mMergeHost != null) {
28359bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            mMergeHost.mMergePeer = null;
2836165aed55d289ae2a5cdf34de4164c2395f46b8c1Libin.Tang@motorola.com            mMergeHost.mUpdateRequest = UPDATE_NONE;
2837c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            mMergeHost.mCallSessionMergePending = false;
28389bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        }
28399bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (mMergePeer != null) {
28409bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            mMergePeer.mMergeHost = null;
2841165aed55d289ae2a5cdf34de4164c2395f46b8c1Libin.Tang@motorola.com            mMergePeer.mUpdateRequest = UPDATE_NONE;
2842c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            mMergePeer.mCallSessionMergePending = false;
28439bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        }
2844c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        mMergeHost = null;
2845c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        mMergePeer = null;
2846c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        mUpdateRequest = UPDATE_NONE;
2847c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        mCallSessionMergePending = false;
28489bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    }
28499bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
28509bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    /**
28519bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * Sets the merge peer for the current call.  The merge peer is the background call that will be
28529bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * merged into this call.  On the merge peer, sets the merge host to be this call.
28539bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     *
28549bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * @param mergePeer The peer call to be merged into this one.
28559bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     */
28569bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    private void setMergePeer(ImsCall mergePeer) {
28579bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        mMergePeer = mergePeer;
28589bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        mMergeHost = null;
28599bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
28609bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        mergePeer.mMergeHost = ImsCall.this;
28619bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        mergePeer.mMergePeer = null;
28629bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    }
28639bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
28649bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    /**
28659bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * Sets the merge hody for the current call.  The merge host is the foreground call this call
28669bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * will be merged into.  On the merge host, sets the merge peer to be this call.
28679bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     *
28689bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * @param mergeHost The merge host this call will be merged into.
28699bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     */
28709bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    public void setMergeHost(ImsCall mergeHost) {
28719bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        mMergeHost = mergeHost;
28729bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        mMergePeer = null;
28739bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
28749bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        mergeHost.mMergeHost = null;
28759bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        mergeHost.mMergePeer = ImsCall.this;
28769bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    }
28779bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
28789bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    /**
28799bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * Determines if the current call is in the process of merging with another call or conference.
28809bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     *
28819bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * @return {@code true} if in the process of merging.
28829bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     */
28839bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    private boolean isMerging() {
28849bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        return mMergePeer != null || mMergeHost != null;
28859bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    }
28869bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
28879bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    /**
28889bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * Determines if the current call is the host of the merge.
28899bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     *
28909bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * @return {@code true} if the call is the merge host.
28919bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     */
28929bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    private boolean isMergeHost() {
28939bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        return mMergePeer != null && mMergeHost == null;
28949bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    }
28959bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
28969bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    /**
28979bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * Determines if the current call is the peer of the merge.
28989bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     *
28999bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * @return {@code true} if the call is the merge peer.
29009bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     */
29019bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    private boolean isMergePeer() {
29029bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        return mMergePeer == null && mMergeHost != null;
29039bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    }
29049bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
29059bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    /**
2906047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * Determines if the call session is pending merge into a conference or not.
2907047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     *
2908047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * @return {@code true} if a merge into a conference is pending, {@code false} otherwise.
2909047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     */
2910047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    private boolean isCallSessionMergePending() {
2911047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        return mCallSessionMergePending;
2912047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    }
2913047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
2914047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    /**
2915047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * Sets flag indicating whether the call session is pending merge into a conference or not.
2916047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     *
2917047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * @param callSessionMergePending {@code true} if a merge into the conference is pending,
2918047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     *      {@code false} otherwise.
2919047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     */
2920047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    private void setCallSessionMergePending(boolean callSessionMergePending) {
2921047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        mCallSessionMergePending = callSessionMergePending;
2922047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    }
2923047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
2924047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    /**
2925047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * Determines if there is a conference merge in process.  If there is a merge in process,
2926047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * determines if both the merge host and peer sessions have completed the merge process.  This
2927047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * means that we have received terminate or hold signals for the sessions, indicating that they
2928047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * are no longer in the process of being merged into the conference.
2929047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * <p>
2930c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * The sessions are considered to have merged if: both calls still have merge peer/host
2931c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * relationships configured,  both sessions are not waiting to be merged into the conference,
2932c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * and the transient conference session is alive in the case of an initial conference.
2933047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     *
2934047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * @return {@code true} where the host and peer sessions have finished merging into the
2935047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     *      conference, {@code false} if the merge has not yet completed, and {@code false} if there
2936047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     *      is no conference merge in progress.
2937047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     */
2938c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    private boolean shouldProcessConferenceResult() {
2939c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        boolean areMergeTriggersDone = false;
2940c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
2941c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        synchronized (ImsCall.this) {
2942c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // if there is a merge going on, then the merge host/peer relationships should have been
2943c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // set up.  This works for both the initial conference or merging a call into an
2944c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // existing conference.
2945c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            if (!isMergeHost() && !isMergePeer()) {
2946c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                if (VDBG) {
2947c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    log("shouldProcessConferenceResult :: no merge in progress");
2948c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                }
2949c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                return false;
2950c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            }
2951047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
2952c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // There is a merge in progress, so check the sessions to ensure:
2953c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // 1. Both calls have completed being merged (or failing to merge) into the conference.
2954c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // 2. The transient conference session is alive.
2955c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            if (isMergeHost()) {
2956c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                if (VDBG) {
2957c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    log("shouldProcessConferenceResult :: We are a merge host=" + this);
2958c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    log("shouldProcessConferenceResult :: Here is the merge peer=" + mMergePeer);
2959c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                }
2960c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                areMergeTriggersDone = !isCallSessionMergePending() &&
2961c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                        !mMergePeer.isCallSessionMergePending();
2962c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                if (!isMultiparty()) {
2963c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // Only check the transient session when there is no existing conference
2964c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    areMergeTriggersDone &= isSessionAlive(mTransientConferenceSession);
2965c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                }
2966c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            } else if (isMergePeer()) {
2967c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                if (VDBG) {
2968c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    log("shouldProcessConferenceResult :: We are a merge peer=" + this);
2969c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    log("shouldProcessConferenceResult :: Here is the merge host=" + mMergeHost);
2970c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                }
2971c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                areMergeTriggersDone = !isCallSessionMergePending() &&
2972c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                        !mMergeHost.isCallSessionMergePending();
2973c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                if (!mMergeHost.isMultiparty()) {
2974c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // Only check the transient session when there is no existing conference
2975c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    areMergeTriggersDone &= isSessionAlive(mMergeHost.mTransientConferenceSession);
2976c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                } else {
2977c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // This else block is a special case for Verizon to handle these steps
2978c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // 1. Establish a conference call.
2979c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // 2. Add a new call (conference in in BG)
2980c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // 3. Swap (conference active on FG)
2981c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // 4. Merge
2982c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // What happens here is that the BG call gets a terminated callback
2983c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // because it was added to the conference. I've seen where
2984c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // the FG gets no callback at all because its already active.
2985c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // So if we continue to wait for it to set its isCallSessionMerging
2986c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // flag to false...we'll be waiting forever.
2987c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    areMergeTriggersDone = !isCallSessionMergePending();
2988c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                }
2989c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            } else {
2990c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // Realistically this shouldn't happen, but best to be safe.
2991c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                loge("shouldProcessConferenceResult : merge in progress but call is neither" +
2992c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                        "host nor peer.");
2993c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            }
2994c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            if (VDBG) {
2995c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                log("shouldProcessConferenceResult :: returning:" +
2996c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                        (areMergeTriggersDone ? "true" : "false"));
2997c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            }
2998047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        }
2999c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        return areMergeTriggersDone;
3000047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    }
3001047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
3002047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    /**
3003168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     * Provides a string representation of the {@link ImsCall}.  Primarily intended for use in log
3004168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     * statements.
3005168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     *
3006168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     * @return String representation of call.
3007168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     */
3008168c634eef29f21c73129164207d04b8cce23738Tyler Gunn    @Override
3009168c634eef29f21c73129164207d04b8cce23738Tyler Gunn    public String toString() {
3010168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        StringBuilder sb = new StringBuilder();
3011168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        sb.append("[ImsCall objId:");
3012168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        sb.append(System.identityHashCode(this));
30139bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        sb.append(" onHold:");
30149bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        sb.append(isOnHold() ? "Y" : "N");
30159bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        sb.append(" mute:");
30169bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        sb.append(isMuted() ? "Y" : "N");
30179bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        sb.append(" updateRequest:");
30189bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        sb.append(updateRequestToString(mUpdateRequest));
301987466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn        sb.append(" merging:");
302087466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn        sb.append(isMerging() ? "Y" : "N");
302187466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn        if (isMerging()) {
302287466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn            if (isMergePeer()) {
302387466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                sb.append("P");
302487466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn            } else {
302587466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                sb.append("H");
302687466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn            }
302787466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn        }
3028c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        sb.append(" merge action pending:");
3029c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        sb.append(isCallSessionMergePending() ? "Y" : "N");
303087466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn        sb.append(" merged:");
303187466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn        sb.append(isMerged() ? "Y" : "N");
3032168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        sb.append(" multiParty:");
30339bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        sb.append(isMultiparty() ? "Y" : "N");
3034c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        sb.append(" buried term:");
3035c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        sb.append(mSessionEndDuringMerge ? "Y" : "N");
3036168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        sb.append(" session:");
3037168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        sb.append(mSession);
3038168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        sb.append(" transientSession:");
3039168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        sb.append(mTransientConferenceSession);
3040168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        sb.append("]");
3041168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        return sb.toString();
3042168c634eef29f21c73129164207d04b8cce23738Tyler Gunn    }
3043ef36ef67e009449300b0150c60c9f637e205d79eWink Saville}
3044