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
58684de85a0e1313be480fdebb107a9adaaf432b36Anthony 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        }
377ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
378ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
379ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
380ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
381ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // List of update operation for IMS call control
382ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_NONE = 0;
383ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_HOLD = 1;
384ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_HOLD_MERGE = 2;
385ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_RESUME = 3;
386ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_MERGE = 4;
387ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_EXTEND_TO_CONFERENCE = 5;
388ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_UNSPECIFIED = 6;
389ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
390ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // For synchronization of private variables
391ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private Object mLockObj = new Object();
392ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private Context mContext;
393ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
394ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // true if the call is established & in the conversation state
395ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private boolean mInCall = false;
396ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // true if the call is on hold
397ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // If it is triggered by the local, mute the call. Otherwise, play local hold tone
398ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // or network generated media.
399ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private boolean mHold = false;
400ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // true if the call is on mute
401ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private boolean mMute = false;
402ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // It contains the exclusive call update request. Refer to UPDATE_*.
403ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private int mUpdateRequest = UPDATE_NONE;
404ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
405ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsCall.Listener mListener = null;
4069bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
4079bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    // When merging two calls together, the "peer" call that will merge into this call.
4089bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    private ImsCall mMergePeer = null;
4099bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    // When merging two calls together, the "host" call we are merging into.
4109bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    private ImsCall mMergeHost = null;
411ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
412ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // Wrapper call session to interworking the IMS service (server).
413ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsCallSession mSession = null;
414ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // Call profile of the current session.
415ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // It can be changed at anytime when the call is updated.
416ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsCallProfile mCallProfile = null;
417ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // Call profile to be updated after the application's action (accept/reject)
418ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // to the call update. After the application's action (accept/reject) is done,
419ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // it will be set to null.
420ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsCallProfile mProposedCallProfile = null;
421ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsReasonInfo mLastReasonInfo = null;
422ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
423ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // Media session to control media (audio/video) operations for an IMS call
424ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsStreamMediaSession mMediaSession = null;
425ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
426b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // The temporary ImsCallSession that could represent the merged call once
427b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // we receive notification that the merge was successful.
42871382693cbc81b1d131085f52d97879976706f55Anthony Lee    private ImsCallSession mTransientConferenceSession = null;
429b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // While a merge is progressing, we bury any session termination requests
430b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // made on the original ImsCallSession until we have closure on the merge request
431b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // If the request ultimately fails, we need to act on the termination request
432b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // that we buried temporarily. We do this because we feel that timing issues could
433b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // cause the termination request to occur just because the merge is succeeding.
434b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    private boolean mSessionEndDuringMerge = false;
435b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // Just like mSessionEndDuringMerge, we need to keep track of the reason why the
436b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // termination request was made on the original session in case we need to act
437b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // on it in the case of a merge failure.
438b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    private ImsReasonInfo mSessionEndDuringMergeReasonInfo = null;
439684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee    // This flag is used to indicate if this ImsCall was merged into a conference
440684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee    // or not.  It is used primarily to determine if a disconnect sound should
441684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee    // be heard when the call is terminated.
4428ae59492156d9cef275f559c5ee09a44315989beAndrew Lee    private boolean mIsMerged = false;
443684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee    // If true, this flag means that this ImsCall is in the process of merging
444684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee    // into a conference but it does not yet have closure on if it was
445684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee    // actually added to the conference or not. false implies that it either
446684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee    // is not part of a merging conference or already knows if it was
447684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee    // successfully added.
448047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    private boolean mCallSessionMergePending = false;
449047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
450ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
451ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Create an IMS call object.
452ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
453ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param context the context for accessing system services
454ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param profile the call profile to make/take a call
455ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
456ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsCall(Context context, ImsCallProfile profile) {
457ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mContext = context;
458ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mCallProfile = profile;
459ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
460ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
461ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
462ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Closes this object. This object is not usable after being closed.
463ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
464ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    @Override
465ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void close() {
466ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
467ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession != null) {
468ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mSession.close();
469ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mSession = null;
470ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
471ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
472ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mCallProfile = null;
473ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mProposedCallProfile = null;
474ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mLastReasonInfo = null;
475ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mMediaSession = null;
476ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
477ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
478ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
479ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
480ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Checks if the call has a same remote user identity or not.
481ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
482ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param userId the remote user identity
483ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return true if the remote user identity is equal; otherwise, false
484ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
485ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    @Override
486ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public boolean checkIfRemoteUserIsSame(String userId) {
487ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (userId == null) {
488ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return false;
489ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
490ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
491ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        return userId.equals(mCallProfile.getCallExtra(ImsCallProfile.EXTRA_REMOTE_URI, ""));
492ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
493ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
494ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
495ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Checks if the call is equal or not.
496ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
497ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param call the call to be compared
498ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return true if the call is equal; otherwise, false
499ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
500ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    @Override
501ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public boolean equalsTo(ICall call) {
502ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (call == null) {
503ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return false;
504ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
505ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
506ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (call instanceof ImsCall) {
50716b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen            return this.equals(call);
508ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
509ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
510ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        return false;
511ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
512ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
513684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee    public static boolean isSessionAlive(ImsCallSession session) {
514684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee        return session != null && session.isAlive();
515684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee    }
516684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee
517ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
518ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the negotiated (local & remote) call profile.
519ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
520ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return a {@link ImsCallProfile} object that has the negotiated call profile
521ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
522ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsCallProfile getCallProfile() {
523ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
524ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mCallProfile;
525ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
526ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
527ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
528ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
529ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the local call profile (local capabilities).
530ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
531ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return a {@link ImsCallProfile} object that has the local call profile
532ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
533ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsCallProfile getLocalCallProfile() throws ImsException {
534ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
535ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
536ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
537ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
538ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
539ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
540ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            try {
541ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return mSession.getLocalCallProfile();
542ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } catch (Throwable t) {
543ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("getLocalCallProfile :: ", t);
544ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("getLocalCallProfile()", t, 0);
545ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
546ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
547ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
548ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
549ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
550e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh     * Gets the remote call profile (remote capabilities).
551e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh     *
552e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh     * @return a {@link ImsCallProfile} object that has the remote call profile
553e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh     */
554e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh    public ImsCallProfile getRemoteCallProfile() throws ImsException {
555e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh        synchronized(mLockObj) {
556e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh            if (mSession == null) {
557e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh                throw new ImsException("No call session",
558e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
559e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh            }
560e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh
561e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh            try {
562e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh                return mSession.getRemoteCallProfile();
563e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh            } catch (Throwable t) {
564e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh                loge("getRemoteCallProfile :: ", t);
565e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh                throw new ImsException("getRemoteCallProfile()", t, 0);
566e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh            }
567e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh        }
568e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh    }
569e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh
570e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh    /**
571ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the call profile proposed by the local/remote user.
572ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
573ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return a {@link ImsCallProfile} object that has the proposed call profile
574ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
575ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsCallProfile getProposedCallProfile() {
576ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
577ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (!isInCall()) {
578ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return null;
579ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
580ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
581ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mProposedCallProfile;
582ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
583ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
584ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
585ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
586ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the state of the {@link ImsCallSession} that carries this call.
587ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * The value returned must be one of the states in {@link ImsCallSession#State}.
588ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
589ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return the session state
590ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
591ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public int getState() {
592ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
593ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
594ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return ImsCallSession.State.IDLE;
595ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
596ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
597ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mSession.getState();
598ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
599ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
600ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
601ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
602ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the {@link ImsCallSession} that carries this call.
603ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
604ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return the session object that carries this call
605ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @hide
606ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
607ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsCallSession getCallSession() {
608ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
609ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mSession;
610ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
611ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
612ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
613ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
614ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the {@link ImsStreamMediaSession} that handles the media operation of this call.
615ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Almost interface APIs are for the VT (Video Telephony).
616ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
617ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return the media session object that handles the media operation of this call
618ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @hide
619ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
620ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsStreamMediaSession getMediaSession() {
621ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
622ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mMediaSession;
623ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
624ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
625ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
626ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
627ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the specified property of this call.
628ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
629ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param name key to get the extra call information defined in {@link ImsCallProfile}
630ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return the extra call information as string
631ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
632ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public String getCallExtra(String name) throws ImsException {
633ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        // Lookup the cache
634ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
635ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
636ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // If not found, try to get the property from the remote
637ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
638ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
639ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
640ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
641ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
642ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            try {
643ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return mSession.getProperty(name);
644ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } catch (Throwable t) {
645ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("getCallExtra :: ", t);
646ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("getCallExtra()", t, 0);
647ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
648ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
649ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
650ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
651ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
652ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the last reason information when the call is not established, cancelled or terminated.
653ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
654ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return the last reason information
655ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
656ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsReasonInfo getLastReasonInfo() {
657ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
658ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mLastReasonInfo;
659ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
660ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
661ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
662ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
663ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Checks if the call has a pending update operation.
664ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
665ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return true if the call has a pending update operation
666ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
667ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public boolean hasPendingUpdate() {
668ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
669ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return (mUpdateRequest != UPDATE_NONE);
670ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
671ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
672ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
673ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
674ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Checks if the call is established.
675ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
676ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return true if the call is established
677ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
678ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public boolean isInCall() {
679ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
680ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mInCall;
681ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
682ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
683ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
684ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
685ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Checks if the call is muted.
686ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
687ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return true if the call is muted
688ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
689ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public boolean isMuted() {
690ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
691ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mMute;
692ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
693ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
694ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
695ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
696ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Checks if the call is on hold.
697ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
698ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return true if the call is on hold
699ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
700ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public boolean isOnHold() {
701ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
702ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mHold;
703ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
704ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
705ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
706ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
707725ad373383798c1516348475b1f6304484e031eTyler Gunn     * Determines if the call is a multiparty call.
708725ad373383798c1516348475b1f6304484e031eTyler Gunn     *
709725ad373383798c1516348475b1f6304484e031eTyler Gunn     * @return {@code True} if the call is a multiparty call.
710725ad373383798c1516348475b1f6304484e031eTyler Gunn     */
711725ad373383798c1516348475b1f6304484e031eTyler Gunn    public boolean isMultiparty() {
71216b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen        synchronized(mLockObj) {
71316b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen            if (mSession == null) {
71416b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen                return false;
71516b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen            }
71616b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen
71771382693cbc81b1d131085f52d97879976706f55Anthony Lee            return mSession.isMultiparty();
71816b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen        }
719725ad373383798c1516348475b1f6304484e031eTyler Gunn    }
720725ad373383798c1516348475b1f6304484e031eTyler Gunn
721725ad373383798c1516348475b1f6304484e031eTyler Gunn    /**
7229bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * Marks whether an IMS call is merged. This should be set {@code true} when the call merges
7239bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * into a conference.
7248ae59492156d9cef275f559c5ee09a44315989beAndrew Lee     *
7258ae59492156d9cef275f559c5ee09a44315989beAndrew Lee     * @param isMerged Whether the call is merged.
7268ae59492156d9cef275f559c5ee09a44315989beAndrew Lee     */
7278ae59492156d9cef275f559c5ee09a44315989beAndrew Lee    public void setIsMerged(boolean isMerged) {
7288ae59492156d9cef275f559c5ee09a44315989beAndrew Lee        mIsMerged = isMerged;
7298ae59492156d9cef275f559c5ee09a44315989beAndrew Lee    }
7308ae59492156d9cef275f559c5ee09a44315989beAndrew Lee
7318ae59492156d9cef275f559c5ee09a44315989beAndrew Lee    /**
7329bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * @return {@code true} if the call recently merged into a conference call.
7338ae59492156d9cef275f559c5ee09a44315989beAndrew Lee     */
7348ae59492156d9cef275f559c5ee09a44315989beAndrew Lee    public boolean isMerged() {
7358ae59492156d9cef275f559c5ee09a44315989beAndrew Lee        return mIsMerged;
7368ae59492156d9cef275f559c5ee09a44315989beAndrew Lee    }
7378ae59492156d9cef275f559c5ee09a44315989beAndrew Lee
7388ae59492156d9cef275f559c5ee09a44315989beAndrew Lee    /**
739ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Sets the listener to listen to the IMS call events.
740ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * The method calls {@link #setListener setListener(listener, false)}.
741ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
742ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param listener to listen to the IMS call events of this object; null to remove listener
743ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see #setListener(Listener, boolean)
744ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
745ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void setListener(ImsCall.Listener listener) {
746ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        setListener(listener, false);
747ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
748ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
749ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
750ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Sets the listener to listen to the IMS call events.
751ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * A {@link ImsCall} can only hold one listener at a time. Subsequent calls
752ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * to this method override the previous listener.
753ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
754ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param listener to listen to the IMS call events of this object; null to remove listener
755ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param callbackImmediately set to true if the caller wants to be called
756ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *        back immediately on the current state
757ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
758ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void setListener(ImsCall.Listener listener, boolean callbackImmediately) {
759ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        boolean inCall;
760ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        boolean onHold;
761ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        int state;
762ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        ImsReasonInfo lastReasonInfo;
763ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
764ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
765ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mListener = listener;
766ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
767ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if ((listener == null) || !callbackImmediately) {
768ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return;
769ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
770ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
771ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            inCall = mInCall;
772ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onHold = mHold;
773ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            state = getState();
774ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            lastReasonInfo = mLastReasonInfo;
775ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
776ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
777ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        try {
778ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (lastReasonInfo != null) {
779ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener.onCallError(this, lastReasonInfo);
780ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } else if (inCall) {
781ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (onHold) {
782ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallHeld(this);
783ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } else {
784ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallStarted(this);
785ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
786ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } else {
787ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                switch (state) {
788ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    case ImsCallSession.State.ESTABLISHING:
789ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        listener.onCallProgressing(this);
790ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        break;
791ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    case ImsCallSession.State.TERMINATED:
792ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        listener.onCallTerminated(this, lastReasonInfo);
793ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        break;
794ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    default:
795ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        // Ignore it. There is no action in the other state.
796ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        break;
797ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
798ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
799ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        } catch (Throwable t) {
800ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            loge("setListener()", t);
801ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
802ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
803ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
804ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
805ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Mutes or unmutes the mic for the active call.
806ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
807ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param muted true if the call is muted, false otherwise
808ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
809ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void setMute(boolean muted) throws ImsException {
810ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
811ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mMute != muted) {
812ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mMute = muted;
813ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
814ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
815ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    mSession.setMute(muted);
816ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
817ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("setMute :: ", t);
818ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    throwImsException(t, 0);
819ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
820ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
821ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
822ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
823ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
824ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     /**
825ef36ef67e009449300b0150c60c9f637e205d79eWink Saville      * Attaches an incoming call to this call object.
826ef36ef67e009449300b0150c60c9f637e205d79eWink Saville      *
827ef36ef67e009449300b0150c60c9f637e205d79eWink Saville      * @param session the session that receives the incoming call
828ef36ef67e009449300b0150c60c9f637e205d79eWink Saville      * @throws ImsException if the IMS service fails to attach this object to the session
829ef36ef67e009449300b0150c60c9f637e205d79eWink Saville      */
830ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     public void attachSession(ImsCallSession session) throws ImsException {
831ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         if (DBG) {
832ef36ef67e009449300b0150c60c9f637e205d79eWink Saville             log("attachSession :: session=" + session);
833ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         }
834ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
835ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         synchronized(mLockObj) {
836ef36ef67e009449300b0150c60c9f637e205d79eWink Saville             mSession = session;
837ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
838ef36ef67e009449300b0150c60c9f637e205d79eWink Saville             try {
839ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                 mSession.setListener(createCallSessionListener());
840ef36ef67e009449300b0150c60c9f637e205d79eWink Saville             } catch (Throwable t) {
841ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                 loge("attachSession :: ", t);
842ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                 throwImsException(t, 0);
843ef36ef67e009449300b0150c60c9f637e205d79eWink Saville             }
844ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         }
845ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     }
846ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
847ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
848ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Initiates an IMS call with the call profile which is provided
849ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * when creating a {@link ImsCall}.
850ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
851ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param session the {@link ImsCallSession} for carrying out the call
852ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param callee callee information to initiate an IMS call
853ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to initiate the call
854ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
855ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void start(ImsCallSession session, String callee)
856ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            throws ImsException {
857ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (DBG) {
858ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            log("start(1) :: session=" + session + ", callee=" + callee);
859ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
860ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
861ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
862ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession = session;
863ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
864ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            try {
865ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                session.setListener(createCallSessionListener());
866ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                session.start(callee, mCallProfile);
867ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } catch (Throwable t) {
868ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("start(1) :: ", t);
869ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("start(1)", t, 0);
870ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
871ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
872ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
873ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
874ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
875ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Initiates an IMS conferenca call with the call profile which is provided
876ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * when creating a {@link ImsCall}.
877ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
878ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param session the {@link ImsCallSession} for carrying out the call
879ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param participants participant list to initiate an IMS conference call
880ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to initiate the call
881ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
882ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void start(ImsCallSession session, String[] participants)
883ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            throws ImsException {
884ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (DBG) {
885ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            log("start(n) :: session=" + session + ", callee=" + participants);
886ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
887ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
888ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
889ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession = session;
890ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
891ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            try {
892ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                session.setListener(createCallSessionListener());
893ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                session.start(participants, mCallProfile);
894ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } catch (Throwable t) {
895ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("start(n) :: ", t);
896ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("start(n)", t, 0);
897ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
898ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
899ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
900ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
901ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
902ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Accepts a call.
903ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
904ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallStarted
905d1edfd8cf9ffeb191a84e08522bb570cd8cd4381Tyler Gunn     *
906d1edfd8cf9ffeb191a84e08522bb570cd8cd4381Tyler Gunn     * @param callType The call type the user agreed to for accepting the call.
907ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to accept the call
908ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
909d1edfd8cf9ffeb191a84e08522bb570cd8cd4381Tyler Gunn    public void accept(int callType) throws ImsException {
9109bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (VDBG) {
911684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            log("accept ::");
912ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
913ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
914d1edfd8cf9ffeb191a84e08522bb570cd8cd4381Tyler Gunn        accept(callType, new ImsStreamMediaProfile());
915ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
916ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
917ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
918ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Accepts a call.
919ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
920ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param callType call type to be answered in {@link ImsCallProfile}
921ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param profile a media profile to be answered (audio/audio & video, direction, ...)
922ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallStarted
923ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to accept the call
924ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
925ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void accept(int callType, ImsStreamMediaProfile profile) throws ImsException {
9269bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (VDBG) {
927684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            log("accept :: callType=" + callType + ", profile=" + profile);
928ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
929ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
930ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
931ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
932ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call to answer",
933ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
934ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
935ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
936ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            try {
937ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mSession.accept(callType, profile);
938ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } catch (Throwable t) {
939ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("accept :: ", t);
940ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("accept()", t, 0);
941ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
942ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
943ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mInCall && (mProposedCallProfile != null)) {
944ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (DBG) {
945ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    log("accept :: call profile will be updated");
946ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
947ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
948ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallProfile = mProposedCallProfile;
949ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mProposedCallProfile = null;
950ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
951ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
952ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // Other call update received
953ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mInCall && (mUpdateRequest == UPDATE_UNSPECIFIED)) {
954ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
955ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
956ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
957ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
958ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
959ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
960ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Rejects a call.
961ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
962ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param reason reason code to reject an incoming call
963ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallStartFailed
964ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to accept the call
965ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
966ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void reject(int reason) throws ImsException {
9679bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (VDBG) {
968684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            log("reject :: reason=" + reason);
969ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
970ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
971ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
972ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession != null) {
973ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mSession.reject(reason);
974ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
975ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
976ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mInCall && (mProposedCallProfile != null)) {
977ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (DBG) {
978ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    log("reject :: call profile is not updated; destroy it...");
979ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
980ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
981ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mProposedCallProfile = null;
982ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
983ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
984ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // Other call update received
985ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mInCall && (mUpdateRequest == UPDATE_UNSPECIFIED)) {
986ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
987ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
988ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
989ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
990ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
991ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
992ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Terminates an IMS call.
993ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
994ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param reason reason code to terminate a call
995ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to terminate the call
996ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
997ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void terminate(int reason) throws ImsException {
9989bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (VDBG) {
999684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            log("terminate :: ImsCall=" + this +" reason=" + reason);
1000ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1001ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1002ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1003ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mHold = false;
1004ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mInCall = false;
1005ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1006ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession != null) {
1007684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // TODO: Fix the fact that user invoked call terminations during
1008684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // the process of establishing a conference call needs to be handled
1009684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // as a special case.
1010684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // Currently, any terminations (both invoked by the user or
1011684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // by the network results in a callSessionTerminated() callback
1012684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // from the network.  When establishing a conference call we bury
1013684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // these callbacks until we get closure on all participants of the
1014684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // conference. In some situations, we will throw away the callback
1015684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // (when the underlying session of the host of the new conference
1016684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // is terminated) or will will unbury it when the conference has been
1017684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // established, like when the peer of the new conference goes away
1018684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // after the conference has been created.  The UI relies on the callback
1019684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // to reflect the fact that the call is gone.
1020684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // So if a user decides to terminated a call while it is merging, it
1021684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // could take a long time to reflect in the UI due to the conference
1022684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // processing but we should probably cancel that and just terminate
1023684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // the call immediately and clean up.  This is not a huge issue right
1024684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // now because we have not seen instances where establishing a
1025684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // conference takes a long time (more than a second or two).
1026ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mSession.terminate(reason);
1027ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1028ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1029ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1030ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1031d43b5302d8edf4df90a28055f043786f542df219Uma Maheswari Ramalingam
1032ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1033ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Puts a call on hold. When succeeds, {@link Listener#onCallHeld} is called.
1034ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1035ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallHeld, Listener#onCallHoldFailed
1036ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to hold the call
1037ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1038ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void hold() throws ImsException {
10399bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (VDBG) {
1040684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            log("hold :: ImsCall=" + this);
1041111eecc9845826e985c48133b754e453fb3aca84Etan Cohen        }
1042111eecc9845826e985c48133b754e453fb3aca84Etan Cohen
1043ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (isOnHold()) {
1044ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
1045ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("hold :: call is already on hold");
1046ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1047ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return;
1048ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1049ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1050ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1051ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mUpdateRequest != UPDATE_NONE) {
10529bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                loge("hold :: update is in progress; request=" +
10539bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                        updateRequestToString(mUpdateRequest));
1054ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("Call update is in progress",
1055ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
1056ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1057ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1058ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1059ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("hold :: ");
1060ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1061ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1062ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1063ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1064ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession.hold(createHoldMediaProfile());
1065ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // FIXME: update the state on the callback?
1066ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mHold = true;
1067ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mUpdateRequest = UPDATE_HOLD;
1068ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1069ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1070ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1071ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1072ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Continues a call that's on hold. When succeeds, {@link Listener#onCallResumed} is called.
1073ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1074ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallResumed, Listener#onCallResumeFailed
1075ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to resume the call
1076ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1077ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void resume() throws ImsException {
10789bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (VDBG) {
1079684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            log("resume :: ImsCall=" + this);
1080111eecc9845826e985c48133b754e453fb3aca84Etan Cohen        }
1081111eecc9845826e985c48133b754e453fb3aca84Etan Cohen
1082ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (!isOnHold()) {
1083ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
1084ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("resume :: call is in conversation");
1085ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1086ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return;
1087ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1088ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1089ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1090ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mUpdateRequest != UPDATE_NONE) {
10919bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                loge("resume :: update is in progress; request=" +
10929bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                        updateRequestToString(mUpdateRequest));
1093ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("Call update is in progress",
1094ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
1095ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1096ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1097ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1098ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("resume :: ");
1099ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1100ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1101ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1102ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1103684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            // mHold is set to false in confirmation callback that the
1104684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            // ImsCall was resumed.
1105ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mUpdateRequest = UPDATE_RESUME;
1106684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            mSession.resume(createResumeMediaProfile());
1107ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1108ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1109ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1110ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1111ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Merges the active & hold call.
1112ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1113ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallMerged, Listener#onCallMergeFailed
1114ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to merge the call
1115ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1116047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    private void merge() throws ImsException {
11179bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (VDBG) {
1118684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            log("merge :: ImsCall=" + this);
1119ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1120ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1121ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1122ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mUpdateRequest != UPDATE_NONE) {
11239bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                loge("merge :: update is in progress; request=" +
11249bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                        updateRequestToString(mUpdateRequest));
1125ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("Call update is in progress",
1126ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
1127ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1128ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1129ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1130684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                loge("merge :: no call session");
1131ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1132ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1133ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1134ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1135ca45f58a57eb782153c034ae067f59c0018799caUma Maheswari Ramalingam            // if skipHoldBeforeMerge = true, IMS service implementation will
1136ca45f58a57eb782153c034ae067f59c0018799caUma Maheswari Ramalingam            // merge without explicitly holding the call.
1137ca45f58a57eb782153c034ae067f59c0018799caUma Maheswari Ramalingam            if (mHold || (mContext.getResources().getBoolean(
1138ca45f58a57eb782153c034ae067f59c0018799caUma Maheswari Ramalingam                    com.android.internal.R.bool.skipHoldBeforeMerge))) {
1139b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee
11409bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                if (mMergePeer != null && !mMergePeer.isMultiparty() && !isMultiparty()) {
11419bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                    // We only set UPDATE_MERGE when we are adding the first
11429bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                    // calls to the Conference.  If there is already a conference
1143047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                    // no special handling is needed. The existing conference
11449bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                    // session will just go active and any other sessions will be terminated
11459bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                    // if needed.  There will be no merge failed callback.
1146047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                    // Mark both the host and peer UPDATE_MERGE to ensure both are aware that a
1147047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                    // merge is pending.
11489bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                    mUpdateRequest = UPDATE_MERGE;
1149047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                    mMergePeer.mUpdateRequest = UPDATE_MERGE;
1150b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                }
11519bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
11529bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                mSession.merge();
1153ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } else {
115471382693cbc81b1d131085f52d97879976706f55Anthony Lee                // This code basically says, we need to explicitly hold before requesting a merge
115571382693cbc81b1d131085f52d97879976706f55Anthony Lee                // when we get the callback that the hold was successful (or failed), we should
115671382693cbc81b1d131085f52d97879976706f55Anthony Lee                // automatically request a merge.
1157ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mSession.hold(createHoldMediaProfile());
1158ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mHold = true;
1159ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_HOLD_MERGE;
1160ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1161ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1162ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1163ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1164ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1165ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Merges the active & hold call.
1166ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1167ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param bgCall the background (holding) call
1168ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallMerged, Listener#onCallMergeFailed
1169ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to merge the call
1170ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1171ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void merge(ImsCall bgCall) throws ImsException {
11729bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (VDBG) {
1173684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            log("merge(1) :: bgImsCall=" + bgCall);
1174ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1175ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1176ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (bgCall == null) {
1177ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            throw new ImsException("No background call",
1178ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
1179ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1180ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1181ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1182047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            // Mark both sessions as pending merge.
1183047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            this.setCallSessionMergePending(true);
1184047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            bgCall.setCallSessionMergePending(true);
1185047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
118687466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn            if ((!isMultiparty() && !bgCall.isMultiparty()) || isMultiparty()) {
118787466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                // If neither call is multiparty, the current call is the merge host and the bg call
118887466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                // is the merge peer (ie we're starting a new conference).
118987466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                // OR
119087466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                // If this call is multiparty, it is the merge host and the other call is the merge
119187466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                // peer.
119287466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                setMergePeer(bgCall);
119387466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn            } else {
119487466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                // If the bg call is multiparty, it is the merge host.
119587466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                setMergeHost(bgCall);
119687466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn            }
1197ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1198ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        merge();
1199ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1200ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1201ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1202ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Updates the current call's properties (ex. call mode change: video upgrade / downgrade).
1203ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1204ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void update(int callType, ImsStreamMediaProfile mediaProfile) throws ImsException {
12059bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (VDBG) {
1206684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            log("update ::");
1207ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1208ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1209ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (isOnHold()) {
1210ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
1211ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("update :: call is on hold");
1212ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1213ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            throw new ImsException("Not in a call to update call",
1214ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
1215ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1216ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1217ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1218ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mUpdateRequest != UPDATE_NONE) {
1219ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (DBG) {
12209bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                    log("update :: update is in progress; request=" +
12219bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                            updateRequestToString(mUpdateRequest));
1222ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1223ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("Call update is in progress",
1224ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
1225ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1226ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1227ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1228ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("update :: ");
1229ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1230ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1231ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1232ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1233ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession.update(callType, mediaProfile);
1234ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mUpdateRequest = UPDATE_UNSPECIFIED;
1235ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1236ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1237ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1238ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1239ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Extends this call (1-to-1 call) to the conference call
1240ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * inviting the specified participants to.
1241ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1242ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1243ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void extendToConference(String[] participants) throws ImsException {
12449bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (VDBG) {
1245684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            log("extendToConference ::");
1246ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1247ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1248ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (isOnHold()) {
1249ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
1250ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("extendToConference :: call is on hold");
1251ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1252ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            throw new ImsException("Not in a call to extend a call to conference",
1253ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
1254ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1255ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1256ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1257ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mUpdateRequest != UPDATE_NONE) {
1258ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (DBG) {
12599bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                    log("extendToConference :: update is in progress; request=" +
12609bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                            updateRequestToString(mUpdateRequest));
1261ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1262ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("Call update is in progress",
1263ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
1264ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1265ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1266ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1267ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("extendToConference :: ");
1268ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1269ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1270ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1271ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1272ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession.extendToConference(participants);
1273ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mUpdateRequest = UPDATE_EXTEND_TO_CONFERENCE;
1274ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1275ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1276ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1277ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1278ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Requests the conference server to invite an additional participants to the conference.
1279ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1280ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1281ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void inviteParticipants(String[] participants) throws ImsException {
12829bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (VDBG) {
1283684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            log("inviteParticipants ::");
1284ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1285ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1286ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1287ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1288ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("inviteParticipants :: ");
1289ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1290ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1291ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1292ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1293ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession.inviteParticipants(participants);
1294ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1295ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1296ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1297ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1298ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Requests the conference server to remove the specified participants from the conference.
1299ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1300ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1301ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void removeParticipants(String[] participants) throws ImsException {
1302ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (DBG) {
13039bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            log("removeParticipants ::");
1304ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1305ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1306ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1307ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1308ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("removeParticipants :: ");
1309ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1310ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1311ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1312ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1313ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession.removeParticipants(participants);
1314ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1315ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1316ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1317ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1318ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Sends a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2833</a>,
1319ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * event 0 ~ 9 maps to decimal value 0 ~ 9, '*' to 10, '#' to 11, event 'A' ~ 'D' to 12 ~ 15,
1320ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * and event flash to 16. Currently, event flash is not supported.
1321ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
13222f92daf76a66d7d2fe6fb7b1a28fc1b5888a7b7cLibin.Tang@motorola.com     * @param c that represents the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs.
13232f92daf76a66d7d2fe6fb7b1a28fc1b5888a7b7cLibin.Tang@motorola.com     * @param result the result message to send when done.
1324ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
13252f92daf76a66d7d2fe6fb7b1a28fc1b5888a7b7cLibin.Tang@motorola.com    public void sendDtmf(char c, Message result) {
13269bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (VDBG) {
1327684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            log("sendDtmf :: code=" + c);
1328ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1329ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1330ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1331ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession != null) {
1332a4710d5d926d8112179acece620f49cb79257e98Andrew Lee                mSession.sendDtmf(c, result);
1333ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1334ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1335ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1336ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1337ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1338a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam     * Start a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2833</a>,
1339a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam     * event 0 ~ 9 maps to decimal value 0 ~ 9, '*' to 10, '#' to 11, event 'A' ~ 'D' to 12 ~ 15,
1340a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam     * and event flash to 16. Currently, event flash is not supported.
1341a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam     *
1342a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam     * @param c that represents the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs.
1343a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam     */
1344a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam    public void startDtmf(char c) {
1345a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam        if (DBG) {
1346a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam            log("startDtmf :: session=" + mSession + ", code=" + c);
1347a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam        }
1348a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam
1349a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam        synchronized(mLockObj) {
1350a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam            if (mSession != null) {
1351a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam                mSession.startDtmf(c);
1352a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam            }
1353a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam        }
1354a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam    }
1355a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam
1356a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam    /**
1357a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam     * Stop a DTMF code.
1358a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam     */
1359a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam    public void stopDtmf() {
1360a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam        if (DBG) {
1361a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam            log("stopDtmf :: session=" + mSession);
1362a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam        }
1363a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam
1364a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam        synchronized(mLockObj) {
1365a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam            if (mSession != null) {
1366a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam                mSession.stopDtmf();
1367a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam            }
1368a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam        }
1369a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam    }
1370a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam
1371a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam    /**
1372ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Sends an USSD message.
1373ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1374ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param ussdMessage USSD message to send
1375ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1376ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void sendUssd(String ussdMessage) throws ImsException {
13779bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (VDBG) {
1378684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            log("sendUssd :: ussdMessage=" + ussdMessage);
1379ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1380ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1381ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1382ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1383ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("sendUssd :: ");
1384ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1385ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1386ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1387ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1388ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession.sendUssd(ussdMessage);
1389ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1390ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1391ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1392ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void clear(ImsReasonInfo lastReasonInfo) {
1393ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mInCall = false;
1394ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mHold = false;
1395ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mUpdateRequest = UPDATE_NONE;
1396ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mLastReasonInfo = lastReasonInfo;
1397ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1398ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1399ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1400ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Creates an IMS call session listener.
1401ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1402ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsCallSession.Listener createCallSessionListener() {
1403ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        return new ImsCallSessionListenerProxy();
1404ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1405ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1406ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsCall createNewCall(ImsCallSession session, ImsCallProfile profile) {
1407ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        ImsCall call = new ImsCall(mContext, profile);
1408ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1409ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        try {
1410ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            call.attachSession(session);
1411ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        } catch (ImsException e) {
1412ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (call != null) {
1413ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                call.close();
1414ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                call = null;
1415ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1416ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1417ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1418ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        // Do additional operations...
1419ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1420ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        return call;
1421ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1422ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1423ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsStreamMediaProfile createHoldMediaProfile() {
1424ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        ImsStreamMediaProfile mediaProfile = new ImsStreamMediaProfile();
1425ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1426ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (mCallProfile == null) {
1427ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mediaProfile;
1428ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1429ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1430ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mediaProfile.mAudioQuality = mCallProfile.mMediaProfile.mAudioQuality;
1431ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mediaProfile.mVideoQuality = mCallProfile.mMediaProfile.mVideoQuality;
1432ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mediaProfile.mAudioDirection = ImsStreamMediaProfile.DIRECTION_SEND;
1433ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1434ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (mediaProfile.mVideoQuality != ImsStreamMediaProfile.VIDEO_QUALITY_NONE) {
1435ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mediaProfile.mVideoDirection = ImsStreamMediaProfile.DIRECTION_SEND;
1436ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1437ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1438ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        return mediaProfile;
1439ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1440ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1441ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsStreamMediaProfile createResumeMediaProfile() {
1442ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        ImsStreamMediaProfile mediaProfile = new ImsStreamMediaProfile();
1443ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1444ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (mCallProfile == null) {
1445ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mediaProfile;
1446ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1447ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1448ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mediaProfile.mAudioQuality = mCallProfile.mMediaProfile.mAudioQuality;
1449ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mediaProfile.mVideoQuality = mCallProfile.mMediaProfile.mVideoQuality;
1450ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mediaProfile.mAudioDirection = ImsStreamMediaProfile.DIRECTION_SEND_RECEIVE;
1451ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1452ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (mediaProfile.mVideoQuality != ImsStreamMediaProfile.VIDEO_QUALITY_NONE) {
1453ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mediaProfile.mVideoDirection = ImsStreamMediaProfile.DIRECTION_SEND_RECEIVE;
1454ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1455ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1456ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        return mediaProfile;
1457ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1458ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1459ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void enforceConversationMode() {
1460ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (mInCall) {
1461ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mHold = false;
1462ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mUpdateRequest = UPDATE_NONE;
1463ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1464ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1465ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1466ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void mergeInternal() {
14679bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (VDBG) {
1468684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            log("mergeInternal :: ImsCall=" + this);
1469ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1470ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1471ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mSession.merge();
1472ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mUpdateRequest = UPDATE_MERGE;
1473ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1474ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1475ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void notifyConferenceSessionTerminated(ImsReasonInfo reasonInfo) {
14769bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        ImsCall.Listener listener = mListener;
1477ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        clear(reasonInfo);
1478ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1479ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (listener != null) {
1480ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            try {
1481ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener.onCallTerminated(this, reasonInfo);
1482ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } catch (Throwable t) {
1483ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("notifyConferenceSessionTerminated :: ", t);
1484ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1485ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1486ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1487ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1488ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void notifyConferenceStateUpdated(ImsConferenceState state) {
14891c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn        Set<Entry<String, Bundle>> participants = state.mParticipants.entrySet();
1490ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
14911c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn        if (participants == null) {
1492ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return;
1493ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1494ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
14951c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn        Iterator<Entry<String, Bundle>> iterator = participants.iterator();
14961c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn        List<ConferenceParticipant> conferenceParticipants = new ArrayList<>(participants.size());
1497ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        while (iterator.hasNext()) {
1498ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            Entry<String, Bundle> entry = iterator.next();
1499ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1500ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            String key = entry.getKey();
1501ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            Bundle confInfo = entry.getValue();
1502ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            String status = confInfo.getString(ImsConferenceState.STATUS);
1503ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            String user = confInfo.getString(ImsConferenceState.USER);
15045965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn            String displayName = confInfo.getString(ImsConferenceState.DISPLAY_TEXT);
1505ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            String endpoint = confInfo.getString(ImsConferenceState.ENDPOINT);
1506ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1507ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
1508ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("notifyConferenceStateUpdated :: key=" + key +
1509ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ", status=" + status +
1510ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ", user=" + user +
15115965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn                        ", displayName= " + displayName +
1512ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ", endpoint=" + endpoint);
1513ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1514ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
15159bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            Uri handle = Uri.parse(user);
15169bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            Uri endpointUri = Uri.parse(endpoint);
15179bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            int connectionState = ImsConferenceState.getConnectionStateForStatus(status);
1518ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
15199bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            ConferenceParticipant conferenceParticipant = new ConferenceParticipant(handle,
15209bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                    displayName, endpointUri, connectionState);
15219bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            conferenceParticipants.add(conferenceParticipant);
1522ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
15231c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn
15241c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn        if (!conferenceParticipants.isEmpty() && mListener != null) {
15251c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn            try {
15261c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn                mListener.onConferenceParticipantsStateChanged(this, conferenceParticipants);
15271c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn            } catch (Throwable t) {
15281c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn                loge("notifyConferenceStateUpdated :: ", t);
15291c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn            }
15301c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn        }
1531ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1532ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1533b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    /**
1534b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee     * Perform all cleanup and notification around the termination of a session.
1535b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee     * Note that there are 2 distinct modes of operation.  The first is when
1536b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee     * we receive a session termination on the primary session when we are
1537b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee     * in the processing of merging.  The second is when we are not merging anything
1538b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee     * and the call is terminated.
1539b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee     *
1540b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee     * @param reasonInfo The reason for the session termination
1541b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee     */
1542b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    private void processCallTerminated(ImsReasonInfo reasonInfo) {
15439bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (VDBG) {
1544b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee            String reasonString = reasonInfo != null ? reasonInfo.toString() : "null";
1545684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            log("processCallTerminated :: ImsCall=" + this + " reason=" + reasonString);
1546b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee        }
1547b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee
1548b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee        ImsCall.Listener listener = null;
1549b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee
1550b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee        synchronized(ImsCall.this) {
1551047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            // If we are in the midst of establishing a conference, we will bury the termination
1552047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            // until the merge has completed.  If necessary we can surface the termination at this
1553047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            // point.
1554684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            if (isCallSessionMergePending()) {
1555b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                // Since we are in the process of a merge, this trigger means something
1556b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                // else because it is probably due to the merge happening vs. the
1557b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                // session is really terminated. Let's flag this and revisit if
1558b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                // the merge() ends up failing because we will need to take action on the
1559b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                // mSession in that case since the termination was not due to the merge
1560b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                // succeeding.
1561b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                if (DBG) {
1562b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                    log("processCallTerminated :: burying termination during ongoing merge.");
1563b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                }
1564b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                mSessionEndDuringMerge = true;
1565b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                mSessionEndDuringMergeReasonInfo = reasonInfo;
1566b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                return;
1567b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee            }
1568b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee
15699bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            // If we are terminating the conference call, notify using conference listeners.
15709bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (isMultiparty()) {
1571b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                notifyConferenceSessionTerminated(reasonInfo);
15729bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                return;
1573b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee            } else {
1574b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                listener = mListener;
1575b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                clear(reasonInfo);
1576b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee            }
1577b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee        }
1578b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee
1579b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee        if (listener != null) {
1580b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee            try {
1581b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                listener.onCallTerminated(ImsCall.this, reasonInfo);
1582b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee            } catch (Throwable t) {
1583684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                loge("processCallTerminated :: ", t);
1584b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee            }
1585b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee        }
1586b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    }
158771382693cbc81b1d131085f52d97879976706f55Anthony Lee
158871382693cbc81b1d131085f52d97879976706f55Anthony Lee    /**
158971382693cbc81b1d131085f52d97879976706f55Anthony Lee     * This function determines if the ImsCallSession is our actual ImsCallSession or if is
159071382693cbc81b1d131085f52d97879976706f55Anthony Lee     * the transient session used in the process of creating a conference. This function should only
159171382693cbc81b1d131085f52d97879976706f55Anthony Lee     * be called within  callbacks that are not directly related to conference merging but might
159271382693cbc81b1d131085f52d97879976706f55Anthony Lee     * potentially still be called on the transient ImsCallSession sent to us from
159371382693cbc81b1d131085f52d97879976706f55Anthony Lee     * callSessionMergeStarted() when we don't really care. In those situations, we probably don't
159471382693cbc81b1d131085f52d97879976706f55Anthony Lee     * want to take any action so we need to know that we can return early.
159571382693cbc81b1d131085f52d97879976706f55Anthony Lee     *
159671382693cbc81b1d131085f52d97879976706f55Anthony Lee     * @param session - The {@link ImsCallSession} that the function needs to analyze
159771382693cbc81b1d131085f52d97879976706f55Anthony Lee     * @return true if this is the transient {@link ImsCallSession}, false otherwise.
159871382693cbc81b1d131085f52d97879976706f55Anthony Lee     */
159971382693cbc81b1d131085f52d97879976706f55Anthony Lee    private boolean isTransientConferenceSession(ImsCallSession session) {
160071382693cbc81b1d131085f52d97879976706f55Anthony Lee        if (session != null && session != mSession && session == mTransientConferenceSession) {
160171382693cbc81b1d131085f52d97879976706f55Anthony Lee            return true;
160271382693cbc81b1d131085f52d97879976706f55Anthony Lee        }
160371382693cbc81b1d131085f52d97879976706f55Anthony Lee        return false;
160471382693cbc81b1d131085f52d97879976706f55Anthony Lee    }
160571382693cbc81b1d131085f52d97879976706f55Anthony Lee
1606684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee    private void setTransientSessionAsPrimary(ImsCallSession transientSession) {
1607684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee        synchronized (ImsCall.this) {
1608684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            mSession.setListener(null);
1609684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            mSession = transientSession;
1610684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            mSession.setListener(createCallSessionListener());
1611684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee        }
1612684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee    }
1613684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee
161471382693cbc81b1d131085f52d97879976706f55Anthony Lee    /**
1615684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee     * This function will determine if there is a pending conference and if
1616684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee     * we are ready to finalize processing it.
1617047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     */
1618684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee    private void tryProcessConferenceResult() {
1619684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee        if (shouldProcessConferenceResult()) {
1620684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            if (isMergeHost()) {
1621684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                processMergeComplete();
1622684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            } else if (mMergeHost != null) {
1623684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                mMergeHost.processMergeComplete();
1624684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            } else {
1625684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // There must be a merge host at this point.
1626684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                loge("tryProcessConferenceResult :: No merge host for this conference!");
1627684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            }
1628684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee        }
1629047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    }
1630047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
1631047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    /**
1632684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee     * We have detected that a initial conference call has been fully configured. The internal
1633684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee     * state of both {@code ImsCall} objects need to be cleaned up to reflect the new state.
1634684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee     * This function should only be called in the context of the merge host to simplify logic
163571382693cbc81b1d131085f52d97879976706f55Anthony Lee     *
163671382693cbc81b1d131085f52d97879976706f55Anthony Lee     */
1637b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    private void processMergeComplete() {
16389bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (VDBG) {
1639684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            log("processMergeComplete :: ImsCall=" + this);
1640684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee        }
1641684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee
1642684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee        // The logic simplifies if we can assume that this function is only called on
1643684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee        // the merge host.
1644684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee        if (!isMergeHost()) {
1645684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            loge("processMergeComplete :: We are not the merge host!");
1646684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            return;
1647b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee        }
1648b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee
164971382693cbc81b1d131085f52d97879976706f55Anthony Lee        ImsCall.Listener listener;
1650047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        boolean swapRequired = false;
165171382693cbc81b1d131085f52d97879976706f55Anthony Lee        synchronized(ImsCall.this) {
1652684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            ImsCall finalHostCall = this;
1653684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            ImsCall finalPeerCall = mMergePeer;
16549bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
1655684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            if (isMultiparty()) {
1656684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // The only clean up that we need to do for a merge into an existing conference
1657684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // is to deal with the disconnect of the peer if it was successfully added to
1658684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // the conference.
1659684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                setIsMerged(false);
1660684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                if (!isSessionAlive(mMergePeer.mSession)) {
1661684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    // If the peer is dead, let's not play a disconnect sound for it when we
1662684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    // unbury the termination callback.
1663684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    mMergePeer.setIsMerged(true);
1664684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                } else {
1665684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    mMergePeer.setIsMerged(false);
1666047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                }
1667047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            } else {
1668684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // If we are here, we are not trying to merge a new call into an existing
1669684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // conference.  That means that there is a transient session on the merge
1670684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // host that represents the future conference once all the parties
1671684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // have been added to it.  So make sure that it exists or else something
1672684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // very wrong is going on.
1673684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                if (mTransientConferenceSession == null) {
1674684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    loge("processMergeComplete :: No transient session!");
1675684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    return;
1676047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                }
1677684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                if (mMergePeer == null) {
1678684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    loge("processMergeComplete :: No merge peer!");
1679684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    return;
1680047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                }
1681047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
1682684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // Since we are the host, we have the transient session attached to us. Let's detach
1683684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // it and figure out where we need to set it for the final conference configuration.
1684684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                ImsCallSession transientConferenceSession = mTransientConferenceSession;
1685684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                mTransientConferenceSession = null;
1686684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee
1687684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // Clear the listener for this transient session, we'll create a new listener
1688684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // when it is attached to the final ImsCall that it should live on.
1689684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                transientConferenceSession.setListener(null);
1690684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee
1691684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // Determine which call the transient session should be moved to.  If the current
1692684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // call session is still alive and the merge peer's session is not, we have a
1693684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // situation where the current call failed to merge into the conference but the
1694684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // merge peer did merge in to the conference.  In this type of scenario the current
1695684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // call will continue as a single party call, yet the background call will become
1696684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // the conference.
1697684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee
1698684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                if (isSessionAlive(mSession) && !isSessionAlive(mMergePeer.getCallSession())) {
1699684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    // I'm the host but we are moving the transient session to the peer since its
1700684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    // session was disconnected and my session is still alive.  This signifies that
1701684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    // their session was properly added to the conference but mine was not because
1702684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    // it is probably in the held state as opposed to part of the final conference.
1703684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    // In this case, we need to set isMerged to false on both calls so the
1704684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    // disconnect sound is called when either call disconnects.
1705684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    // Note that this case is only valid if this is an initial conference being
1706684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    // brought up.
1707684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    finalHostCall = mMergePeer;
1708684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    finalPeerCall = this;
1709684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    swapRequired = true;
1710684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    setIsMerged(false);
1711684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    mMergePeer.setIsMerged(false);
1712047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                    if (VDBG) {
1713684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                        log("processMergeComplete :: transient will transfer to merge peer");
1714047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                    }
1715684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                } else if (!isSessionAlive(mSession) && isSessionAlive(mMergePeer.getCallSession())) {
1716684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    // The transient session stays with us and the disconnect sound should be played
1717684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    // when the merge peer eventually disconnects since it was not actually added to
1718684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    // the conference and is probably sitting in the held state.
1719684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    finalHostCall = this;
1720684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    finalPeerCall = mMergePeer;
1721684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    swapRequired = false;
1722684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    setIsMerged(false);
1723684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    mMergePeer.setIsMerged(false); // Play the disconnect sound
1724047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                    if (VDBG) {
1725684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                        log("processMergeComplete :: transient will stay with the merge host");
1726684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    }
1727684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                } else {
1728684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    // The transient session stays with us and the disconnect sound should not be
1729684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    // played when we ripple up the disconnect for the merge peer because it was
1730684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    // only disconnected to be added to the conference.
1731684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    finalHostCall = this;
1732684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    finalPeerCall = mMergePeer;
1733684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    swapRequired = false;
1734684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    setIsMerged(false);
1735684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    mMergePeer.setIsMerged(true);
1736684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    if (VDBG) {
1737684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                        log("processMergeComplete :: transient will stay with us (I'm the host).");
1738047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                    }
1739047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                }
1740047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
1741684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                if (VDBG) {
1742684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    log("processMergeComplete :: call=" + finalHostCall + " is the final host");
1743684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                }
1744684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee
1745684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // Add the transient session to the ImsCall that ended up being the host for the
1746684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // conference.
1747684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                finalHostCall.setTransientSessionAsPrimary(transientConferenceSession);
1748047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            }
1749047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
1750684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            listener = finalHostCall.mListener;
1751684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee
1752684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            // Clear all the merge related flags.
1753684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            clearMergeInfo();
1754684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee
1755684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            // For the final peer...let's bubble up any possible disconnects that we had
1756684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            // during the merge process
1757684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            finalPeerCall.notifySessionTerminatedDuringMerge();
1758684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            // For the final host, let's just bury the disconnects that we my have received
1759684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            // during the merge process since we are now the host of the conference call.
1760684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            finalHostCall.clearSessionTerminationFlags();
176171382693cbc81b1d131085f52d97879976706f55Anthony Lee        }
176271382693cbc81b1d131085f52d97879976706f55Anthony Lee        if (listener != null) {
176371382693cbc81b1d131085f52d97879976706f55Anthony Lee            try {
1764047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                listener.onCallMerged(ImsCall.this, swapRequired);
176571382693cbc81b1d131085f52d97879976706f55Anthony Lee            } catch (Throwable t) {
1766b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                loge("processMergeComplete :: ", t);
176771382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
176871382693cbc81b1d131085f52d97879976706f55Anthony Lee        }
176971382693cbc81b1d131085f52d97879976706f55Anthony Lee        return;
177071382693cbc81b1d131085f52d97879976706f55Anthony Lee    }
177171382693cbc81b1d131085f52d97879976706f55Anthony Lee
177271382693cbc81b1d131085f52d97879976706f55Anthony Lee    /**
1773047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * Handles the case where the session has ended during a merge by reporting the termination
1774047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * reason to listeners.
1775047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     */
1776047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    private void notifySessionTerminatedDuringMerge() {
1777047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        ImsCall.Listener listener;
1778047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        boolean notifyFailure = false;
1779047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        ImsReasonInfo notifyFailureReasonInfo = null;
1780047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
1781047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        synchronized(ImsCall.this) {
1782047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            listener = mListener;
1783047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            if (mSessionEndDuringMerge) {
1784047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                // Set some local variables that will send out a notification about a
1785047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                // previously buried termination callback for our primary session now that
1786047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                // we know that this is not due to the conference call merging successfully.
1787047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                if (DBG) {
1788047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                    log("notifySessionTerminatedDuringMerge ::reporting terminate during merge");
1789047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                }
1790047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                notifyFailure = true;
1791047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                notifyFailureReasonInfo = mSessionEndDuringMergeReasonInfo;
1792047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            }
1793684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            clearSessionTerminationFlags();
1794047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        }
1795047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
1796047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        if (listener != null && notifyFailure) {
1797047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            try {
1798047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                processCallTerminated(notifyFailureReasonInfo);
1799047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            } catch (Throwable t) {
1800047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                loge("notifySessionTerminatedDuringMerge :: ", t);
1801047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            }
1802047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        }
1803047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    }
1804047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
1805684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee    private void clearSessionTerminationFlags() {
1806684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee        mSessionEndDuringMerge = false;
1807684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee        mSessionEndDuringMergeReasonInfo = null;
1808684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee    }
1809684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee
1810047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    /**
181171382693cbc81b1d131085f52d97879976706f55Anthony Lee     * We received a callback from ImsCallSession that a merge failed. Clean up all
1812684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee     * internal state to represent this state change.  The calling function is a callback
1813684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee     * and should have been called on the session that was in the foreground
1814684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee     * when merge() was originally called.  It is assumed that this function will be called
1815684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee     * on the merge host.
181671382693cbc81b1d131085f52d97879976706f55Anthony Lee     *
181771382693cbc81b1d131085f52d97879976706f55Anthony Lee     * @param reasonInfo The {@link ImsReasonInfo} why the merge failed.
181871382693cbc81b1d131085f52d97879976706f55Anthony Lee     */
1819b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    private void processMergeFailed(ImsReasonInfo reasonInfo) {
18209bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (VDBG) {
1821684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            log("processMergeFailed :: this=" + this + "reason=" + reasonInfo);
1822047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        }
1823047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
1824047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        ImsCall.Listener listener;
182571382693cbc81b1d131085f52d97879976706f55Anthony Lee        synchronized(ImsCall.this) {
1826684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            // The logic simplifies if we can assume that this function is only called on
1827684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            // the merge host.
1828684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            if (!isMergeHost()) {
1829684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                loge("processMergeFailed :: We are not the merge host!");
1830684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                return;
1831684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            }
1832684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee
1833684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            if (mMergePeer == null) {
1834684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                loge("processMergeFailed :: No merge peer!");
1835684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                return;
1836684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            }
1837684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee
1838684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            if (!isMultiparty()) {
1839684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                if (mTransientConferenceSession == null) {
1840684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    loge("processMergeFailed :: No transient session!");
1841684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    return;
1842684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                }
184371382693cbc81b1d131085f52d97879976706f55Anthony Lee                // Clean up any work that we performed on the transient session.
184471382693cbc81b1d131085f52d97879976706f55Anthony Lee                mTransientConferenceSession.setListener(null);
184571382693cbc81b1d131085f52d97879976706f55Anthony Lee                mTransientConferenceSession = null;
1846b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee            }
1847047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
1848684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            // Ensure the calls being conferenced into the conference has isMerged = false.
1849684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            setIsMerged(false);
1850684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            mMergePeer.setIsMerged(false);
18519bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
1852684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            listener = mListener;
1853684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee
1854684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            // Ensure any terminations are surfaced from this session.
1855684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            notifySessionTerminatedDuringMerge();
1856684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            mMergePeer.notifySessionTerminatedDuringMerge();
1857684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee
1858684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            // Clear all the various flags around coordinating this merge.
1859684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            clearMergeInfo();
186071382693cbc81b1d131085f52d97879976706f55Anthony Lee        }
186171382693cbc81b1d131085f52d97879976706f55Anthony Lee        if (listener != null) {
186271382693cbc81b1d131085f52d97879976706f55Anthony Lee            try {
186371382693cbc81b1d131085f52d97879976706f55Anthony Lee                listener.onCallMergeFailed(ImsCall.this, reasonInfo);
186471382693cbc81b1d131085f52d97879976706f55Anthony Lee            } catch (Throwable t) {
1865b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                loge("processMergeFailed :: ", t);
186671382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
186771382693cbc81b1d131085f52d97879976706f55Anthony Lee        }
1868684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee
186971382693cbc81b1d131085f52d97879976706f55Anthony Lee        return;
187071382693cbc81b1d131085f52d97879976706f55Anthony Lee    }
187171382693cbc81b1d131085f52d97879976706f55Anthony Lee
1872ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void notifyError(int reason, int statusCode, String message) {
1873ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1874ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1875ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void throwImsException(Throwable t, int code) throws ImsException {
1876ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (t instanceof ImsException) {
1877ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            throw (ImsException) t;
1878ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        } else {
1879ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            throw new ImsException(String.valueOf(code), t, code);
1880ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1881ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1882ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1883ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void log(String s) {
1884ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        Rlog.d(TAG, s);
1885ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1886ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
18879bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    /**
18889bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * Logs the specified message, as well as the current instance of {@link ImsCall}.
18899bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     *
18909bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * @param s The message to log.
18919bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     */
18929bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    private void logv(String s) {
18939bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        StringBuilder sb = new StringBuilder();
18949bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        sb.append(s);
18959bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        sb.append(" imsCall=");
18969bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        sb.append(ImsCall.this);
18979bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        Rlog.v(TAG, sb.toString());
18989bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    }
18999bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
1900ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void loge(String s) {
1901ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        Rlog.e(TAG, s);
1902ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1903ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1904ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void loge(String s, Throwable t) {
1905ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        Rlog.e(TAG, s, t);
1906ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1907ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1908ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private class ImsCallSessionListenerProxy extends ImsCallSession.Listener {
1909ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
191071382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionProgressing(ImsCallSession session, ImsStreamMediaProfile profile) {
191171382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
1912684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // If it is a transient (conference) session, there is no action for this signal.
1913b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                log("callSessionProgressing :: not supported for transient conference session=" +
1914b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
191571382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
191671382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
191771382693cbc81b1d131085f52d97879976706f55Anthony Lee
19189bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
1919684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                log("callSessionProgressing :: session=" + session + " profile=" + profile);
1920ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1921ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1922ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
1923ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1924ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
1925ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
1926ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallProfile.mMediaProfile.copyFrom(profile);
1927ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1928ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1929ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
1930ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
1931ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallProgressing(ImsCall.this);
1932ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
1933ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionProgressing :: ", t);
1934ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1935ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1936ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1937ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1938ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
193971382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionStarted(ImsCallSession session, ImsCallProfile profile) {
19409bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
1941684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                log("callSessionStarted :: session=" + session + " profile=" + profile);
1942684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            }
1943684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee
1944684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            if (!isTransientConferenceSession(session)) {
1945684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // In the case that we are in the middle of a merge (either host or peer), we have
1946684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // closure as far as this call's primary session is concerned.  If we are not
1947684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // merging...its a NOOP.
1948684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                setCallSessionMergePending(false);
1949684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            } else {
1950684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                if (VDBG) {
1951684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    log("callSessionStarted :: on transient session=" + session);
1952684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                }
1953684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                return;
1954ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1955ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1956047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            // Check if there is an ongoing conference merge which has completed.  If there is
1957047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            // we can process the merge completion now.
1958684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            tryProcessConferenceResult();
1959684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee
1960684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            if (isTransientConferenceSession(session)) {
1961684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // No further processing is needed if this is the transient session.
1962b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                return;
1963b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee            }
1964b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee
1965ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
1966ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1967ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
1968ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
1969ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallProfile = profile;
1970ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1971ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1972ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
1973ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
1974ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallStarted(ImsCall.this);
1975ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
1976ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionStarted :: ", t);
1977ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1978ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1979ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1980ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1981ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
198271382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionStartFailed(ImsCallSession session, ImsReasonInfo reasonInfo) {
198371382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
1984684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // We should not get this callback for a transient session.
1985b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                log("callSessionStartFailed :: not supported for transient conference session=" +
1986b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
198771382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
198871382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
198971382693cbc81b1d131085f52d97879976706f55Anthony Lee
19909bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
1991684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                log("callSessionStartFailed :: session=" + session + " reasonInfo=" + reasonInfo);
1992ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1993ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1994ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
1995ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1996ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
1997ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
1998ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mLastReasonInfo = reasonInfo;
1999ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2000ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2001ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2002ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2003ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallStartFailed(ImsCall.this, reasonInfo);
2004ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2005ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionStarted :: ", t);
2006ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2007ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2008ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2009ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2010ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
201171382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionTerminated(ImsCallSession session, ImsReasonInfo reasonInfo) {
2012684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            if (isTransientConferenceSession(session)) {
2013684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                log("callSessionTerminated :: on transient session=" + session);
2014684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // This is bad, it should be treated much a callSessionMergeFailed since the
2015684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // transient session only exists when in the process of a merge and the
2016684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // termination of this session is effectively the end of the merge.
2017684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                processMergeFailed(reasonInfo);
201871382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
201971382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
202071382693cbc81b1d131085f52d97879976706f55Anthony Lee
2021684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            if (VDBG) {
2022684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                log("callSessionTerminated :: session=" + session + " reasonInfo=" + reasonInfo);
2023684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            }
2024684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee
2025684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            // Process the termination first.  If we are in the midst of establishing a conference
2026684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            // call, we may bury this callback until we are done.  If there so no conference
2027684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            // call, the code after this function will be a NOOP.
2028684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            processCallTerminated(reasonInfo);
2029684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee
2030047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            // If session has terminated, it is no longer pending merge.
2031047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            setCallSessionMergePending(false);
2032047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
2033047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            // Check if there is an ongoing conference merge which has completed.  If there is
2034047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            // we can process the merge completion now.
2035684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            tryProcessConferenceResult();
2036ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2037ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2038ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
203971382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionHeld(ImsCallSession session, ImsCallProfile profile) {
204071382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2041684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // We should not get this callback for a transient session.
2042b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                log("callSessionHeld :: not supported for transient conference session=" + session);
204371382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
204471382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
204571382693cbc81b1d131085f52d97879976706f55Anthony Lee
20469bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2047684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                log("callSessionHeld :: session=" + session + "profile=" + profile);
2048ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2049ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2050ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2051ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2052ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2053047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                // If the session was held, it is no longer pending a merge -- this means it could
2054047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                // not be merged into the conference and was held instead.
2055047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                setCallSessionMergePending(false);
2056047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
2057ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallProfile = profile;
2058ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2059ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (mUpdateRequest == UPDATE_HOLD_MERGE) {
2060684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    // This hold request was made to set the stage for a merge.
2061ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    mergeInternal();
2062ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    return;
2063ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2064ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2065047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                // Check if there is an ongoing conference merge which has completed.  If there is
2066684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // we can process the merge completion now.  processMergeComplete needs to be
2067684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // called on the merge host.
2068684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                tryProcessConferenceResult();
2069047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
2070ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2071ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2072ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2073ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2074ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2075ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2076ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallHeld(ImsCall.this);
2077ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2078ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionHeld :: ", t);
2079ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2080ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2081ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2082ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2083ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
208471382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionHoldFailed(ImsCallSession session, ImsReasonInfo reasonInfo) {
208571382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2086684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // We should not get this callback for a transient session.
2087b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                log("callSessionHoldFailed :: not supported for transient conference session=" +
2088b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
208971382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
209071382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
209171382693cbc81b1d131085f52d97879976706f55Anthony Lee
20929bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2093684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                log("callSessionHoldFailed :: session" + session + "reasonInfo=" + reasonInfo);
2094ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2095ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2096ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            boolean isHoldForMerge = false;
2097ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2098ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2099ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2100ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (mUpdateRequest == UPDATE_HOLD_MERGE) {
2101ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    isHoldForMerge = true;
2102ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2103ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2104ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2105ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2106ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2107ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2108ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2109ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2110ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallHoldFailed(ImsCall.this, reasonInfo);
2111ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2112ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionHoldFailed :: ", t);
2113ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2114ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2115ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2116ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2117ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
211871382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionHoldReceived(ImsCallSession session, ImsCallProfile profile) {
211971382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2120684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // We should not get this callback for a transient session.
2121b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                log("callSessionHoldReceived :: not supported for transient conference session=" +
2122b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
212371382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
212471382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
212571382693cbc81b1d131085f52d97879976706f55Anthony Lee
21269bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2127684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                log("callSessionHoldReceived :: session=" + session + "profile=" + profile);
2128ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2129ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2130ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2131ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2132ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2133ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2134ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallProfile = profile;
2135ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2136ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2137ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2138ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2139ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallHoldReceived(ImsCall.this);
2140ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2141ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionHoldReceived :: ", t);
2142ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2143ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2144ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2145ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2146ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
214771382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionResumed(ImsCallSession session, ImsCallProfile profile) {
214871382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2149b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                log("callSessionResumed :: not supported for transient conference session=" +
2150b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
215171382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
215271382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
215371382693cbc81b1d131085f52d97879976706f55Anthony Lee
21549bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2155684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                log("callSessionResumed :: session=" + session + "profile=" + profile);
2156ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2157ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2158684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            // If this call was pending a merge, it is not anymore. This is the case when we
2159684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            // are merging in a new call into an existing conference.
2160684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            setCallSessionMergePending(false);
2161684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee
2162684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            // Check if there is an ongoing conference merge which has completed.  If there is
2163684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            // we can process the merge completion now.
2164684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            tryProcessConferenceResult();
2165684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee
2166684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            // TOOD: When we are merging a new call into an existing conference we are waiting
2167684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            // for 2 triggers to let us know that the conference has been established, the first
2168684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            // is a termination for the new calls (since it is added to the conference) the second
2169684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            // would be a resume on the existing conference.  If the resume comes first, then
2170684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            // we will make the onCallResumed() callback and its unclear how this will behave if
2171684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            // the termination has not come yet.
2172ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2173684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            ImsCall.Listener listener;
2174ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2175ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2176ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallProfile = profile;
2177ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2178095839a66699a128c76cd5002459fcba7c3a9a0dUma Maheswari Ramalingam                mHold = false;
2179ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2180ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2181ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2182ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2183ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallResumed(ImsCall.this);
2184ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2185ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionResumed :: ", t);
2186ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2187ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2188ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2189ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2190ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
219171382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionResumeFailed(ImsCallSession session, ImsReasonInfo reasonInfo) {
219271382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2193b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                log("callSessionResumeFailed :: not supported for transient conference session=" +
2194b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
219571382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
219671382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
219771382693cbc81b1d131085f52d97879976706f55Anthony Lee
21989bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2199684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                log("callSessionResumeFailed :: session=" + session + "reasonInfo=" + reasonInfo);
2200ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2201ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2202ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2203ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2204ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2205ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2206ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2207ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2208ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2209ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2210ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2211ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallResumeFailed(ImsCall.this, reasonInfo);
2212ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2213ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionResumeFailed :: ", t);
2214ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2215ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2216ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2217ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2218ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
221971382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionResumeReceived(ImsCallSession session, ImsCallProfile profile) {
222071382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2221b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                log("callSessionResumeReceived :: not supported for transient conference session=" +
2222b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
222371382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
222471382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
222571382693cbc81b1d131085f52d97879976706f55Anthony Lee
22269bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2227684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                log("callSessionResumeReceived :: session=" + session + "profile=" + profile);
2228ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2229ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2230ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2231ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2232ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2233ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2234ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallProfile = profile;
2235ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2236ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2237ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2238ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2239ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallResumeReceived(ImsCall.this);
2240ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2241ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionResumeReceived :: ", t);
2242ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2243ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2244ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2245ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2246ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
22473f2b0aaa277545886571cbf90fc90fd5d304e714Tyler Gunn        public void callSessionMergeStarted(ImsCallSession session,
2248ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsCallSession newSession, ImsCallProfile profile) {
22499bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2250684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                log("callSessionMergeStarted :: session=" + session + " newSession=" + newSession +
22519bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                        ", profile=" + profile);
2252ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2253ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2254684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            if (!isCallSessionMergePending()) {
225571382693cbc81b1d131085f52d97879976706f55Anthony Lee                // Odd, we are not in the midst of merging anything.
22569bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                log("callSessionMergeStarted :: no merge in progress.");
2257ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return;
2258ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2259ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
226071382693cbc81b1d131085f52d97879976706f55Anthony Lee            // There are 2 ways that we can go here.  If the session that supplied the params
226171382693cbc81b1d131085f52d97879976706f55Anthony Lee            // is not null, then it is the new session that represents the new conference
226271382693cbc81b1d131085f52d97879976706f55Anthony Lee            // if the merge succeeds. If it is null, the merge is happening on our current
226371382693cbc81b1d131085f52d97879976706f55Anthony Lee            // ImsCallSession.
226471382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (session == null) {
226571382693cbc81b1d131085f52d97879976706f55Anthony Lee                // Everything is already set up and we just need to make sure
226671382693cbc81b1d131085f52d97879976706f55Anthony Lee                // that we properly respond to all the future callbacks about
226771382693cbc81b1d131085f52d97879976706f55Anthony Lee                // this merge.
226871382693cbc81b1d131085f52d97879976706f55Anthony Lee                if (DBG) {
226971382693cbc81b1d131085f52d97879976706f55Anthony Lee                    log("callSessionMergeStarted :: merging into existing ImsCallSession");
227071382693cbc81b1d131085f52d97879976706f55Anthony Lee                }
227171382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
227271382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
2273ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
227471382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (DBG) {
227571382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionMergeStarted ::  setting our transient ImsCallSession");
2276ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2277ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
227871382693cbc81b1d131085f52d97879976706f55Anthony Lee            // If we are here, this means that we are creating a new conference and
227971382693cbc81b1d131085f52d97879976706f55Anthony Lee            // we need to do some extra work around managing a new ImsCallSession that
228071382693cbc81b1d131085f52d97879976706f55Anthony Lee            // could represent our new ImsCallSession if the merge succeeds.
228171382693cbc81b1d131085f52d97879976706f55Anthony Lee            synchronized(ImsCall.this) {
228271382693cbc81b1d131085f52d97879976706f55Anthony Lee                // Keep track of this session for future callbacks to indicate success
228371382693cbc81b1d131085f52d97879976706f55Anthony Lee                // or failure of this merge.
228471382693cbc81b1d131085f52d97879976706f55Anthony Lee                mTransientConferenceSession = newSession;
228571382693cbc81b1d131085f52d97879976706f55Anthony Lee                mTransientConferenceSession.setListener(createCallSessionListener());
2286ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
228771382693cbc81b1d131085f52d97879976706f55Anthony Lee
228871382693cbc81b1d131085f52d97879976706f55Anthony Lee            return;
2289ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2290ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2291ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
22923f2b0aaa277545886571cbf90fc90fd5d304e714Tyler Gunn        public void callSessionMergeComplete(ImsCallSession session) {
22939bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2294684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                log("callSessionMergeComplete :: session=" + session);
22953f2b0aaa277545886571cbf90fc90fd5d304e714Tyler Gunn            }
2296047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
2297684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            setCallSessionMergePending(false);
2298684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee
2299047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            // Check if there is an ongoing conference merge which has completed.  If there is
2300047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            // we can process the merge completion now.
2301684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            tryProcessConferenceResult();
23023f2b0aaa277545886571cbf90fc90fd5d304e714Tyler Gunn        }
23033f2b0aaa277545886571cbf90fc90fd5d304e714Tyler Gunn
23043f2b0aaa277545886571cbf90fc90fd5d304e714Tyler Gunn        @Override
230571382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionMergeFailed(ImsCallSession session, ImsReasonInfo reasonInfo) {
23069bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2307684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                log("callSessionMergeFailed :: session=" + session + "reasonInfo=" + reasonInfo);
2308ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2309684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee
2310684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            // Its possible that there could be threading issues with the other thread handling
2311684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            // the other call. This could affect our state.
2312684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            synchronized (ImsCall.this) {
2313684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                if (!isCallSessionMergePending()) {
2314684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    // Odd, we are not in the midst of merging anything.
2315684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    log("callSessionMergeFailed :: no merge in progress.");
2316684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    return;
2317684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                }
2318684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // Let's tell our parent ImsCall that the merge has failed and we need to clean
2319684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // up any temporary, transient state.  Note this only gets called for an initial
2320684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // conference.  If a merge into an existing conference fails, the two sessions will
2321684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // just go back to their original state (ACTIVE or HELD).
2322684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                if (isMergeHost()) {
2323684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    processMergeFailed(reasonInfo);
2324684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                } else if (mMergeHost != null) {
2325684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    mMergeHost.processMergeFailed(reasonInfo);
2326684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                } else {
2327684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    loge("callSessionMergeFailed :: No merge host for this conference!");
2328684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                }
2329ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2330ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2331ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2332ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
233371382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionUpdated(ImsCallSession session, ImsCallProfile profile) {
233471382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2335b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                log("callSessionUpdated :: not supported for transient conference session=" +
2336b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
233771382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
233871382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
233971382693cbc81b1d131085f52d97879976706f55Anthony Lee
23409bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2341684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                log("callSessionUpdated :: session=" + session + " profile=" + profile);
2342ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2343ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2344ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2345ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2346ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2347ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2348ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallProfile = profile;
2349ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2350ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2351ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2352ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2353ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2354ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallUpdated(ImsCall.this);
2355ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2356ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionUpdated :: ", t);
2357ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2358ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2359ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2360ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2361ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
236271382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionUpdateFailed(ImsCallSession session, ImsReasonInfo reasonInfo) {
236371382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2364b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                log("callSessionUpdateFailed :: not supported for transient conference session=" +
2365b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
236671382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
236771382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
236871382693cbc81b1d131085f52d97879976706f55Anthony Lee
23699bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2370684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                log("callSessionUpdateFailed :: session=" + session + " reasonInfo=" + reasonInfo);
2371ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2372ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2373ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2374ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2375ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2376ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2377ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2378ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2379ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2380ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2381ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2382ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallUpdateFailed(ImsCall.this, reasonInfo);
2383ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2384ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionUpdateFailed :: ", t);
2385ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2386ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2387ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2388ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2389ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
239071382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionUpdateReceived(ImsCallSession session, ImsCallProfile profile) {
239171382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2392b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                log("callSessionUpdateReceived :: not supported for transient conference " +
2393b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        "session=" + session);
239471382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
239571382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
239671382693cbc81b1d131085f52d97879976706f55Anthony Lee
23979bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2398684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                log("callSessionUpdateReceived :: session=" + session + " profile=" + profile);
2399ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2400ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2401ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2402ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2403ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2404ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2405ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mProposedCallProfile = profile;
2406ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_UNSPECIFIED;
2407ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2408ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2409ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2410ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2411ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallUpdateReceived(ImsCall.this);
2412ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2413ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionUpdateReceived :: ", t);
2414ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2415ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2416ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2417ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2418ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
241971382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionConferenceExtended(ImsCallSession session, ImsCallSession newSession,
242071382693cbc81b1d131085f52d97879976706f55Anthony Lee                ImsCallProfile profile) {
242171382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2422b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                log("callSessionConferenceExtended :: not supported for transient conference " +
2423b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        "session=" + session);
242471382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
242571382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
242671382693cbc81b1d131085f52d97879976706f55Anthony Lee
24279bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2428684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                log("callSessionConferenceExtended :: session=" + session  + " newSession=" +
2429684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                        newSession + ", profile=" + profile);
2430ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2431ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2432ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall newCall = createNewCall(newSession, profile);
2433ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2434ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (newCall == null) {
2435ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                callSessionConferenceExtendFailed(session, new ImsReasonInfo());
2436ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return;
2437ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2438ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2439ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2440ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2441ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2442ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2443ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2444ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2445ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2446ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2447ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2448ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallConferenceExtended(ImsCall.this, newCall);
2449ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2450ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionConferenceExtended :: ", t);
2451ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2452ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2453ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2454ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2455ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2456ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionConferenceExtendFailed(ImsCallSession session,
2457ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsReasonInfo reasonInfo) {
245871382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2459b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                log("callSessionConferenceExtendFailed :: not supported for transient " +
2460b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        "conference session=" + session);
246171382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
246271382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
246371382693cbc81b1d131085f52d97879976706f55Anthony Lee
2464ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
24659bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                log("callSessionConferenceExtendFailed :: imsCall=" + ImsCall.this +
2466ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ", reasonInfo=" + reasonInfo);
2467ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2468ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2469ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2470ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2471ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2472ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2473ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2474ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2475ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2476ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2477ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2478ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallConferenceExtendFailed(ImsCall.this, reasonInfo);
2479ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2480ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionConferenceExtendFailed :: ", t);
2481ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2482ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2483ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2484ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2485ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2486ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionConferenceExtendReceived(ImsCallSession session,
2487ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsCallSession newSession, ImsCallProfile profile) {
248871382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2489b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                log("callSessionConferenceExtendReceived :: not supported for transient " +
24909bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                        "conference session" + session);
249171382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
249271382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
249371382693cbc81b1d131085f52d97879976706f55Anthony Lee
24949bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2495684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                log("callSessionConferenceExtendReceived :: newSession=" + newSession +
24969bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                        ", profile=" + profile);
2497ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2498ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2499ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall newCall = createNewCall(newSession, profile);
2500ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2501ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (newCall == null) {
2502ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                // Should all the calls be terminated...???
2503ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return;
2504ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2505ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2506ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2507ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2508ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2509ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2510ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2511ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2512ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2513ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2514ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallConferenceExtendReceived(ImsCall.this, newCall);
2515ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2516ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionConferenceExtendReceived :: ", t);
2517ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2518ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2519ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2520ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2521ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2522ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionInviteParticipantsRequestDelivered(ImsCallSession session) {
252371382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
252471382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionInviteParticipantsRequestDelivered :: not supported for " +
252571382693cbc81b1d131085f52d97879976706f55Anthony Lee                        "conference session=" + session);
252671382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
252771382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
252871382693cbc81b1d131085f52d97879976706f55Anthony Lee
25299bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2530684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                log("callSessionInviteParticipantsRequestDelivered ::");
2531ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2532ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2533ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2534ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2535ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2536ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2537ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2538ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2539ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2540ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2541ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallInviteParticipantsRequestDelivered(ImsCall.this);
2542ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2543ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionInviteParticipantsRequestDelivered :: ", t);
2544ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2545ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2546ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2547ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2548ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2549ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionInviteParticipantsRequestFailed(ImsCallSession session,
2550ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsReasonInfo reasonInfo) {
255171382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
255271382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionInviteParticipantsRequestFailed :: not supported for " +
255371382693cbc81b1d131085f52d97879976706f55Anthony Lee                        "conference session=" + session);
255471382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
255571382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
255671382693cbc81b1d131085f52d97879976706f55Anthony Lee
25579bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2558684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                log("callSessionInviteParticipantsRequestFailed :: reasonInfo=" + reasonInfo);
2559ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2560ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2561ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2562ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2563ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2564ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2565ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2566ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2567ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2568ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2569ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallInviteParticipantsRequestFailed(ImsCall.this, reasonInfo);
2570ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2571ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionInviteParticipantsRequestFailed :: ", t);
2572ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2573ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2574ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2575ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2576ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2577ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionRemoveParticipantsRequestDelivered(ImsCallSession session) {
257871382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
257971382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionRemoveParticipantsRequestDelivered :: not supported for " +
258071382693cbc81b1d131085f52d97879976706f55Anthony Lee                        "conference session=" + session);
258171382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
258271382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
258371382693cbc81b1d131085f52d97879976706f55Anthony Lee
25849bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2585684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                log("callSessionRemoveParticipantsRequestDelivered ::");
2586ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2587ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2588ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2589ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2590ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2591ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2592ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2593ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2594ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2595ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2596ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallRemoveParticipantsRequestDelivered(ImsCall.this);
2597ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2598ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionRemoveParticipantsRequestDelivered :: ", t);
2599ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2600ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2601ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2602ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2603ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2604ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionRemoveParticipantsRequestFailed(ImsCallSession session,
2605ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsReasonInfo reasonInfo) {
260671382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
260771382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionRemoveParticipantsRequestFailed :: not supported for " +
26089bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                        "conference session=" + session);
260971382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
261071382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
261171382693cbc81b1d131085f52d97879976706f55Anthony Lee
26129bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2613684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                log("callSessionRemoveParticipantsRequestFailed :: reasonInfo=" + reasonInfo);
2614ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2615ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2616ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2617ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2618ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2619ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2620ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2621ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2622ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2623ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2624ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallRemoveParticipantsRequestFailed(ImsCall.this, reasonInfo);
2625ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2626ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionRemoveParticipantsRequestFailed :: ", t);
2627ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2628ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2629ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2630ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2631ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2632ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionConferenceStateUpdated(ImsCallSession session,
2633ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsConferenceState state) {
263471382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2635b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                log("callSessionConferenceStateUpdated :: not supported for transient " +
2636b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        "conference session=" + session);
263771382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
263871382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
263971382693cbc81b1d131085f52d97879976706f55Anthony Lee
26409bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2641684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                log("callSessionConferenceStateUpdated :: state=" + state);
2642ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2643ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2644938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn            conferenceStateUpdated(state);
2645ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2646ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2647ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
264871382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionUssdMessageReceived(ImsCallSession session, int mode,
264971382693cbc81b1d131085f52d97879976706f55Anthony Lee                String ussdMessage) {
265071382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2651b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                log("callSessionUssdMessageReceived :: not supported for transient " +
2652b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        "conference session=" + session);
265371382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
265471382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
265571382693cbc81b1d131085f52d97879976706f55Anthony Lee
26569bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2657684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                log("callSessionUssdMessageReceived :: mode=" + mode + ", ussdMessage=" +
26589bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                        ussdMessage);
2659ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2660ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2661ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2662ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2663ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2664ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2665ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2666ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2667ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2668ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2669ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallUssdMessageReceived(ImsCall.this, mode, ussdMessage);
2670ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2671ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionUssdMessageReceived :: ", t);
2672ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2673ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2674ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2675987bab859324396c0d1fc00c375f98f3f74c9067Pavel Zhamaitsiak
2676987bab859324396c0d1fc00c375f98f3f74c9067Pavel Zhamaitsiak        @Override
2677987bab859324396c0d1fc00c375f98f3f74c9067Pavel Zhamaitsiak        public void callSessionTtyModeReceived(ImsCallSession session, int mode) {
26789bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (VDBG) {
2679684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                log("callSessionTtyModeReceived :: mode=" + mode);
2680987bab859324396c0d1fc00c375f98f3f74c9067Pavel Zhamaitsiak            }
2681987bab859324396c0d1fc00c375f98f3f74c9067Pavel Zhamaitsiak
2682a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak            ImsCall.Listener listener;
2683a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak
2684a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak            synchronized(ImsCall.this) {
2685a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak                listener = mListener;
2686a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak            }
2687a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak
2688a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak            if (listener != null) {
2689a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak                try {
2690a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak                    listener.onCallSessionTtyModeReceived(ImsCall.this, mode);
2691a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak                } catch (Throwable t) {
2692a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak                    loge("callSessionTtyModeReceived :: ", t);
2693987bab859324396c0d1fc00c375f98f3f74c9067Pavel Zhamaitsiak                }
2694987bab859324396c0d1fc00c375f98f3f74c9067Pavel Zhamaitsiak            }
2695987bab859324396c0d1fc00c375f98f3f74c9067Pavel Zhamaitsiak        }
2696ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
2697938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn
2698938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn    /**
2699938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     * Report a new conference state to the current {@link ImsCall} and inform listeners of the
2700938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     * change.  Marked as {@code VisibleForTesting} so that the
2701938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     * {@code com.android.internal.telephony.TelephonyTester} class can inject a test conference
2702938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     * event package into a regular ongoing IMS call.
2703938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     *
2704938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     * @param state The {@link ImsConferenceState}.
2705938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     */
2706938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn    @VisibleForTesting
2707938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn    public void conferenceStateUpdated(ImsConferenceState state) {
2708938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn        Listener listener;
2709938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn
2710938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn        synchronized(this) {
2711938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn            notifyConferenceStateUpdated(state);
2712938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn            listener = mListener;
2713938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn        }
2714938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn
2715938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn        if (listener != null) {
2716938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn            try {
2717938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn                listener.onCallConferenceStateUpdated(this, state);
2718938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn            } catch (Throwable t) {
2719938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn                loge("callSessionConferenceStateUpdated :: ", t);
2720938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn            }
2721938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn        }
2722938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn    }
2723168c634eef29f21c73129164207d04b8cce23738Tyler Gunn
2724168c634eef29f21c73129164207d04b8cce23738Tyler Gunn    /**
2725168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     * Provides a human-readable string representation of an update request.
2726168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     *
2727168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     * @param updateRequest The update request.
2728168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     * @return The string representation.
2729168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     */
2730168c634eef29f21c73129164207d04b8cce23738Tyler Gunn    private String updateRequestToString(int updateRequest) {
2731168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        switch (updateRequest) {
2732168c634eef29f21c73129164207d04b8cce23738Tyler Gunn            case UPDATE_NONE:
2733168c634eef29f21c73129164207d04b8cce23738Tyler Gunn                return "NONE";
2734168c634eef29f21c73129164207d04b8cce23738Tyler Gunn            case UPDATE_HOLD:
2735168c634eef29f21c73129164207d04b8cce23738Tyler Gunn                return "HOLD";
2736168c634eef29f21c73129164207d04b8cce23738Tyler Gunn            case UPDATE_HOLD_MERGE:
2737168c634eef29f21c73129164207d04b8cce23738Tyler Gunn                return "HOLD_MERGE";
2738168c634eef29f21c73129164207d04b8cce23738Tyler Gunn            case UPDATE_RESUME:
2739168c634eef29f21c73129164207d04b8cce23738Tyler Gunn                return "RESUME";
2740168c634eef29f21c73129164207d04b8cce23738Tyler Gunn            case UPDATE_MERGE:
2741168c634eef29f21c73129164207d04b8cce23738Tyler Gunn                return "MERGE";
2742168c634eef29f21c73129164207d04b8cce23738Tyler Gunn            case UPDATE_EXTEND_TO_CONFERENCE:
2743168c634eef29f21c73129164207d04b8cce23738Tyler Gunn                return "EXTEND_TO_CONFERENCE";
2744168c634eef29f21c73129164207d04b8cce23738Tyler Gunn            case UPDATE_UNSPECIFIED:
2745168c634eef29f21c73129164207d04b8cce23738Tyler Gunn                return "UNSPECIFIED";
2746168c634eef29f21c73129164207d04b8cce23738Tyler Gunn            default:
2747168c634eef29f21c73129164207d04b8cce23738Tyler Gunn                return "UNKNOWN";
2748168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        }
2749168c634eef29f21c73129164207d04b8cce23738Tyler Gunn    }
2750168c634eef29f21c73129164207d04b8cce23738Tyler Gunn
2751168c634eef29f21c73129164207d04b8cce23738Tyler Gunn    /**
27529bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * Clears the merge peer for this call, ensuring that the peer's connection to this call is also
27539bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * severed at the same time.
27549bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     */
2755684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee    private void clearMergeInfo() {
2756684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee        if (VDBG) {
2757684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            log("clearMergeInfo :: clearing all merge info");
2758684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee        }
2759047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
2760684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee        // First clear out the merge partner then clear ourselves out.
27619bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (mMergeHost != null) {
27629bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            mMergeHost.mMergePeer = null;
276373fe1489812922e6b9583eeb080e20b420aa4d7aLibin.Tang@motorola.com            mMergeHost.mUpdateRequest = UPDATE_NONE;
2764684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            mMergeHost.mCallSessionMergePending = false;
27659bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        }
27669bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (mMergePeer != null) {
27679bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            mMergePeer.mMergeHost = null;
276873fe1489812922e6b9583eeb080e20b420aa4d7aLibin.Tang@motorola.com            mMergePeer.mUpdateRequest = UPDATE_NONE;
2769684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            mMergePeer.mCallSessionMergePending = false;
27709bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        }
2771684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee        mMergeHost = null;
2772684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee        mMergePeer = null;
2773684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee        mUpdateRequest = UPDATE_NONE;
2774684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee        mCallSessionMergePending = false;
27759bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    }
27769bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
27779bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    /**
27789bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * Sets the merge peer for the current call.  The merge peer is the background call that will be
27799bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * merged into this call.  On the merge peer, sets the merge host to be this call.
27809bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     *
27819bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * @param mergePeer The peer call to be merged into this one.
27829bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     */
27839bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    private void setMergePeer(ImsCall mergePeer) {
27849bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        mMergePeer = mergePeer;
27859bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        mMergeHost = null;
27869bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
27879bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        mergePeer.mMergeHost = ImsCall.this;
27889bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        mergePeer.mMergePeer = null;
27899bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    }
27909bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
27919bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    /**
27929bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * Sets the merge hody for the current call.  The merge host is the foreground call this call
27939bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * will be merged into.  On the merge host, sets the merge peer to be this call.
27949bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     *
27959bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * @param mergeHost The merge host this call will be merged into.
27969bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     */
27979bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    public void setMergeHost(ImsCall mergeHost) {
27989bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        mMergeHost = mergeHost;
27999bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        mMergePeer = null;
28009bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
28019bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        mergeHost.mMergeHost = null;
28029bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        mergeHost.mMergePeer = ImsCall.this;
28039bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    }
28049bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
28059bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    /**
28069bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * Determines if the current call is in the process of merging with another call or conference.
28079bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     *
28089bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * @return {@code true} if in the process of merging.
28099bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     */
28109bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    private boolean isMerging() {
28119bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        return mMergePeer != null || mMergeHost != null;
28129bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    }
28139bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
28149bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    /**
28159bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * Determines if the current call is the host of the merge.
28169bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     *
28179bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * @return {@code true} if the call is the merge host.
28189bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     */
28199bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    private boolean isMergeHost() {
28209bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        return mMergePeer != null && mMergeHost == null;
28219bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    }
28229bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
28239bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    /**
28249bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * Determines if the current call is the peer of the merge.
28259bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     *
28269bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * @return {@code true} if the call is the merge peer.
28279bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     */
28289bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    private boolean isMergePeer() {
28299bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        return mMergePeer == null && mMergeHost != null;
28309bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    }
28319bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
28329bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    /**
2833047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * Determines if the call session is pending merge into a conference or not.
2834047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     *
2835047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * @return {@code true} if a merge into a conference is pending, {@code false} otherwise.
2836047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     */
2837047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    private boolean isCallSessionMergePending() {
2838047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        return mCallSessionMergePending;
2839047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    }
2840047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
2841047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    /**
2842047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * Sets flag indicating whether the call session is pending merge into a conference or not.
2843047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     *
2844047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * @param callSessionMergePending {@code true} if a merge into the conference is pending,
2845047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     *      {@code false} otherwise.
2846047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     */
2847047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    private void setCallSessionMergePending(boolean callSessionMergePending) {
2848047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        mCallSessionMergePending = callSessionMergePending;
2849047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    }
2850047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
2851047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    /**
2852047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * Determines if there is a conference merge in process.  If there is a merge in process,
2853047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * determines if both the merge host and peer sessions have completed the merge process.  This
2854047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * means that we have received terminate or hold signals for the sessions, indicating that they
2855047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * are no longer in the process of being merged into the conference.
2856047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * <p>
2857684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee     * The sessions are considered to have merged if: both calls still have merge peer/host
2858684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee     * relationships configured,  both sessions are not waiting to be merged into the conference,
2859684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee     * and the transient conference session is alive in the case of an initial conference.
2860047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     *
2861047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * @return {@code true} where the host and peer sessions have finished merging into the
2862047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     *      conference, {@code false} if the merge has not yet completed, and {@code false} if there
2863047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     *      is no conference merge in progress.
2864047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     */
2865684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee    private boolean shouldProcessConferenceResult() {
2866684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee        boolean areMergeTriggersDone = false;
2867684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee
2868684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee        synchronized (ImsCall.this) {
2869684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            // if there is a merge going on, then the merge host/peer relationships should have been
2870684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            // set up.  This works for both the initial conference or merging a call into an
2871684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            // existing conference.
2872684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            if (!isMergeHost() && !isMergePeer()) {
2873684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                if (VDBG) {
2874684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    log("shouldProcessConferenceResult :: no merge in progress");
2875684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                }
2876684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                return false;
2877684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            }
2878047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
2879684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            // There is a merge in progress, so check the sessions to ensure:
2880684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            // 1. Both calls have completed being merged (or failing to merge) into the conference.
2881684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            // 2. The transient conference session is alive.
2882684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            if (isMergeHost()) {
2883684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                if (VDBG) {
2884684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    log("shouldProcessConferenceResult :: We are a merge host=" + this);
2885684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    log("shouldProcessConferenceResult :: Here is the merge peer=" + mMergePeer);
2886684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                }
2887684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                areMergeTriggersDone = !isCallSessionMergePending() &&
2888684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                        !mMergePeer.isCallSessionMergePending();
2889684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                if (!isMultiparty()) {
2890684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    // Only check the transient session when there is no existing conference
2891684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    areMergeTriggersDone &= isSessionAlive(mTransientConferenceSession);
2892684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                }
2893684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            } else if (isMergePeer()) {
2894684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                if (VDBG) {
2895684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    log("shouldProcessConferenceResult :: We are a merge peer=" + this);
2896684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    log("shouldProcessConferenceResult :: Here is the merge host=" + mMergeHost);
2897684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                }
2898684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                areMergeTriggersDone = !isCallSessionMergePending() &&
2899684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                        !mMergeHost.isCallSessionMergePending();
2900684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                if (!mMergeHost.isMultiparty()) {
2901684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    // Only check the transient session when there is no existing conference
2902684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    areMergeTriggersDone &= isSessionAlive(mMergeHost.mTransientConferenceSession);
2903684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                } else {
2904684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    // This else block is a special case for Verizon to handle these steps
2905684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    // 1. Establish a conference call.
2906684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    // 2. Add a new call (conference in in BG)
2907684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    // 3. Swap (conference active on FG)
2908684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    // 4. Merge
2909684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    // What happens here is that the BG call gets a terminated callback
2910684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    // because it was added to the conference. I've seen where
2911684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    // the FG gets no callback at all because its already active.
2912684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    // So if we continue to wait for it to set its isCallSessionMerging
2913684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    // flag to false...we'll be waiting forever.
2914684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                    areMergeTriggersDone = !isCallSessionMergePending();
2915684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                }
2916684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            } else {
2917684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                // Realistically this shouldn't happen, but best to be safe.
2918684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                loge("shouldProcessConferenceResult : merge in progress but call is neither" +
2919684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                        "host nor peer.");
2920684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            }
2921684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            if (VDBG) {
2922684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                log("shouldProcessConferenceResult :: returning:" +
2923684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee                        (areMergeTriggersDone ? "true" : "false"));
2924684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee            }
2925047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        }
2926684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee        return areMergeTriggersDone;
2927047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    }
2928047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
2929047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    /**
2930168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     * Provides a string representation of the {@link ImsCall}.  Primarily intended for use in log
2931168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     * statements.
2932168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     *
2933168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     * @return String representation of call.
2934168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     */
2935168c634eef29f21c73129164207d04b8cce23738Tyler Gunn    @Override
2936168c634eef29f21c73129164207d04b8cce23738Tyler Gunn    public String toString() {
2937168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        StringBuilder sb = new StringBuilder();
2938168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        sb.append("[ImsCall objId:");
2939168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        sb.append(System.identityHashCode(this));
29409bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        sb.append(" onHold:");
29419bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        sb.append(isOnHold() ? "Y" : "N");
29429bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        sb.append(" mute:");
29439bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        sb.append(isMuted() ? "Y" : "N");
29449bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        sb.append(" updateRequest:");
29459bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        sb.append(updateRequestToString(mUpdateRequest));
294687466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn        sb.append(" merging:");
294787466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn        sb.append(isMerging() ? "Y" : "N");
294887466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn        if (isMerging()) {
294987466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn            if (isMergePeer()) {
295087466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                sb.append("P");
295187466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn            } else {
295287466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                sb.append("H");
295387466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn            }
295487466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn        }
2955684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee        sb.append(" merge action pending:");
2956684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee        sb.append(isCallSessionMergePending() ? "Y" : "N");
295787466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn        sb.append(" merged:");
295887466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn        sb.append(isMerged() ? "Y" : "N");
2959168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        sb.append(" multiParty:");
29609bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        sb.append(isMultiparty() ? "Y" : "N");
2961684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee        sb.append(" buried term:");
2962684de85a0e1313be480fdebb107a9adaaf432b36Anthony Lee        sb.append(mSessionEndDuringMerge ? "Y" : "N");
2963168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        sb.append(" session:");
2964168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        sb.append(mSession);
2965168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        sb.append(" transientSession:");
2966168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        sb.append(mTransientConferenceSession);
2967168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        sb.append("]");
2968168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        return sb.toString();
2969168c634eef29f21c73129164207d04b8cce23738Tyler Gunn    }
2970ef36ef67e009449300b0150c60c9f637e205d79eWink Saville}
2971