ImsCall.java revision 1c46760f9e523312d92e027dfdb52d359d65efe1
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;
33ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
34ef36ef67e009449300b0150c60c9f637e205d79eWink Savilleimport com.android.ims.internal.CallGroup;
35ef36ef67e009449300b0150c60c9f637e205d79eWink Savilleimport com.android.ims.internal.CallGroupManager;
36ef36ef67e009449300b0150c60c9f637e205d79eWink Savilleimport com.android.ims.internal.ICall;
37ef36ef67e009449300b0150c60c9f637e205d79eWink Savilleimport com.android.ims.internal.ImsCallSession;
38ef36ef67e009449300b0150c60c9f637e205d79eWink Savilleimport com.android.ims.internal.ImsStreamMediaSession;
39938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunnimport com.android.internal.annotations.VisibleForTesting;
40ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
41ef36ef67e009449300b0150c60c9f637e205d79eWink Saville/**
42ef36ef67e009449300b0150c60c9f637e205d79eWink Saville * Handles an IMS voice / video call over LTE. You can instantiate this class with
43ef36ef67e009449300b0150c60c9f637e205d79eWink Saville * {@link ImsManager}.
44ef36ef67e009449300b0150c60c9f637e205d79eWink Saville *
45ef36ef67e009449300b0150c60c9f637e205d79eWink Saville * @hide
46ef36ef67e009449300b0150c60c9f637e205d79eWink Saville */
47ef36ef67e009449300b0150c60c9f637e205d79eWink Savillepublic class ImsCall implements ICall {
48ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public static final int CALL_STATE_ACTIVE_TO_HOLD = 1;
49ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public static final int CALL_STATE_HOLD_TO_ACTIVE = 2;
50ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
51ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // Mode of USSD message
52ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public static final int USSD_MODE_NOTIFY = 0;
53ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public static final int USSD_MODE_REQUEST = 1;
54ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
55ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final String TAG = "ImsCall";
56ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final boolean DBG = true;
57ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
58ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
59ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Listener for events relating to an IMS call, such as when a call is being
60ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * recieved ("on ringing") or a call is outgoing ("on calling").
61ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * <p>Many of these events are also received by {@link ImsCallSession.Listener}.</p>
62ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
63ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public static class Listener {
64ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
65ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when a request is sent out to initiate a new call
66ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * and 1xx response is received from the network.
67ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
68ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
69ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
70ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
71ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallProgressing(ImsCall call) {
72ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallStateChanged(call);
73ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
74ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
75ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
76ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call is established.
77ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
78ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
79ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
80ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
81ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallStarted(ImsCall call) {
82ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallStateChanged(call);
83ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
84ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
85ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
86ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call setup is failed.
87ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallError}.
88ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
89ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
90ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the call setup failure
91ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
92ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallStartFailed(ImsCall call, ImsReasonInfo reasonInfo) {
93ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallError(call, reasonInfo);
94ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
95ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
96ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
97ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call is terminated.
98ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
99ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
100ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
101ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the call termination
102ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
103ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallTerminated(ImsCall call, ImsReasonInfo reasonInfo) {
104ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // Store the call termination reason
105ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
106ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallStateChanged(call);
107ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
108ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
109ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
110ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call is in hold.
111ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
112ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
113ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
114ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
115ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallHeld(ImsCall call) {
116ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallStateChanged(call);
117ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
118ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
119ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
120ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call hold is failed.
121ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallError}.
122ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
123ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
124ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the call hold failure
125ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
126ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallHoldFailed(ImsCall call, ImsReasonInfo reasonInfo) {
127ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallError(call, reasonInfo);
128ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
129ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
130ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
131ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call hold is received from the remote user.
132ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
133ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
134ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
135ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
136ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallHoldReceived(ImsCall call) {
137ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallStateChanged(call);
138ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
139ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
140ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
141ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call is in call.
142ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
143ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
144ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
145ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
146ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallResumed(ImsCall call) {
147ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallStateChanged(call);
148ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
149ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
150ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
151ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call resume is failed.
152ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallError}.
153ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
154ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
155ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the call resume failure
156ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
157ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallResumeFailed(ImsCall call, ImsReasonInfo reasonInfo) {
158ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallError(call, reasonInfo);
159ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
160ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
161ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
162ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call resume is received from the remote user.
163ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
164ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
165ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
166ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
167ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallResumeReceived(ImsCall call) {
168ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallStateChanged(call);
169ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
170ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
171ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
172ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call is in call.
173ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
174ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
175ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
176ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param newCall the call object that is merged with an active & hold call
177ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
17871382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void onCallMerged(ImsCall call) {
17971382693cbc81b1d131085f52d97879976706f55Anthony Lee            onCallStateChanged(call);
180ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
181ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
182ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
183ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call merge is failed.
184ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallError}.
185ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
186ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
187ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the call merge failure
188ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
189ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallMergeFailed(ImsCall call, ImsReasonInfo reasonInfo) {
190ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallError(call, reasonInfo);
191ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
192ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
193ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
194ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call is updated (except for hold/unhold).
195ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
196ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
197ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
198ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
199ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallUpdated(ImsCall call) {
200ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallStateChanged(call);
201ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
202ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
203ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
204ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call update is failed.
205ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallError}.
206ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
207ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
208ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the call update failure
209ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
210ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallUpdateFailed(ImsCall call, ImsReasonInfo reasonInfo) {
211ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallError(call, reasonInfo);
212ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
213ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
214ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
215ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call update is received from the remote user.
216ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
217ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
218ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
219ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallUpdateReceived(ImsCall call) {
220ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
221ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
222ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
223ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
224ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call is extended to the conference call.
225ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
226ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
227ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
228ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param newCall the call object that is extended to the conference from the active call
229ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
230ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallConferenceExtended(ImsCall call, ImsCall newCall) {
23171382693cbc81b1d131085f52d97879976706f55Anthony Lee            onCallStateChanged(call);
232ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
233ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
234ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
235ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the conference extension is failed.
236ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallError}.
237ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
238ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
239ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the conference extension failure
240ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
241ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallConferenceExtendFailed(ImsCall call,
242ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsReasonInfo reasonInfo) {
243ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallError(call, reasonInfo);
244ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
245ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
246ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
247ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the conference extension is received from the remote user.
248ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
249ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
250ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param newCall the call object that is extended to the conference from the active call
251ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
252ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallConferenceExtendReceived(ImsCall call, ImsCall newCall) {
25371382693cbc81b1d131085f52d97879976706f55Anthony Lee            onCallStateChanged(call);
254ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
255ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
256ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
257ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the invitation request of the participants is delivered to
258ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * the conference server.
259ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
260ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
261ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
262ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallInviteParticipantsRequestDelivered(ImsCall call) {
263ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
264ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
265ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
266ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
267ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the invitation request of the participants is failed.
268ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
269ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
270ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the conference invitation failure
271ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
272ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallInviteParticipantsRequestFailed(ImsCall call,
273ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsReasonInfo reasonInfo) {
274ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
275ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
276ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
277ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
278ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the removal request of the participants is delivered to
279ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * the conference server.
280ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
281ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
282ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
283ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallRemoveParticipantsRequestDelivered(ImsCall call) {
284ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
285ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
286ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
287ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
288ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the removal request of the participants is failed.
289ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
290ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
291ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the conference removal failure
292ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
293ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallRemoveParticipantsRequestFailed(ImsCall call,
294ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsReasonInfo reasonInfo) {
295ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
296ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
297ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
298ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
299ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the conference state is updated.
300ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
301ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
302ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param state state of the participant who is participated in the conference call
303ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
304ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallConferenceStateUpdated(ImsCall call, ImsConferenceState state) {
305ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
306ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
307ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
308ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
3091c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn         * Called when the state of IMS conference participant(s) has changed.
3105965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn         *
3115965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn         * @param call the call object that carries out the IMS call.
3121c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn         * @param participants the participant(s) and their new state information.
3135965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn         */
3141c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn        public void onConferenceParticipantsStateChanged(ImsCall call,
3151c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn                List<ConferenceParticipant> participants) {
3165965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn            // no-op
3175965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn        }
3185965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn
3195965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn        /**
320ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the USSD message is received from the network.
321ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
322ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param mode mode of the USSD message (REQUEST / NOTIFY)
323ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param ussdMessage USSD message
324ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
325ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallUssdMessageReceived(ImsCall call,
326ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                int mode, String ussdMessage) {
327ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
328ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
329ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
330ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
331ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when an error occurs. The default implementation is no op.
332ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * overridden. The default implementation is no op. Error events are
333ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * not re-directed to this callback and are handled in {@link #onCallError}.
334ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
335ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
336ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of this error
337ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @see ImsReasonInfo
338ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
339ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallError(ImsCall call, ImsReasonInfo reasonInfo) {
340ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
341ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
342ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
343ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
344ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when an event occurs and the corresponding callback is not
345ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * overridden. The default implementation is no op. Error events are
346ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * not re-directed to this callback and are handled in {@link #onCallError}.
347ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
348ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
349ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
350ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallStateChanged(ImsCall call) {
351ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
352ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
353ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
354ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
355ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call moves the hold state to the conversation state.
356ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * For example, when merging the active & hold call, the state of all the hold call
357ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * will be changed from hold state to conversation state.
358ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * This callback method can be invoked even though the application does not trigger
359ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * any operations.
360ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
361ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
362ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param state the detailed state of call state changes;
363ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *      Refer to CALL_STATE_* in {@link ImsCall}
364ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
365ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallStateChanged(ImsCall call, int state) {
366ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
367ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
368ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
369ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
370ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
371ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
372ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // List of update operation for IMS call control
373ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_NONE = 0;
374ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_HOLD = 1;
375ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_HOLD_MERGE = 2;
376ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_RESUME = 3;
377ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_MERGE = 4;
378ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_EXTEND_TO_CONFERENCE = 5;
379ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_UNSPECIFIED = 6;
380ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
381ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // For synchronization of private variables
382ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private Object mLockObj = new Object();
383ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private Context mContext;
384ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
385ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // true if the call is established & in the conversation state
386ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private boolean mInCall = false;
387ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // true if the call is on hold
388ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // If it is triggered by the local, mute the call. Otherwise, play local hold tone
389ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // or network generated media.
390ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private boolean mHold = false;
391ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // true if the call is on mute
392ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private boolean mMute = false;
393ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // It contains the exclusive call update request. Refer to UPDATE_*.
394ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private int mUpdateRequest = UPDATE_NONE;
395ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
396ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsCall.Listener mListener = null;
397ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // It is for managing the multiple calls
398ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // when the multiparty call is extended to the conference.
399ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private CallGroup mCallGroup = null;
400ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
401ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // Wrapper call session to interworking the IMS service (server).
402ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsCallSession mSession = null;
403ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // Call profile of the current session.
404ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // It can be changed at anytime when the call is updated.
405ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsCallProfile mCallProfile = null;
406ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // Call profile to be updated after the application's action (accept/reject)
407ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // to the call update. After the application's action (accept/reject) is done,
408ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // it will be set to null.
409ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsCallProfile mProposedCallProfile = null;
410ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsReasonInfo mLastReasonInfo = null;
411ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
412ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // Media session to control media (audio/video) operations for an IMS call
413ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsStreamMediaSession mMediaSession = null;
414ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
41571382693cbc81b1d131085f52d97879976706f55Anthony Lee    private ImsCallSession mTransientConferenceSession = null;
41667a843d7d44c1b3a87644389b33f842df1c08351Tyler Gunn
417ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
418ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Create an IMS call object.
419ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
420ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param context the context for accessing system services
421ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param profile the call profile to make/take a call
422ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
423ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsCall(Context context, ImsCallProfile profile) {
424ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mContext = context;
425ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mCallProfile = profile;
426ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
427ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
428ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
429ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Closes this object. This object is not usable after being closed.
430ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
431ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    @Override
432ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void close() {
433ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
434ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            destroyCallGroup();
435ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
436ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession != null) {
437ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mSession.close();
438ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mSession = null;
439ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
440ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
441ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mCallProfile = null;
442ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mProposedCallProfile = null;
443ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mLastReasonInfo = null;
444ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mMediaSession = null;
445ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
446ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
447ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
448ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
449ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Checks if the call has a same remote user identity or not.
450ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
451ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param userId the remote user identity
452ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return true if the remote user identity is equal; otherwise, false
453ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
454ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    @Override
455ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public boolean checkIfRemoteUserIsSame(String userId) {
456ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (userId == null) {
457ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return false;
458ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
459ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
460ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        return userId.equals(mCallProfile.getCallExtra(ImsCallProfile.EXTRA_REMOTE_URI, ""));
461ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
462ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
463ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
464ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Checks if the call is equal or not.
465ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
466ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param call the call to be compared
467ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return true if the call is equal; otherwise, false
468ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
469ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    @Override
470ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public boolean equalsTo(ICall call) {
471ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (call == null) {
472ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return false;
473ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
474ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
475ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (call instanceof ImsCall) {
47616b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen            return this.equals(call);
477ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
478ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
479ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        return false;
480ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
481ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
482ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
483ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the negotiated (local & remote) call profile.
484ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
485ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return a {@link ImsCallProfile} object that has the negotiated call profile
486ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
487ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsCallProfile getCallProfile() {
488ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
489ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mCallProfile;
490ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
491ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
492ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
493ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
494ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the local call profile (local capabilities).
495ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
496ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return a {@link ImsCallProfile} object that has the local call profile
497ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
498ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsCallProfile getLocalCallProfile() throws ImsException {
499ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
500ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
501ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
502ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
503ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
504ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
505ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            try {
506ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return mSession.getLocalCallProfile();
507ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } catch (Throwable t) {
508ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("getLocalCallProfile :: ", t);
509ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("getLocalCallProfile()", t, 0);
510ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
511ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
512ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
513ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
514ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
515ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the call profile proposed by the local/remote user.
516ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
517ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return a {@link ImsCallProfile} object that has the proposed call profile
518ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
519ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsCallProfile getProposedCallProfile() {
520ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
521ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (!isInCall()) {
522ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return null;
523ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
524ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
525ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mProposedCallProfile;
526ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
527ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
528ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
529ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
530ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the state of the {@link ImsCallSession} that carries this call.
531ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * The value returned must be one of the states in {@link ImsCallSession#State}.
532ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
533ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return the session state
534ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
535ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public int getState() {
536ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
537ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
538ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return ImsCallSession.State.IDLE;
539ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
540ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
541ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mSession.getState();
542ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
543ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
544ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
545ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
546ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the {@link ImsCallSession} that carries this call.
547ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
548ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return the session object that carries this call
549ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @hide
550ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
551ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsCallSession getCallSession() {
552ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
553ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mSession;
554ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
555ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
556ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
557ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
558ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the {@link ImsStreamMediaSession} that handles the media operation of this call.
559ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Almost interface APIs are for the VT (Video Telephony).
560ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
561ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return the media session object that handles the media operation of this call
562ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @hide
563ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
564ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsStreamMediaSession getMediaSession() {
565ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
566ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mMediaSession;
567ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
568ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
569ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
570ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
571ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the specified property of this call.
572ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
573ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param name key to get the extra call information defined in {@link ImsCallProfile}
574ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return the extra call information as string
575ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
576ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public String getCallExtra(String name) throws ImsException {
577ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        // Lookup the cache
578ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
579ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
580ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // If not found, try to get the property from the remote
581ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
582ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
583ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
584ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
585ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
586ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            try {
587ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return mSession.getProperty(name);
588ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } catch (Throwable t) {
589ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("getCallExtra :: ", t);
590ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("getCallExtra()", t, 0);
591ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
592ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
593ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
594ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
595ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
596ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the last reason information when the call is not established, cancelled or terminated.
597ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
598ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return the last reason information
599ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
600ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsReasonInfo getLastReasonInfo() {
601ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
602ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mLastReasonInfo;
603ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
604ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
605ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
606ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
607ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Checks if the call has a pending update operation.
608ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
609ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return true if the call has a pending update operation
610ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
611ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public boolean hasPendingUpdate() {
612ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
613ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return (mUpdateRequest != UPDATE_NONE);
614ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
615ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
616ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
617ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
618ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Checks if the call is established.
619ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
620ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return true if the call is established
621ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
622ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public boolean isInCall() {
623ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
624ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mInCall;
625ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
626ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
627ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
628ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
629ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Checks if the call is muted.
630ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
631ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return true if the call is muted
632ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
633ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public boolean isMuted() {
634ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
635ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mMute;
636ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
637ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
638ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
639ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
640ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Checks if the call is on hold.
641ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
642ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return true if the call is on hold
643ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
644ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public boolean isOnHold() {
645ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
646ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mHold;
647ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
648ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
649ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
650ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
651725ad373383798c1516348475b1f6304484e031eTyler Gunn     * Determines if the call is a multiparty call.
652725ad373383798c1516348475b1f6304484e031eTyler Gunn     *
653725ad373383798c1516348475b1f6304484e031eTyler Gunn     * @return {@code True} if the call is a multiparty call.
654725ad373383798c1516348475b1f6304484e031eTyler Gunn     */
655725ad373383798c1516348475b1f6304484e031eTyler Gunn    public boolean isMultiparty() {
65616b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen        synchronized(mLockObj) {
65716b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen            if (mSession == null) {
65816b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen                return false;
65916b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen            }
66016b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen
66171382693cbc81b1d131085f52d97879976706f55Anthony Lee            return mSession.isMultiparty();
66216b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen        }
663725ad373383798c1516348475b1f6304484e031eTyler Gunn    }
664725ad373383798c1516348475b1f6304484e031eTyler Gunn
665725ad373383798c1516348475b1f6304484e031eTyler Gunn    /**
666ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Sets the listener to listen to the IMS call events.
667ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * The method calls {@link #setListener setListener(listener, false)}.
668ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
669ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param listener to listen to the IMS call events of this object; null to remove listener
670ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see #setListener(Listener, boolean)
671ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
672ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void setListener(ImsCall.Listener listener) {
673ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        setListener(listener, false);
674ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
675ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
676ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
677ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Sets the listener to listen to the IMS call events.
678ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * A {@link ImsCall} can only hold one listener at a time. Subsequent calls
679ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * to this method override the previous listener.
680ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
681ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param listener to listen to the IMS call events of this object; null to remove listener
682ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param callbackImmediately set to true if the caller wants to be called
683ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *        back immediately on the current state
684ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
685ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void setListener(ImsCall.Listener listener, boolean callbackImmediately) {
686ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        boolean inCall;
687ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        boolean onHold;
688ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        int state;
689ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        ImsReasonInfo lastReasonInfo;
690ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
691ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
692ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mListener = listener;
693ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
694ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if ((listener == null) || !callbackImmediately) {
695ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return;
696ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
697ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
698ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            inCall = mInCall;
699ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onHold = mHold;
700ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            state = getState();
701ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            lastReasonInfo = mLastReasonInfo;
702ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
703ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
704ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        try {
705ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (lastReasonInfo != null) {
706ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener.onCallError(this, lastReasonInfo);
707ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } else if (inCall) {
708ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (onHold) {
709ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallHeld(this);
710ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } else {
711ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallStarted(this);
712ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
713ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } else {
714ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                switch (state) {
715ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    case ImsCallSession.State.ESTABLISHING:
716ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        listener.onCallProgressing(this);
717ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        break;
718ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    case ImsCallSession.State.TERMINATED:
719ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        listener.onCallTerminated(this, lastReasonInfo);
720ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        break;
721ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    default:
722ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        // Ignore it. There is no action in the other state.
723ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        break;
724ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
725ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
726ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        } catch (Throwable t) {
727ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            loge("setListener()", t);
728ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
729ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
730ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
731ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
732ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Mutes or unmutes the mic for the active call.
733ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
734ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param muted true if the call is muted, false otherwise
735ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
736ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void setMute(boolean muted) throws ImsException {
737ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
738ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mMute != muted) {
739ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mMute = muted;
740ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
741ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
742ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    mSession.setMute(muted);
743ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
744ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("setMute :: ", t);
745ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    throwImsException(t, 0);
746ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
747ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
748ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
749ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
750ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
751ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     /**
752ef36ef67e009449300b0150c60c9f637e205d79eWink Saville      * Attaches an incoming call to this call object.
753ef36ef67e009449300b0150c60c9f637e205d79eWink Saville      *
754ef36ef67e009449300b0150c60c9f637e205d79eWink Saville      * @param session the session that receives the incoming call
755ef36ef67e009449300b0150c60c9f637e205d79eWink Saville      * @throws ImsException if the IMS service fails to attach this object to the session
756ef36ef67e009449300b0150c60c9f637e205d79eWink Saville      */
757ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     public void attachSession(ImsCallSession session) throws ImsException {
758ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         if (DBG) {
759ef36ef67e009449300b0150c60c9f637e205d79eWink Saville             log("attachSession :: session=" + session);
760ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         }
761ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
762ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         synchronized(mLockObj) {
763ef36ef67e009449300b0150c60c9f637e205d79eWink Saville             mSession = session;
764ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
765ef36ef67e009449300b0150c60c9f637e205d79eWink Saville             try {
766ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                 mSession.setListener(createCallSessionListener());
767ef36ef67e009449300b0150c60c9f637e205d79eWink Saville             } catch (Throwable t) {
768ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                 loge("attachSession :: ", t);
769ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                 throwImsException(t, 0);
770ef36ef67e009449300b0150c60c9f637e205d79eWink Saville             }
771ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         }
772ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     }
773ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
774ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
775ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Initiates an IMS call with the call profile which is provided
776ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * when creating a {@link ImsCall}.
777ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
778ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param session the {@link ImsCallSession} for carrying out the call
779ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param callee callee information to initiate an IMS call
780ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to initiate the call
781ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
782ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void start(ImsCallSession session, String callee)
783ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            throws ImsException {
784ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (DBG) {
785ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            log("start(1) :: session=" + session + ", callee=" + callee);
786ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
787ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
788ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
789ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession = session;
790ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
791ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            try {
792ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                session.setListener(createCallSessionListener());
793ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                session.start(callee, mCallProfile);
794ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } catch (Throwable t) {
795ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("start(1) :: ", t);
796ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("start(1)", t, 0);
797ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
798ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
799ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
800ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
801ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
802ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Initiates an IMS conferenca call with the call profile which is provided
803ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * when creating a {@link ImsCall}.
804ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
805ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param session the {@link ImsCallSession} for carrying out the call
806ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param participants participant list to initiate an IMS conference call
807ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to initiate the call
808ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
809ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void start(ImsCallSession session, String[] participants)
810ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            throws ImsException {
811ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (DBG) {
812ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            log("start(n) :: session=" + session + ", callee=" + participants);
813ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
814ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
815ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
816ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession = session;
817ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
818ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            try {
819ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                session.setListener(createCallSessionListener());
820ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                session.start(participants, mCallProfile);
821ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } catch (Throwable t) {
822ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("start(n) :: ", t);
823ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("start(n)", t, 0);
824ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
825ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
826ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
827ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
828ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
829ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Accepts a call.
830ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
831ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallStarted
832d1edfd8cf9ffeb191a84e08522bb570cd8cd4381Tyler Gunn     *
833d1edfd8cf9ffeb191a84e08522bb570cd8cd4381Tyler Gunn     * @param callType The call type the user agreed to for accepting the call.
834ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to accept the call
835ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
836d1edfd8cf9ffeb191a84e08522bb570cd8cd4381Tyler Gunn    public void accept(int callType) throws ImsException {
837ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (DBG) {
838ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            log("accept :: session=" + mSession);
839ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
840ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
841d1edfd8cf9ffeb191a84e08522bb570cd8cd4381Tyler Gunn        accept(callType, new ImsStreamMediaProfile());
842ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
843ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
844ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
845ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Accepts a call.
846ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
847ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param callType call type to be answered in {@link ImsCallProfile}
848ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param profile a media profile to be answered (audio/audio & video, direction, ...)
849ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallStarted
850ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to accept the call
851ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
852ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void accept(int callType, ImsStreamMediaProfile profile) throws ImsException {
853ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (DBG) {
854ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            log("accept :: session=" + mSession
855ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    + ", callType=" + callType + ", profile=" + profile);
856ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
857ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
858ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
859ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
860ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call to answer",
861ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
862ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
863ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
864ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            try {
865ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mSession.accept(callType, profile);
866ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } catch (Throwable t) {
867ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("accept :: ", t);
868ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("accept()", t, 0);
869ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
870ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
871ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mInCall && (mProposedCallProfile != null)) {
872ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (DBG) {
873ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    log("accept :: call profile will be updated");
874ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
875ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
876ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallProfile = mProposedCallProfile;
877ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mProposedCallProfile = null;
878ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
879ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
880ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // Other call update received
881ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mInCall && (mUpdateRequest == UPDATE_UNSPECIFIED)) {
882ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
883ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
884ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
885ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
886ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
887ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
888ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Rejects a call.
889ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
890ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param reason reason code to reject an incoming call
891ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallStartFailed
892ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to accept the call
893ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
894ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void reject(int reason) throws ImsException {
895ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (DBG) {
896ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            log("reject :: session=" + mSession + ", reason=" + reason);
897ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
898ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
899ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
900ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession != null) {
901ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mSession.reject(reason);
902ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
903ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
904ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mInCall && (mProposedCallProfile != null)) {
905ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (DBG) {
906ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    log("reject :: call profile is not updated; destroy it...");
907ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
908ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
909ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mProposedCallProfile = null;
910ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
911ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
912ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // Other call update received
913ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mInCall && (mUpdateRequest == UPDATE_UNSPECIFIED)) {
914ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
915ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
916ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
917ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
918ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
919ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
920ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Terminates an IMS call.
921ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
922ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param reason reason code to terminate a call
923ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to terminate the call
924ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
925ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void terminate(int reason) throws ImsException {
926ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (DBG) {
927ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            log("terminate :: session=" + mSession + ", reason=" + reason);
928ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
929ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
930ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
931ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mHold = false;
932ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mInCall = false;
933d43b5302d8edf4df90a28055f043786f542df219Uma Maheswari Ramalingam            CallGroup callGroup = getCallGroup();
934ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
935ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession != null) {
936d43b5302d8edf4df90a28055f043786f542df219Uma Maheswari Ramalingam                if (callGroup != null && !callGroup.isOwner(ImsCall.this)) {
937d43b5302d8edf4df90a28055f043786f542df219Uma Maheswari Ramalingam                    log("terminate owner of the call group");
938d43b5302d8edf4df90a28055f043786f542df219Uma Maheswari Ramalingam                    ImsCall owner = (ImsCall) callGroup.getOwner();
939d43b5302d8edf4df90a28055f043786f542df219Uma Maheswari Ramalingam                    if (owner != null) {
940d43b5302d8edf4df90a28055f043786f542df219Uma Maheswari Ramalingam                        owner.terminate(reason);
941d43b5302d8edf4df90a28055f043786f542df219Uma Maheswari Ramalingam                        return;
942d43b5302d8edf4df90a28055f043786f542df219Uma Maheswari Ramalingam                    }
943d43b5302d8edf4df90a28055f043786f542df219Uma Maheswari Ramalingam                }
944ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mSession.terminate(reason);
945ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
946ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
947ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
948ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
949d43b5302d8edf4df90a28055f043786f542df219Uma Maheswari Ramalingam
950ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
951ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Puts a call on hold. When succeeds, {@link Listener#onCallHeld} is called.
952ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
953ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallHeld, Listener#onCallHoldFailed
954ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to hold the call
955ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
956ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void hold() throws ImsException {
957ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (DBG) {
958ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            log("hold :: session=" + mSession);
959ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
960ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
961111eecc9845826e985c48133b754e453fb3aca84Etan Cohen        // perform operation on owner before doing any local checks: local
962111eecc9845826e985c48133b754e453fb3aca84Etan Cohen        // call may not have its status updated
963111eecc9845826e985c48133b754e453fb3aca84Etan Cohen        synchronized (mLockObj) {
964111eecc9845826e985c48133b754e453fb3aca84Etan Cohen            CallGroup callGroup = mCallGroup;
965111eecc9845826e985c48133b754e453fb3aca84Etan Cohen            if (callGroup != null && !callGroup.isOwner(ImsCall.this)) {
966111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                log("hold owner of the call group");
967111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                ImsCall owner = (ImsCall) callGroup.getOwner();
968111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                if (owner != null) {
969111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                    owner.hold();
970111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                    return;
971111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                }
972111eecc9845826e985c48133b754e453fb3aca84Etan Cohen            }
973111eecc9845826e985c48133b754e453fb3aca84Etan Cohen        }
974111eecc9845826e985c48133b754e453fb3aca84Etan Cohen
975ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (isOnHold()) {
976ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
977ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("hold :: call is already on hold");
978ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
979ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return;
980ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
981ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
982ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
983ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mUpdateRequest != UPDATE_NONE) {
984ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("hold :: update is in progress; request=" + mUpdateRequest);
985ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("Call update is in progress",
986ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
987ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
988ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
989ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
990ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("hold :: ");
991ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
992ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
993ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
994ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
995ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession.hold(createHoldMediaProfile());
996ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // FIXME: update the state on the callback?
997ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mHold = true;
998ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mUpdateRequest = UPDATE_HOLD;
999ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1000ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1001ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1002ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1003ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Continues a call that's on hold. When succeeds, {@link Listener#onCallResumed} is called.
1004ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1005ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallResumed, Listener#onCallResumeFailed
1006ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to resume the call
1007ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1008ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void resume() throws ImsException {
1009ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (DBG) {
1010ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            log("resume :: session=" + mSession);
1011ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1012ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1013111eecc9845826e985c48133b754e453fb3aca84Etan Cohen        // perform operation on owner before doing any local checks: local
1014111eecc9845826e985c48133b754e453fb3aca84Etan Cohen        // call may not have its status updated
1015111eecc9845826e985c48133b754e453fb3aca84Etan Cohen        synchronized (mLockObj) {
1016111eecc9845826e985c48133b754e453fb3aca84Etan Cohen            CallGroup callGroup = mCallGroup;
1017111eecc9845826e985c48133b754e453fb3aca84Etan Cohen            if (callGroup != null && !callGroup.isOwner(ImsCall.this)) {
1018111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                log("resume owner of the call group");
1019111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                ImsCall owner = (ImsCall) callGroup.getOwner();
1020111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                if (owner != null) {
1021111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                    owner.resume();
1022111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                    return;
1023111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                }
1024111eecc9845826e985c48133b754e453fb3aca84Etan Cohen            }
1025111eecc9845826e985c48133b754e453fb3aca84Etan Cohen        }
1026111eecc9845826e985c48133b754e453fb3aca84Etan Cohen
1027ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (!isOnHold()) {
1028ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
1029ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("resume :: call is in conversation");
1030ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1031ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return;
1032ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1033ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1034ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1035ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mUpdateRequest != UPDATE_NONE) {
1036ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("resume :: update is in progress; request=" + mUpdateRequest);
1037ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("Call update is in progress",
1038ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
1039ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1040ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1041ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1042ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("resume :: ");
1043ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1044ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1045ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1046ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1047ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession.resume(createResumeMediaProfile());
1048ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // FIXME: update the state on the callback?
1049ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mHold = false;
1050ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mUpdateRequest = UPDATE_RESUME;
1051ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1052ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1053ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1054ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1055ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Merges the active & hold call.
1056ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1057ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallMerged, Listener#onCallMergeFailed
1058ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to merge the call
1059ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1060ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void merge() throws ImsException {
1061ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (DBG) {
1062ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            log("merge :: session=" + mSession);
1063ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1064ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1065ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1066ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mUpdateRequest != UPDATE_NONE) {
1067ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("merge :: update is in progress; request=" + mUpdateRequest);
1068ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("Call update is in progress",
1069ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
1070ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1071ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1072ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1073ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("merge :: ");
1074ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1075ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1076ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1077ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1078ca45f58a57eb782153c034ae067f59c0018799caUma Maheswari Ramalingam            // if skipHoldBeforeMerge = true, IMS service implementation will
1079ca45f58a57eb782153c034ae067f59c0018799caUma Maheswari Ramalingam            // merge without explicitly holding the call.
1080ca45f58a57eb782153c034ae067f59c0018799caUma Maheswari Ramalingam            if (mHold || (mContext.getResources().getBoolean(
1081ca45f58a57eb782153c034ae067f59c0018799caUma Maheswari Ramalingam                    com.android.internal.R.bool.skipHoldBeforeMerge))) {
1082ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mSession.merge();
1083ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_MERGE;
1084ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } else {
108571382693cbc81b1d131085f52d97879976706f55Anthony Lee                // This code basically says, we need to explicitly hold before requesting a merge
108671382693cbc81b1d131085f52d97879976706f55Anthony Lee                // when we get the callback that the hold was successful (or failed), we should
108771382693cbc81b1d131085f52d97879976706f55Anthony Lee                // automatically request a merge.
1088ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mSession.hold(createHoldMediaProfile());
1089ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mHold = true;
1090ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_HOLD_MERGE;
1091ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1092ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1093ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1094ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1095ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1096ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Merges the active & hold call.
1097ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1098ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param bgCall the background (holding) call
1099ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallMerged, Listener#onCallMergeFailed
1100ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to merge the call
1101ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1102ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void merge(ImsCall bgCall) throws ImsException {
1103ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (DBG) {
1104ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            log("merge(1) :: session=" + mSession);
1105ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1106ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1107ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (bgCall == null) {
1108ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            throw new ImsException("No background call",
1109ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
1110ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1111ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1112ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1113ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            createCallGroup(bgCall);
1114ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1115ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1116ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        merge();
1117ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1118ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1119ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1120ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Updates the current call's properties (ex. call mode change: video upgrade / downgrade).
1121ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1122ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void update(int callType, ImsStreamMediaProfile mediaProfile) throws ImsException {
1123ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (DBG) {
1124ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            log("update :: session=" + mSession);
1125ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1126ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1127ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (isOnHold()) {
1128ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
1129ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("update :: call is on hold");
1130ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1131ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            throw new ImsException("Not in a call to update call",
1132ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
1133ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1134ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1135ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1136ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mUpdateRequest != UPDATE_NONE) {
1137ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (DBG) {
1138ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    log("update :: update is in progress; request=" + mUpdateRequest);
1139ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1140ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("Call update is in progress",
1141ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
1142ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1143ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1144ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1145ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("update :: ");
1146ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1147ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1148ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1149ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1150ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession.update(callType, mediaProfile);
1151ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mUpdateRequest = UPDATE_UNSPECIFIED;
1152ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1153ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1154ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1155ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1156ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Extends this call (1-to-1 call) to the conference call
1157ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * inviting the specified participants to.
1158ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1159ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1160ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void extendToConference(String[] participants) throws ImsException {
1161ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (DBG) {
1162ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            log("extendToConference :: session=" + mSession);
1163ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1164ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1165ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (isOnHold()) {
1166ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
1167ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("extendToConference :: call is on hold");
1168ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1169ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            throw new ImsException("Not in a call to extend a call to conference",
1170ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
1171ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1172ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1173ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1174ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mUpdateRequest != UPDATE_NONE) {
1175ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (DBG) {
1176ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    log("extendToConference :: update is in progress; request=" + mUpdateRequest);
1177ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1178ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("Call update is in progress",
1179ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
1180ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1181ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1182ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1183ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("extendToConference :: ");
1184ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1185ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1186ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1187ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1188ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession.extendToConference(participants);
1189ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mUpdateRequest = UPDATE_EXTEND_TO_CONFERENCE;
1190ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1191ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1192ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1193ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1194ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Requests the conference server to invite an additional participants to the conference.
1195ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1196ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1197ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void inviteParticipants(String[] participants) throws ImsException {
1198ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (DBG) {
1199ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            log("inviteParticipants :: session=" + mSession);
1200ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1201ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1202ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1203ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1204ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("inviteParticipants :: ");
1205ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1206ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1207ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1208ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1209ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession.inviteParticipants(participants);
1210ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1211ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1212ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1213ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1214ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Requests the conference server to remove the specified participants from the conference.
1215ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1216ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1217ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void removeParticipants(String[] participants) throws ImsException {
1218ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (DBG) {
1219ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            log("removeParticipants :: session=" + mSession);
1220ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1221ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1222ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1223ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1224ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("removeParticipants :: ");
1225ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1226ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1227ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1228ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1229ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession.removeParticipants(participants);
1230ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1231ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1232ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1233ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1234ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1235ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Sends a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2833</a>,
1236ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * event 0 ~ 9 maps to decimal value 0 ~ 9, '*' to 10, '#' to 11, event 'A' ~ 'D' to 12 ~ 15,
1237ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * and event flash to 16. Currently, event flash is not supported.
1238ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
12392f92daf76a66d7d2fe6fb7b1a28fc1b5888a7b7cLibin.Tang@motorola.com     * @param char that represents the DTMF digit to send.
1240ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
12412f92daf76a66d7d2fe6fb7b1a28fc1b5888a7b7cLibin.Tang@motorola.com    public void sendDtmf(char c) {
12422f92daf76a66d7d2fe6fb7b1a28fc1b5888a7b7cLibin.Tang@motorola.com        sendDtmf(c, null);
1243ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1244ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1245ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1246ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Sends a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2833</a>,
1247ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * event 0 ~ 9 maps to decimal value 0 ~ 9, '*' to 10, '#' to 11, event 'A' ~ 'D' to 12 ~ 15,
1248ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * and event flash to 16. Currently, event flash is not supported.
1249ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
12502f92daf76a66d7d2fe6fb7b1a28fc1b5888a7b7cLibin.Tang@motorola.com     * @param c that represents the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs.
12512f92daf76a66d7d2fe6fb7b1a28fc1b5888a7b7cLibin.Tang@motorola.com     * @param result the result message to send when done.
1252ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
12532f92daf76a66d7d2fe6fb7b1a28fc1b5888a7b7cLibin.Tang@motorola.com    public void sendDtmf(char c, Message result) {
1254ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (DBG) {
12552f92daf76a66d7d2fe6fb7b1a28fc1b5888a7b7cLibin.Tang@motorola.com            log("sendDtmf :: session=" + mSession + ", code=" + c);
1256ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1257ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1258ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1259ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession != null) {
12602f92daf76a66d7d2fe6fb7b1a28fc1b5888a7b7cLibin.Tang@motorola.com                mSession.sendDtmf(c);
1261ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1262ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1263ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1264ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (result != null) {
1265ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            result.sendToTarget();
1266ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1267ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1268ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1269ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1270ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Sends an USSD message.
1271ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1272ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param ussdMessage USSD message to send
1273ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1274ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void sendUssd(String ussdMessage) throws ImsException {
1275ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (DBG) {
1276ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            log("sendUssd :: session=" + mSession + ", ussdMessage=" + ussdMessage);
1277ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1278ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1279ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1280ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1281ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("sendUssd :: ");
1282ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1283ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1284ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1285ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1286ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession.sendUssd(ussdMessage);
1287ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1288ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1289ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1290ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void clear(ImsReasonInfo lastReasonInfo) {
1291ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mInCall = false;
1292ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mHold = false;
1293ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mUpdateRequest = UPDATE_NONE;
1294ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mLastReasonInfo = lastReasonInfo;
1295ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        destroyCallGroup();
1296ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1297ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1298ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void createCallGroup(ImsCall neutralReferrer) {
1299ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        CallGroup referrerCallGroup = neutralReferrer.getCallGroup();
1300ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1301ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (mCallGroup == null) {
1302ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (referrerCallGroup == null) {
1303ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallGroup = CallGroupManager.getInstance().createCallGroup(new ImsCallGroup());
1304ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } else {
1305ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallGroup = referrerCallGroup;
1306ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1307ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1308ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mCallGroup != null) {
1309ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallGroup.setNeutralReferrer(neutralReferrer);
1310ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1311ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        } else {
1312ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mCallGroup.setNeutralReferrer(neutralReferrer);
1313ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1314ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if ((referrerCallGroup != null)
1315ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    && (mCallGroup != referrerCallGroup)) {
1316ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("fatal :: call group is mismatched; call is corrupted...");
1317ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1318ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1319ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1320ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1321ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void updateCallGroup(ImsCall owner) {
1322ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (mCallGroup == null) {
1323ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return;
1324ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1325ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1326ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        ImsCall neutralReferrer = (ImsCall)mCallGroup.getNeutralReferrer();
1327ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1328ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (owner == null) {
1329ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // Maintain the call group if the current call has been merged in the past.
1330ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (!mCallGroup.hasReferrer()) {
1331ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                CallGroupManager.getInstance().destroyCallGroup(mCallGroup);
1332ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallGroup = null;
1333ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1334ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        } else {
1335ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mCallGroup.addReferrer(this);
1336ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1337ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (neutralReferrer != null) {
1338d43b5302d8edf4df90a28055f043786f542df219Uma Maheswari Ramalingam                if (neutralReferrer.getCallGroup() == null) {
1339ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    neutralReferrer.setCallGroup(mCallGroup);
1340ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    mCallGroup.addReferrer(neutralReferrer);
1341ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1342ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1343ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                neutralReferrer.enforceConversationMode();
1344ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1345ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1346ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // Close the existing owner call if present
1347ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall exOwner = (ImsCall)mCallGroup.getOwner();
1348ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1349ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mCallGroup.setOwner(owner);
1350ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1351ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (exOwner != null) {
1352ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                exOwner.close();
1353ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1354ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1355ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1356ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1357ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void destroyCallGroup() {
1358ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (mCallGroup == null) {
1359ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return;
1360ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1361ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1362ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mCallGroup.removeReferrer(this);
1363ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1364ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (!mCallGroup.hasReferrer()) {
1365ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            CallGroupManager.getInstance().destroyCallGroup(mCallGroup);
1366ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1367ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1368ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mCallGroup = null;
1369ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1370ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1371345fbb2613e3a1985108dc2c42ceabe2711243a6Pavel Zhamaitsiak    public CallGroup getCallGroup() {
1372ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1373ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mCallGroup;
1374ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1375ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1376ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1377ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void setCallGroup(CallGroup callGroup) {
1378ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1379ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mCallGroup = callGroup;
1380ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1381ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1382ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1383ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1384ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Creates an IMS call session listener.
1385ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1386ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsCallSession.Listener createCallSessionListener() {
1387ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        return new ImsCallSessionListenerProxy();
1388ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1389ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1390ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsCall createNewCall(ImsCallSession session, ImsCallProfile profile) {
1391ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        ImsCall call = new ImsCall(mContext, profile);
1392ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1393ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        try {
1394ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            call.attachSession(session);
1395ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        } catch (ImsException e) {
1396ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (call != null) {
1397ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                call.close();
1398ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                call = null;
1399ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1400ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1401ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1402ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        // Do additional operations...
1403ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1404ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        return call;
1405ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1406ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1407ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsStreamMediaProfile createHoldMediaProfile() {
1408ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        ImsStreamMediaProfile mediaProfile = new ImsStreamMediaProfile();
1409ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1410ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (mCallProfile == null) {
1411ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mediaProfile;
1412ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1413ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1414ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mediaProfile.mAudioQuality = mCallProfile.mMediaProfile.mAudioQuality;
1415ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mediaProfile.mVideoQuality = mCallProfile.mMediaProfile.mVideoQuality;
1416ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mediaProfile.mAudioDirection = ImsStreamMediaProfile.DIRECTION_SEND;
1417ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1418ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (mediaProfile.mVideoQuality != ImsStreamMediaProfile.VIDEO_QUALITY_NONE) {
1419ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mediaProfile.mVideoDirection = ImsStreamMediaProfile.DIRECTION_SEND;
1420ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1421ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1422ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        return mediaProfile;
1423ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1424ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1425ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsStreamMediaProfile createResumeMediaProfile() {
1426ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        ImsStreamMediaProfile mediaProfile = new ImsStreamMediaProfile();
1427ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1428ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (mCallProfile == null) {
1429ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mediaProfile;
1430ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1431ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1432ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mediaProfile.mAudioQuality = mCallProfile.mMediaProfile.mAudioQuality;
1433ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mediaProfile.mVideoQuality = mCallProfile.mMediaProfile.mVideoQuality;
1434ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mediaProfile.mAudioDirection = ImsStreamMediaProfile.DIRECTION_SEND_RECEIVE;
1435ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1436ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (mediaProfile.mVideoQuality != ImsStreamMediaProfile.VIDEO_QUALITY_NONE) {
1437ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mediaProfile.mVideoDirection = ImsStreamMediaProfile.DIRECTION_SEND_RECEIVE;
1438ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1439ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1440ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        return mediaProfile;
1441ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1442ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1443ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void enforceConversationMode() {
1444ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (mInCall) {
1445ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mHold = false;
1446ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mUpdateRequest = UPDATE_NONE;
1447ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1448ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1449ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1450ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void mergeInternal() {
1451ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (DBG) {
1452ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            log("mergeInternal :: session=" + mSession);
1453ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1454ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1455ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mSession.merge();
1456ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mUpdateRequest = UPDATE_MERGE;
1457ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1458ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1459ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void notifyConferenceSessionTerminated(ImsReasonInfo reasonInfo) {
1460ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        ImsCall.Listener listener;
1461ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (mCallGroup.isOwner(ImsCall.this)) {
1462111eecc9845826e985c48133b754e453fb3aca84Etan Cohen            log("Group Owner! Size of referrers list = " + mCallGroup.getReferrers().size());
1463d43b5302d8edf4df90a28055f043786f542df219Uma Maheswari Ramalingam            while (mCallGroup.hasReferrer()) {
1464d43b5302d8edf4df90a28055f043786f542df219Uma Maheswari Ramalingam                ImsCall call = (ImsCall) mCallGroup.getReferrers().get(0);
1465111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                log("onCallTerminated to be called for the call:: " + call);
1466ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1467d43b5302d8edf4df90a28055f043786f542df219Uma Maheswari Ramalingam                if (call == null) {
1468d43b5302d8edf4df90a28055f043786f542df219Uma Maheswari Ramalingam                    continue;
1469d43b5302d8edf4df90a28055f043786f542df219Uma Maheswari Ramalingam                }
1470ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1471d43b5302d8edf4df90a28055f043786f542df219Uma Maheswari Ramalingam                listener = call.mListener;
1472d43b5302d8edf4df90a28055f043786f542df219Uma Maheswari Ramalingam                call.clear(reasonInfo);
1473ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1474d43b5302d8edf4df90a28055f043786f542df219Uma Maheswari Ramalingam                if (listener != null) {
1475d43b5302d8edf4df90a28055f043786f542df219Uma Maheswari Ramalingam                    try {
1476d43b5302d8edf4df90a28055f043786f542df219Uma Maheswari Ramalingam                        listener.onCallTerminated(call, reasonInfo);
1477d43b5302d8edf4df90a28055f043786f542df219Uma Maheswari Ramalingam                    } catch (Throwable t) {
1478d43b5302d8edf4df90a28055f043786f542df219Uma Maheswari Ramalingam                        loge("notifyConferenceSessionTerminated :: ", t);
1479ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    }
1480ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1481ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1482ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        } else if (!mCallGroup.isReferrer(ImsCall.this)) {
1483ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return;
1484ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1485ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1486ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        listener = mListener;
1487ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        clear(reasonInfo);
1488ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1489ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (listener != null) {
1490ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            try {
1491ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener.onCallTerminated(this, reasonInfo);
1492ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } catch (Throwable t) {
1493ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("notifyConferenceSessionTerminated :: ", t);
1494ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1495ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1496ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1497ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1498111eecc9845826e985c48133b754e453fb3aca84Etan Cohen    private void notifyConferenceStateUpdatedThroughGroupOwner(int update) {
1499111eecc9845826e985c48133b754e453fb3aca84Etan Cohen        ImsCall.Listener listener;
1500111eecc9845826e985c48133b754e453fb3aca84Etan Cohen
1501111eecc9845826e985c48133b754e453fb3aca84Etan Cohen        if (mCallGroup.isOwner(ImsCall.this)) {
1502111eecc9845826e985c48133b754e453fb3aca84Etan Cohen            log("Group Owner! Size of referrers list = " + mCallGroup.getReferrers().size());
1503111eecc9845826e985c48133b754e453fb3aca84Etan Cohen            for (ICall icall : mCallGroup.getReferrers()) {
1504111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                ImsCall call = (ImsCall) icall;
150571382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("notifyConferenceStateUpdatedThroughGroupOwner to be called for the call:: " +
150671382693cbc81b1d131085f52d97879976706f55Anthony Lee                        call);
1507111eecc9845826e985c48133b754e453fb3aca84Etan Cohen
1508111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                if (call == null) {
1509111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                    continue;
1510111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                }
1511111eecc9845826e985c48133b754e453fb3aca84Etan Cohen
1512111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                listener = call.mListener;
1513111eecc9845826e985c48133b754e453fb3aca84Etan Cohen
1514111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                if (listener != null) {
1515111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                    try {
1516111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                        switch (update) {
1517111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                            case UPDATE_HOLD:
1518111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                                listener.onCallHeld(call);
1519111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                                break;
1520111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                            case UPDATE_RESUME:
1521111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                                listener.onCallResumed(call);
1522111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                                break;
1523111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                            default:
152471382693cbc81b1d131085f52d97879976706f55Anthony Lee                                loge("notifyConferenceStateUpdatedThroughGroupOwner :: not " +
152571382693cbc81b1d131085f52d97879976706f55Anthony Lee                                        "handled update " + update);
1526111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                        }
1527111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                    } catch (Throwable t) {
1528111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                        loge("notifyConferenceStateUpdatedThroughGroupOwner :: ", t);
1529111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                    }
1530111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                }
1531111eecc9845826e985c48133b754e453fb3aca84Etan Cohen            }
1532111eecc9845826e985c48133b754e453fb3aca84Etan Cohen        }
1533111eecc9845826e985c48133b754e453fb3aca84Etan Cohen    }
1534111eecc9845826e985c48133b754e453fb3aca84Etan Cohen
1535ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void notifyConferenceStateUpdated(ImsConferenceState state) {
15361c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn        Set<Entry<String, Bundle>> participants = state.mParticipants.entrySet();
1537ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
15381c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn        if (participants == null) {
1539ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return;
1540ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1541ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
15421c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn        Iterator<Entry<String, Bundle>> iterator = participants.iterator();
15431c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn        List<ConferenceParticipant> conferenceParticipants = new ArrayList<>(participants.size());
1544ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        while (iterator.hasNext()) {
1545ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            Entry<String, Bundle> entry = iterator.next();
1546ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1547ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            String key = entry.getKey();
1548ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            Bundle confInfo = entry.getValue();
1549ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            String status = confInfo.getString(ImsConferenceState.STATUS);
1550ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            String user = confInfo.getString(ImsConferenceState.USER);
15515965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn            String displayName = confInfo.getString(ImsConferenceState.DISPLAY_TEXT);
1552ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            String endpoint = confInfo.getString(ImsConferenceState.ENDPOINT);
1553ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1554ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
1555ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("notifyConferenceStateUpdated :: key=" + key +
1556ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ", status=" + status +
1557ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ", user=" + user +
15585965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn                        ", displayName= " + displayName +
1559ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ", endpoint=" + endpoint);
1560ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1561ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
15625965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn            if ((mCallGroup != null) && (!mCallGroup.isOwner(ImsCall.this))) {
1563ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                continue;
1564ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1565ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
15665965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn            // Attempt to find the participant in the call group if it exists.
15675965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn            ImsCall referrer = null;
15685965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn            if (mCallGroup != null) {
15695965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn                referrer = (ImsCall) mCallGroup.getReferrer(endpoint);
15705965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn            }
1571ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
15725965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn            // Participant is not being represented by an ImsCall, so handle as generic participant.
15735965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn            // Notify the {@code ImsPhoneCallTracker} of the participant state change so that it
15745965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn            // can be passed up to the {@code TelephonyConferenceController}.
1575ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (referrer == null) {
15765965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn                Uri handle = Uri.parse(user);
15775965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn                Uri endpointUri = Uri.parse(endpoint);
15785965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn                int connectionState = ImsConferenceState.getConnectionStateForStatus(status);
15795965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn
15805965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn                ConferenceParticipant conferenceParticipant = new ConferenceParticipant(handle,
15815965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn                        displayName, endpointUri, connectionState);
15821c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn                conferenceParticipants.add(conferenceParticipant);
1583ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                continue;
1584ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1585ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1586ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (referrer.mListener == null) {
1587ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                continue;
1588ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1589ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1590ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            try {
1591ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (status.equals(ImsConferenceState.STATUS_ALERTING)) {
1592ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    referrer.mListener.onCallProgressing(referrer);
1593ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1594ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                else if (status.equals(ImsConferenceState.STATUS_CONNECT_FAIL)) {
1595ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    referrer.mListener.onCallStartFailed(referrer, new ImsReasonInfo());
1596ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1597ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                else if (status.equals(ImsConferenceState.STATUS_ON_HOLD)) {
1598ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    referrer.mListener.onCallHoldReceived(referrer);
1599ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1600ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                else if (status.equals(ImsConferenceState.STATUS_CONNECTED)) {
1601ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    referrer.mListener.onCallStarted(referrer);
1602ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1603ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                else if (status.equals(ImsConferenceState.STATUS_DISCONNECTED)) {
1604ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    referrer.clear(new ImsReasonInfo());
1605ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    referrer.mListener.onCallTerminated(referrer, referrer.mLastReasonInfo);
1606ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1607ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } catch (Throwable t) {
1608ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("notifyConferenceStateUpdated :: ", t);
1609ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1610ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
16111c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn
16121c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn        if (!conferenceParticipants.isEmpty() && mListener != null) {
16131c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn            try {
16141c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn                mListener.onConferenceParticipantsStateChanged(this, conferenceParticipants);
16151c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn            } catch (Throwable t) {
16161c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn                loge("notifyConferenceStateUpdated :: ", t);
16171c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn            }
16181c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn        }
1619ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1620ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
162171382693cbc81b1d131085f52d97879976706f55Anthony Lee
162271382693cbc81b1d131085f52d97879976706f55Anthony Lee    /**
162371382693cbc81b1d131085f52d97879976706f55Anthony Lee     * This function determines if the ImsCallSession is our actual ImsCallSession or if is
162471382693cbc81b1d131085f52d97879976706f55Anthony Lee     * the transient session used in the process of creating a conference. This function should only
162571382693cbc81b1d131085f52d97879976706f55Anthony Lee     * be called within  callbacks that are not directly related to conference merging but might
162671382693cbc81b1d131085f52d97879976706f55Anthony Lee     * potentially still be called on the transient ImsCallSession sent to us from
162771382693cbc81b1d131085f52d97879976706f55Anthony Lee     * callSessionMergeStarted() when we don't really care. In those situations, we probably don't
162871382693cbc81b1d131085f52d97879976706f55Anthony Lee     * want to take any action so we need to know that we can return early.
162971382693cbc81b1d131085f52d97879976706f55Anthony Lee     *
163071382693cbc81b1d131085f52d97879976706f55Anthony Lee     * @param session - The {@link ImsCallSession} that the function needs to analyze
163171382693cbc81b1d131085f52d97879976706f55Anthony Lee     * @return true if this is the transient {@link ImsCallSession}, false otherwise.
163271382693cbc81b1d131085f52d97879976706f55Anthony Lee     */
163371382693cbc81b1d131085f52d97879976706f55Anthony Lee    private boolean isTransientConferenceSession(ImsCallSession session) {
163471382693cbc81b1d131085f52d97879976706f55Anthony Lee        if (session != null && session != mSession && session == mTransientConferenceSession) {
163571382693cbc81b1d131085f52d97879976706f55Anthony Lee            return true;
163671382693cbc81b1d131085f52d97879976706f55Anthony Lee        }
163771382693cbc81b1d131085f52d97879976706f55Anthony Lee        return false;
163871382693cbc81b1d131085f52d97879976706f55Anthony Lee    }
163971382693cbc81b1d131085f52d97879976706f55Anthony Lee
164071382693cbc81b1d131085f52d97879976706f55Anthony Lee    /**
164171382693cbc81b1d131085f52d97879976706f55Anthony Lee     * We received a callback from ImsCallSession that a merge was complete. Clean up all
164271382693cbc81b1d131085f52d97879976706f55Anthony Lee     * internal state to represent this state change.
164371382693cbc81b1d131085f52d97879976706f55Anthony Lee     *
164471382693cbc81b1d131085f52d97879976706f55Anthony Lee     * @param session The {@link ImsCallSession} that is the host of this conference.
164571382693cbc81b1d131085f52d97879976706f55Anthony Lee     */
164671382693cbc81b1d131085f52d97879976706f55Anthony Lee    private void processMergeComplete(ImsCallSession session) {
164771382693cbc81b1d131085f52d97879976706f55Anthony Lee        // If mTransientConferenceSession is set, this means that this is a newly created
164871382693cbc81b1d131085f52d97879976706f55Anthony Lee        // conference. Otherwise, we are adding to an existing conference.
164971382693cbc81b1d131085f52d97879976706f55Anthony Lee        ImsCall.Listener listener;
165071382693cbc81b1d131085f52d97879976706f55Anthony Lee        synchronized(ImsCall.this) {
165171382693cbc81b1d131085f52d97879976706f55Anthony Lee            listener = mListener;
165271382693cbc81b1d131085f52d97879976706f55Anthony Lee            // TODO: See if we can use the session param to do some further checks here.
165371382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (mTransientConferenceSession != null) {
165471382693cbc81b1d131085f52d97879976706f55Anthony Lee                // We need to replace our ImsCallSession with this new one after adjusting
165571382693cbc81b1d131085f52d97879976706f55Anthony Lee                // the listeners on the session.
165671382693cbc81b1d131085f52d97879976706f55Anthony Lee                mSession.setListener(null);
165771382693cbc81b1d131085f52d97879976706f55Anthony Lee                mTransientConferenceSession.setListener(createCallSessionListener());
165871382693cbc81b1d131085f52d97879976706f55Anthony Lee                mSession = mTransientConferenceSession;
165971382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
166071382693cbc81b1d131085f52d97879976706f55Anthony Lee            mUpdateRequest = UPDATE_NONE;
166171382693cbc81b1d131085f52d97879976706f55Anthony Lee        }
166271382693cbc81b1d131085f52d97879976706f55Anthony Lee        if (listener != null) {
166371382693cbc81b1d131085f52d97879976706f55Anthony Lee            try {
166471382693cbc81b1d131085f52d97879976706f55Anthony Lee                listener.onCallMerged(ImsCall.this);
166571382693cbc81b1d131085f52d97879976706f55Anthony Lee            } catch (Throwable t) {
166671382693cbc81b1d131085f52d97879976706f55Anthony Lee                loge("callSessionMergeStarted :: ", t);
166771382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
166871382693cbc81b1d131085f52d97879976706f55Anthony Lee        }
166971382693cbc81b1d131085f52d97879976706f55Anthony Lee
167071382693cbc81b1d131085f52d97879976706f55Anthony Lee        return;
167171382693cbc81b1d131085f52d97879976706f55Anthony Lee    }
167271382693cbc81b1d131085f52d97879976706f55Anthony Lee
167371382693cbc81b1d131085f52d97879976706f55Anthony Lee    /**
167471382693cbc81b1d131085f52d97879976706f55Anthony Lee     * We received a callback from ImsCallSession that a merge failed. Clean up all
167571382693cbc81b1d131085f52d97879976706f55Anthony Lee     * internal state to represent this state change.
167671382693cbc81b1d131085f52d97879976706f55Anthony Lee     *
167771382693cbc81b1d131085f52d97879976706f55Anthony Lee     * @param session The {@link ImsCallSession} that is the host of this conference.
167871382693cbc81b1d131085f52d97879976706f55Anthony Lee     * @param reasonInfo The {@link ImsReasonInfo} why the merge failed.
167971382693cbc81b1d131085f52d97879976706f55Anthony Lee     */
168071382693cbc81b1d131085f52d97879976706f55Anthony Lee    private void processMergeFailed(ImsCallSession session, ImsReasonInfo reasonInfo) {
168171382693cbc81b1d131085f52d97879976706f55Anthony Lee        // If mTransientConferenceSession is set, this means that this is a newly created
168271382693cbc81b1d131085f52d97879976706f55Anthony Lee        // conference. Otherwise, we are adding to an existing conference.
168371382693cbc81b1d131085f52d97879976706f55Anthony Lee        ImsCall.Listener listener;
168471382693cbc81b1d131085f52d97879976706f55Anthony Lee        synchronized(ImsCall.this) {
168571382693cbc81b1d131085f52d97879976706f55Anthony Lee            listener = mListener;
168671382693cbc81b1d131085f52d97879976706f55Anthony Lee            // TODO: See if we can use the session param to do some further checks here.
168771382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (mTransientConferenceSession != null) {
168871382693cbc81b1d131085f52d97879976706f55Anthony Lee                // Clean up any work that we performed on the transient session.
168971382693cbc81b1d131085f52d97879976706f55Anthony Lee                mTransientConferenceSession.setListener(null);
169071382693cbc81b1d131085f52d97879976706f55Anthony Lee                mTransientConferenceSession = null;
169171382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
169271382693cbc81b1d131085f52d97879976706f55Anthony Lee            mUpdateRequest = UPDATE_NONE;
169371382693cbc81b1d131085f52d97879976706f55Anthony Lee        }
169471382693cbc81b1d131085f52d97879976706f55Anthony Lee        if (listener != null) {
169571382693cbc81b1d131085f52d97879976706f55Anthony Lee            try {
169671382693cbc81b1d131085f52d97879976706f55Anthony Lee                listener.onCallMergeFailed(ImsCall.this, reasonInfo);
169771382693cbc81b1d131085f52d97879976706f55Anthony Lee            } catch (Throwable t) {
169871382693cbc81b1d131085f52d97879976706f55Anthony Lee                loge("callSessionMergeFailed :: ", t);
169971382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
170071382693cbc81b1d131085f52d97879976706f55Anthony Lee        }
170171382693cbc81b1d131085f52d97879976706f55Anthony Lee        return;
170271382693cbc81b1d131085f52d97879976706f55Anthony Lee    }
170371382693cbc81b1d131085f52d97879976706f55Anthony Lee
1704ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void notifyError(int reason, int statusCode, String message) {
1705ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1706ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1707ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void throwImsException(Throwable t, int code) throws ImsException {
1708ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (t instanceof ImsException) {
1709ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            throw (ImsException) t;
1710ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        } else {
1711ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            throw new ImsException(String.valueOf(code), t, code);
1712ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1713ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1714ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1715ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void log(String s) {
1716ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        Rlog.d(TAG, s);
1717ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1718ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1719ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void loge(String s) {
1720ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        Rlog.e(TAG, s);
1721ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1722ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1723ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void loge(String s, Throwable t) {
1724ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        Rlog.e(TAG, s, t);
1725ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1726ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1727ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private class ImsCallSessionListenerProxy extends ImsCallSession.Listener {
1728ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
172971382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionProgressing(ImsCallSession session, ImsStreamMediaProfile profile) {
173071382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
173171382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionProgressing :: not supported for conference session=" + session);
173271382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
173371382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
173471382693cbc81b1d131085f52d97879976706f55Anthony Lee
1735ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
1736ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("callSessionProgressing :: session=" + session + ", profile=" + profile);
1737ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1738ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1739ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
1740ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1741ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
1742ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
1743ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallProfile.mMediaProfile.copyFrom(profile);
1744ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1745ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1746ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
1747ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
1748ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallProgressing(ImsCall.this);
1749ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
1750ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionProgressing :: ", t);
1751ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1752ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1753ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1754ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1755ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
175671382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionStarted(ImsCallSession session, ImsCallProfile profile) {
175771382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
175871382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionStarted :: not supported for conference session=" + session);
175971382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
176071382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
176171382693cbc81b1d131085f52d97879976706f55Anthony Lee
1762ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
1763ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("callSessionStarted :: session=" + session + ", profile=" + profile);
1764ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1765ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1766ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
1767ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1768ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
1769ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
1770ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallProfile = profile;
1771ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1772ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1773ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
1774ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
1775ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallStarted(ImsCall.this);
1776ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
1777ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionStarted :: ", t);
1778ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1779ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1780ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1781ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1782ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
178371382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionStartFailed(ImsCallSession session, ImsReasonInfo reasonInfo) {
178471382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
178571382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionStartFailed :: not supported for conference session=" + session);
178671382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
178771382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
178871382693cbc81b1d131085f52d97879976706f55Anthony Lee
1789ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
1790ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("callSessionStartFailed :: session=" + session +
1791ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ", reasonInfo=" + reasonInfo);
1792ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1793ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1794ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
1795ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1796ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
1797ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
1798ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mLastReasonInfo = reasonInfo;
1799ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1800ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1801ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
1802ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
1803ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallStartFailed(ImsCall.this, reasonInfo);
1804ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
1805ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionStarted :: ", t);
1806ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1807ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1808ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1809ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1810ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
181171382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionTerminated(ImsCallSession session, ImsReasonInfo reasonInfo) {
181271382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
181371382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionTerminated :: not supported for conference session=" + session);
181471382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
181571382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
181671382693cbc81b1d131085f52d97879976706f55Anthony Lee
1817ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
1818ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("callSessionTerminated :: session=" + session +
1819ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ", reasonInfo=" + reasonInfo);
1820ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1821ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1822ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener = null;
1823ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1824ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
182571382693cbc81b1d131085f52d97879976706f55Anthony Lee                // Let's explicitly handle this situation here...
182671382693cbc81b1d131085f52d97879976706f55Anthony Lee                // The ImsCallSession that has just notified that it was terminated could be in the
182771382693cbc81b1d131085f52d97879976706f55Anthony Lee                // state where it is waiting for a merge to happen. If this is the case, let's just
182871382693cbc81b1d131085f52d97879976706f55Anthony Lee                // assume that the merge is going to succeed but the callbacks are being done in the
182971382693cbc81b1d131085f52d97879976706f55Anthony Lee                // wrong order.  We would expect callSessionMergeComplete() to be called on the
183071382693cbc81b1d131085f52d97879976706f55Anthony Lee                // transient session first and then this call to the original merge() "host".
183171382693cbc81b1d131085f52d97879976706f55Anthony Lee                // If the timing is off, we could be getting this call first.
183271382693cbc81b1d131085f52d97879976706f55Anthony Lee                if (mUpdateRequest == UPDATE_MERGE) {
183371382693cbc81b1d131085f52d97879976706f55Anthony Lee                    if (mTransientConferenceSession != null) {
183471382693cbc81b1d131085f52d97879976706f55Anthony Lee                        log("callSessionTerminated() :: called while waiting for a new conference");
183571382693cbc81b1d131085f52d97879976706f55Anthony Lee                        // Let's assume that the merge will complete and the transient session will,
183671382693cbc81b1d131085f52d97879976706f55Anthony Lee                        // in fact, be our new session soon enough.
183771382693cbc81b1d131085f52d97879976706f55Anthony Lee                        mSession.setListener(null);
183871382693cbc81b1d131085f52d97879976706f55Anthony Lee                        mTransientConferenceSession.setListener(createCallSessionListener());
183971382693cbc81b1d131085f52d97879976706f55Anthony Lee                        mSession = mTransientConferenceSession;
184071382693cbc81b1d131085f52d97879976706f55Anthony Lee                        // At this point, we'll handle this conference call like it was a merge()
184171382693cbc81b1d131085f52d97879976706f55Anthony Lee                        // on an existing conference as opposed to creating a new conference. All
184271382693cbc81b1d131085f52d97879976706f55Anthony Lee                        // properly callbacks should be made.
184371382693cbc81b1d131085f52d97879976706f55Anthony Lee
184471382693cbc81b1d131085f52d97879976706f55Anthony Lee                        // TODO: Do we need to handle the case where the new ImsCallSession still
184571382693cbc81b1d131085f52d97879976706f55Anthony Lee                        // fails to merge after this?  Should be a very unlikely scenario.
184671382693cbc81b1d131085f52d97879976706f55Anthony Lee                        return;
184771382693cbc81b1d131085f52d97879976706f55Anthony Lee                    }
184871382693cbc81b1d131085f52d97879976706f55Anthony Lee                }
184971382693cbc81b1d131085f52d97879976706f55Anthony Lee
1850ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (mCallGroup != null) {
1851ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    notifyConferenceSessionTerminated(reasonInfo);
1852ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } else {
1853ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener = mListener;
1854ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    clear(reasonInfo);
1855ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1856ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1857ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1858ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
1859ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
1860ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallTerminated(ImsCall.this, reasonInfo);
1861ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
1862ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionTerminated :: ", t);
1863ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1864ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1865ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1866ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1867ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
186871382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionHeld(ImsCallSession session, ImsCallProfile profile) {
186971382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
187071382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionHeld :: not supported for conference session=" + session);
187171382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
187271382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
187371382693cbc81b1d131085f52d97879976706f55Anthony Lee
1874ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
1875ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("callSessionHeld :: session=" + session + ", profile=" + profile);
1876ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1877ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1878ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
1879ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1880ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
1881ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallProfile = profile;
1882ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1883ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (mUpdateRequest == UPDATE_HOLD_MERGE) {
1884ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    mergeInternal();
1885ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    return;
1886ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1887ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1888ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
1889ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
1890ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1891ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1892ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
1893ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
1894ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallHeld(ImsCall.this);
1895ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
1896ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionHeld :: ", t);
1897ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1898ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1899111eecc9845826e985c48133b754e453fb3aca84Etan Cohen
1900111eecc9845826e985c48133b754e453fb3aca84Etan Cohen            if (mCallGroup != null) {
1901111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                notifyConferenceStateUpdatedThroughGroupOwner(UPDATE_HOLD);
1902111eecc9845826e985c48133b754e453fb3aca84Etan Cohen            }
1903ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1904ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1905ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
190671382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionHoldFailed(ImsCallSession session, ImsReasonInfo reasonInfo) {
190771382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
190871382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionHoldFailed :: not supported for conference session=" + session);
190971382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
191071382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
191171382693cbc81b1d131085f52d97879976706f55Anthony Lee
1912ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
1913ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("callSessionHoldFailed :: session=" + session +
1914ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ", reasonInfo=" + reasonInfo);
1915ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1916ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1917ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            boolean isHoldForMerge = false;
1918ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
1919ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1920ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
1921ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (mUpdateRequest == UPDATE_HOLD_MERGE) {
1922ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    isHoldForMerge = true;
1923ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1924ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1925ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
1926ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
1927ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1928ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1929ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (isHoldForMerge) {
193071382693cbc81b1d131085f52d97879976706f55Anthony Lee                // Is hold for merge implemented/supported? If so we need to take a close look
193171382693cbc81b1d131085f52d97879976706f55Anthony Lee                // at this workflow to make sure that we handle the case where
193271382693cbc81b1d131085f52d97879976706f55Anthony Lee                // callSessionMergeFailed() does the right thing because we have not actually
193371382693cbc81b1d131085f52d97879976706f55Anthony Lee                // started the merge yet.
1934ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                callSessionMergeFailed(session, reasonInfo);
1935ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return;
1936ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1937ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1938ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
1939ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
1940ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallHoldFailed(ImsCall.this, reasonInfo);
1941ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
1942ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionHoldFailed :: ", t);
1943ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1944ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1945ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1946ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1947ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
194871382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionHoldReceived(ImsCallSession session, ImsCallProfile profile) {
194971382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
195071382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionHoldReceived :: not supported for conference session=" + session);
195171382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
195271382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
195371382693cbc81b1d131085f52d97879976706f55Anthony Lee
1954ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
1955ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("callSessionHoldReceived :: session=" + session + ", profile=" + profile);
1956ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1957ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1958ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
1959ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1960ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
1961ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
1962ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallProfile = profile;
1963ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1964ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1965ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
1966ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
1967ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallHoldReceived(ImsCall.this);
1968ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
1969ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionHoldReceived :: ", t);
1970ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1971ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1972ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1973ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1974ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
197571382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionResumed(ImsCallSession session, ImsCallProfile profile) {
197671382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
197771382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionResumed :: not supported for conference session=" + session);
197871382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
197971382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
198071382693cbc81b1d131085f52d97879976706f55Anthony Lee
1981ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
1982ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("callSessionResumed :: session=" + session + ", profile=" + profile);
1983ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1984ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1985ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
1986ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1987ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
1988ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
1989ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallProfile = profile;
1990ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
1991ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1992ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1993ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
1994ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
1995ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallResumed(ImsCall.this);
1996ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
1997ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionResumed :: ", t);
1998ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1999ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2000111eecc9845826e985c48133b754e453fb3aca84Etan Cohen
2001111eecc9845826e985c48133b754e453fb3aca84Etan Cohen            if (mCallGroup != null) {
2002111eecc9845826e985c48133b754e453fb3aca84Etan Cohen                notifyConferenceStateUpdatedThroughGroupOwner(UPDATE_RESUME);
2003111eecc9845826e985c48133b754e453fb3aca84Etan Cohen            }
2004ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2005ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2006ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
200771382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionResumeFailed(ImsCallSession session, ImsReasonInfo reasonInfo) {
200871382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
200971382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionResumeFailed :: not supported for conference session=" + session);
201071382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
201171382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
201271382693cbc81b1d131085f52d97879976706f55Anthony Lee
2013ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
2014ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("callSessionResumeFailed :: session=" + session +
2015ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ", reasonInfo=" + reasonInfo);
2016ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2017ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2018ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2019ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2020ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2021ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2022ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2023ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2024ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2025ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2026ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2027ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallResumeFailed(ImsCall.this, reasonInfo);
2028ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2029ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionResumeFailed :: ", t);
2030ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2031ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2032ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2033ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2034ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
203571382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionResumeReceived(ImsCallSession session, ImsCallProfile profile) {
203671382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
203771382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionResumeReceived :: not supported for conference session=" + session);
203871382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
203971382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
204071382693cbc81b1d131085f52d97879976706f55Anthony Lee
2041ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
2042ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("callSessionResumeReceived :: session=" + session +
2043ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ", profile=" + profile);
2044ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2045ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2046ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2047ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2048ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2049ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2050ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallProfile = profile;
2051ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2052ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2053ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2054ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2055ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallResumeReceived(ImsCall.this);
2056ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2057ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionResumeReceived :: ", t);
2058ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2059ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2060ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2061ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2062ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
20633f2b0aaa277545886571cbf90fc90fd5d304e714Tyler Gunn        public void callSessionMergeStarted(ImsCallSession session,
2064ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsCallSession newSession, ImsCallProfile profile) {
2065ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
206671382693cbc81b1d131085f52d97879976706f55Anthony Lee                String sessionString = newSession == null ? "null" : newSession.toString();
206771382693cbc81b1d131085f52d97879976706f55Anthony Lee                String newSessionString = newSession == null ? "null" : newSession.toString();
206871382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionMergeStarted :: session=" + sessionString
206971382693cbc81b1d131085f52d97879976706f55Anthony Lee                        + ", newSession=" + newSessionString + ", profile=" + profile);
2070ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2071ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
207271382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (mUpdateRequest != UPDATE_MERGE) {
207371382693cbc81b1d131085f52d97879976706f55Anthony Lee                // Odd, we are not in the midst of merging anything.
207471382693cbc81b1d131085f52d97879976706f55Anthony Lee                if (DBG) {
207571382693cbc81b1d131085f52d97879976706f55Anthony Lee                    log("callSessionMergeStarted :: no merge in progress.");
207671382693cbc81b1d131085f52d97879976706f55Anthony Lee                }
2077ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return;
2078ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2079ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
208071382693cbc81b1d131085f52d97879976706f55Anthony Lee            // There are 2 ways that we can go here.  If the session that supplied the params
208171382693cbc81b1d131085f52d97879976706f55Anthony Lee            // is not null, then it is the new session that represents the new conference
208271382693cbc81b1d131085f52d97879976706f55Anthony Lee            // if the merge succeeds. If it is null, the merge is happening on our current
208371382693cbc81b1d131085f52d97879976706f55Anthony Lee            // ImsCallSession.
208471382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (session == null) {
208571382693cbc81b1d131085f52d97879976706f55Anthony Lee                // Everything is already set up and we just need to make sure
208671382693cbc81b1d131085f52d97879976706f55Anthony Lee                // that we properly respond to all the future callbacks about
208771382693cbc81b1d131085f52d97879976706f55Anthony Lee                // this merge.
208871382693cbc81b1d131085f52d97879976706f55Anthony Lee                if (DBG) {
208971382693cbc81b1d131085f52d97879976706f55Anthony Lee                    log("callSessionMergeStarted :: merging into existing ImsCallSession");
209071382693cbc81b1d131085f52d97879976706f55Anthony Lee                }
209171382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
209271382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
2093ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
209471382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (DBG) {
209571382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionMergeStarted ::  setting our transient ImsCallSession");
2096ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2097ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
209871382693cbc81b1d131085f52d97879976706f55Anthony Lee            // If we are here, this means that we are creating a new conference and
209971382693cbc81b1d131085f52d97879976706f55Anthony Lee            // we need to do some extra work around managing a new ImsCallSession that
210071382693cbc81b1d131085f52d97879976706f55Anthony Lee            // could represent our new ImsCallSession if the merge succeeds.
210171382693cbc81b1d131085f52d97879976706f55Anthony Lee            synchronized(ImsCall.this) {
210271382693cbc81b1d131085f52d97879976706f55Anthony Lee                // Keep track of this session for future callbacks to indicate success
210371382693cbc81b1d131085f52d97879976706f55Anthony Lee                // or failure of this merge.
210471382693cbc81b1d131085f52d97879976706f55Anthony Lee                mTransientConferenceSession = newSession;
210571382693cbc81b1d131085f52d97879976706f55Anthony Lee                mTransientConferenceSession.setListener(createCallSessionListener());
2106ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
210771382693cbc81b1d131085f52d97879976706f55Anthony Lee
210871382693cbc81b1d131085f52d97879976706f55Anthony Lee            // STOPSHIP: For now, let's force the complete callback since it is not coming
210971382693cbc81b1d131085f52d97879976706f55Anthony Lee            // from the vendor layer as of when this code was written.
211071382693cbc81b1d131085f52d97879976706f55Anthony Lee            log("callSessionMergeStarted ::  forcing a success callback");
211171382693cbc81b1d131085f52d97879976706f55Anthony Lee            callSessionMergeComplete(mTransientConferenceSession);
211271382693cbc81b1d131085f52d97879976706f55Anthony Lee
211371382693cbc81b1d131085f52d97879976706f55Anthony Lee            return;
2114ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2115ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2116ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
21173f2b0aaa277545886571cbf90fc90fd5d304e714Tyler Gunn        public void callSessionMergeComplete(ImsCallSession session) {
21183f2b0aaa277545886571cbf90fc90fd5d304e714Tyler Gunn            if (DBG) {
211971382693cbc81b1d131085f52d97879976706f55Anthony Lee                String sessionString = session == null ? "null" : session.toString();
212071382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionMergeComplete :: session=" + sessionString);
21213f2b0aaa277545886571cbf90fc90fd5d304e714Tyler Gunn            }
212271382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (mUpdateRequest != UPDATE_MERGE) {
212371382693cbc81b1d131085f52d97879976706f55Anthony Lee                // Odd, we are not in the midst of merging anything.
212471382693cbc81b1d131085f52d97879976706f55Anthony Lee                if (DBG) {
212571382693cbc81b1d131085f52d97879976706f55Anthony Lee                    log("callSessionMergeComplete :: no merge in progress.");
212671382693cbc81b1d131085f52d97879976706f55Anthony Lee                }
212771382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
212871382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
212971382693cbc81b1d131085f52d97879976706f55Anthony Lee            // Let's let our parent ImsCall now that we received notification that
213071382693cbc81b1d131085f52d97879976706f55Anthony Lee            // the merge was completed so we can set up our internal state properly
213171382693cbc81b1d131085f52d97879976706f55Anthony Lee            processMergeComplete(session);
21323f2b0aaa277545886571cbf90fc90fd5d304e714Tyler Gunn        }
21333f2b0aaa277545886571cbf90fc90fd5d304e714Tyler Gunn
21343f2b0aaa277545886571cbf90fc90fd5d304e714Tyler Gunn        @Override
213571382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionMergeFailed(ImsCallSession session, ImsReasonInfo reasonInfo) {
2136ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
213771382693cbc81b1d131085f52d97879976706f55Anthony Lee                String sessionString = session == null? "null" : session.toString();
213871382693cbc81b1d131085f52d97879976706f55Anthony Lee                String reasonInfoString = reasonInfo == null ? "null" : reasonInfo.toString();
213971382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionMergeFailed :: session=" + sessionString +
214071382693cbc81b1d131085f52d97879976706f55Anthony Lee                        ", reasonInfo=" + reasonInfoString);
2141ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
214271382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (mUpdateRequest != UPDATE_MERGE) {
214371382693cbc81b1d131085f52d97879976706f55Anthony Lee                // Odd, we are not in the midst of merging anything.
214471382693cbc81b1d131085f52d97879976706f55Anthony Lee                if (DBG) {
214571382693cbc81b1d131085f52d97879976706f55Anthony Lee                    log("callSessionMergeFailed :: no merge in progress.");
2146ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
214771382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
2148ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
214971382693cbc81b1d131085f52d97879976706f55Anthony Lee            // Let's tell our parent ImsCall that the merge has failed and we need to clean
215071382693cbc81b1d131085f52d97879976706f55Anthony Lee            // up any temporary, transient state.
215171382693cbc81b1d131085f52d97879976706f55Anthony Lee            processMergeFailed(session, reasonInfo);
2152ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2153ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2154ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
215571382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionUpdated(ImsCallSession session, ImsCallProfile profile) {
215671382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
215771382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionUpdated :: not supported for conference session=" + session);
215871382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
215971382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
216071382693cbc81b1d131085f52d97879976706f55Anthony Lee
2161ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
2162ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("callSessionUpdated :: session=" + session + ", profile=" + profile);
2163ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2164ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2165ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2166ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2167ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2168ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2169ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallProfile = profile;
2170ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2171ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2172ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2173ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2174ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2175ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallUpdated(ImsCall.this);
2176ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2177ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionUpdated :: ", t);
2178ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2179ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2180ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2181ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2182ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
218371382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionUpdateFailed(ImsCallSession session, ImsReasonInfo reasonInfo) {
218471382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
218571382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionUpdateFailed :: not supported for conference session=" + session);
218671382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
218771382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
218871382693cbc81b1d131085f52d97879976706f55Anthony Lee
2189ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
2190ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("callSessionUpdateFailed :: session=" + session +
2191ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ", reasonInfo=" + reasonInfo);
2192ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2193ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2194ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2195ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2196ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2197ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2198ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2199ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2200ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2201ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2202ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2203ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallUpdateFailed(ImsCall.this, reasonInfo);
2204ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2205ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionUpdateFailed :: ", t);
2206ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2207ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2208ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2209ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2210ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
221171382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionUpdateReceived(ImsCallSession session, ImsCallProfile profile) {
221271382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
221371382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionUpdateReceived :: not supported for conference session=" + session);
221471382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
221571382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
221671382693cbc81b1d131085f52d97879976706f55Anthony Lee
2217ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
2218ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("callSessionUpdateReceived :: session=" + session +
2219ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ", profile=" + profile);
2220ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2221ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2222ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2223ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2224ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2225ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2226ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mProposedCallProfile = profile;
2227ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_UNSPECIFIED;
2228ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2229ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2230ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2231ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2232ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallUpdateReceived(ImsCall.this);
2233ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2234ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionUpdateReceived :: ", t);
2235ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2236ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2237ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2238ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2239ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
224071382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionConferenceExtended(ImsCallSession session, ImsCallSession newSession,
224171382693cbc81b1d131085f52d97879976706f55Anthony Lee                ImsCallProfile profile) {
224271382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
224371382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionConferenceExtended :: not supported for conference session=" +
224471382693cbc81b1d131085f52d97879976706f55Anthony Lee                        session);
224571382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
224671382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
224771382693cbc81b1d131085f52d97879976706f55Anthony Lee
2248ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
2249ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("callSessionConferenceExtended :: session=" + session
2250ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        + ", newSession=" + newSession + ", profile=" + profile);
2251ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2252ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2253ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall newCall = createNewCall(newSession, profile);
2254ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2255ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (newCall == null) {
2256ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                callSessionConferenceExtendFailed(session, new ImsReasonInfo());
2257ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return;
2258ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2259ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2260ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2261ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2262ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2263ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2264ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2265ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2266ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2267ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2268ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2269ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallConferenceExtended(ImsCall.this, newCall);
2270ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2271ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionConferenceExtended :: ", t);
2272ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2273ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2274ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2275ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2276ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2277ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionConferenceExtendFailed(ImsCallSession session,
2278ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsReasonInfo reasonInfo) {
227971382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
228071382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionConferenceExtendFailed :: not supported for conference session=" +
228171382693cbc81b1d131085f52d97879976706f55Anthony Lee                        session);
228271382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
228371382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
228471382693cbc81b1d131085f52d97879976706f55Anthony Lee
2285ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
2286ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("callSessionConferenceExtendFailed :: session=" + session +
2287ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ", reasonInfo=" + reasonInfo);
2288ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2289ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2290ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2291ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2292ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2293ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2294ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2295ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2296ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2297ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2298ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2299ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallConferenceExtendFailed(ImsCall.this, reasonInfo);
2300ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2301ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionConferenceExtendFailed :: ", t);
2302ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2303ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2304ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2305ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2306ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2307ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionConferenceExtendReceived(ImsCallSession session,
2308ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsCallSession newSession, ImsCallProfile profile) {
230971382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
231071382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionConferenceExtendReceived :: not supported for conference session=" +
231171382693cbc81b1d131085f52d97879976706f55Anthony Lee                        session);
231271382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
231371382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
231471382693cbc81b1d131085f52d97879976706f55Anthony Lee
2315ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
2316ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("callSessionConferenceExtendReceived :: session=" + session
2317ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        + ", newSession=" + newSession + ", profile=" + profile);
2318ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2319ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2320ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall newCall = createNewCall(newSession, profile);
2321ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2322ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (newCall == null) {
2323ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                // Should all the calls be terminated...???
2324ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return;
2325ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2326ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2327ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2328ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2329ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2330ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2331ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2332ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2333ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2334ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2335ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallConferenceExtendReceived(ImsCall.this, newCall);
2336ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2337ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionConferenceExtendReceived :: ", t);
2338ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2339ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2340ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2341ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2342ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2343ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionInviteParticipantsRequestDelivered(ImsCallSession session) {
234471382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
234571382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionInviteParticipantsRequestDelivered :: not supported for " +
234671382693cbc81b1d131085f52d97879976706f55Anthony Lee                        "conference session=" + session);
234771382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
234871382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
234971382693cbc81b1d131085f52d97879976706f55Anthony Lee
2350ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
2351ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("callSessionInviteParticipantsRequestDelivered :: session=" + session);
2352ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2353ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2354ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2355ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2356ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2357ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2358ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2359ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2360ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2361ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2362ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallInviteParticipantsRequestDelivered(ImsCall.this);
2363ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2364ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionInviteParticipantsRequestDelivered :: ", t);
2365ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2366ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2367ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2368ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2369ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2370ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionInviteParticipantsRequestFailed(ImsCallSession session,
2371ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsReasonInfo reasonInfo) {
237271382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
237371382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionInviteParticipantsRequestFailed :: not supported for " +
237471382693cbc81b1d131085f52d97879976706f55Anthony Lee                        "conference session=" + session);
237571382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
237671382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
237771382693cbc81b1d131085f52d97879976706f55Anthony Lee
2378ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
2379ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("callSessionInviteParticipantsRequestFailed :: session=" + session
2380ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        + ", reasonInfo=" + reasonInfo);
2381ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2382ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2383ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2384ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2385ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2386ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2387ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2388ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2389ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2390ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2391ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallInviteParticipantsRequestFailed(ImsCall.this, reasonInfo);
2392ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2393ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionInviteParticipantsRequestFailed :: ", t);
2394ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2395ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2396ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2397ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2398ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2399ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionRemoveParticipantsRequestDelivered(ImsCallSession session) {
240071382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
240171382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionRemoveParticipantsRequestDelivered :: not supported for " +
240271382693cbc81b1d131085f52d97879976706f55Anthony Lee                        "conference session=" + session);
240371382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
240471382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
240571382693cbc81b1d131085f52d97879976706f55Anthony Lee
2406ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
2407ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("callSessionRemoveParticipantsRequestDelivered :: session=" + session);
2408ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2409ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2410ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2411ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2412ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2413ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2414ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2415ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2416ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2417ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2418ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallRemoveParticipantsRequestDelivered(ImsCall.this);
2419ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2420ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionRemoveParticipantsRequestDelivered :: ", t);
2421ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2422ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2423ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2424ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2425ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2426ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionRemoveParticipantsRequestFailed(ImsCallSession session,
2427ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsReasonInfo reasonInfo) {
242871382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
242971382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionRemoveParticipantsRequestFailed :: not supported for " +
243071382693cbc81b1d131085f52d97879976706f55Anthony Lee                        "conference session=" +session);
243171382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
243271382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
243371382693cbc81b1d131085f52d97879976706f55Anthony Lee
2434ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
2435ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("callSessionRemoveParticipantsRequestFailed :: session=" + session
2436ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        + ", reasonInfo=" + reasonInfo);
2437ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2438ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2439ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2440ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2441ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2442ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2443ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2444ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2445ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2446ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2447ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallRemoveParticipantsRequestFailed(ImsCall.this, reasonInfo);
2448ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2449ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionRemoveParticipantsRequestFailed :: ", t);
2450ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2451ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2452ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2453ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2454ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2455ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionConferenceStateUpdated(ImsCallSession session,
2456ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsConferenceState state) {
245771382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
245871382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionConferenceStateUpdated :: not supported for conference session=" +
245971382693cbc81b1d131085f52d97879976706f55Anthony Lee                        session);
246071382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
246171382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
246271382693cbc81b1d131085f52d97879976706f55Anthony Lee
2463ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
2464ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("callSessionConferenceStateUpdated :: session=" + session
2465ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        + ", state=" + state);
2466ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2467ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2468938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn            conferenceStateUpdated(state);
2469ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2470ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2471ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
247271382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionUssdMessageReceived(ImsCallSession session, int mode,
247371382693cbc81b1d131085f52d97879976706f55Anthony Lee                String ussdMessage) {
247471382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
247571382693cbc81b1d131085f52d97879976706f55Anthony Lee                log("callSessionUssdMessageReceived :: not supported for conference session=" +
247671382693cbc81b1d131085f52d97879976706f55Anthony Lee                        session);
247771382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
247871382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
247971382693cbc81b1d131085f52d97879976706f55Anthony Lee
2480ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
2481ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                log("callSessionUssdMessageReceived :: session=" + session
2482ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        + ", mode=" + mode + ", ussdMessage=" + ussdMessage);
2483ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2484ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2485ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2486ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2487ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2488ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2489ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2490ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2491ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2492ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2493ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallUssdMessageReceived(ImsCall.this, mode, ussdMessage);
2494ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2495ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionUssdMessageReceived :: ", t);
2496ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2497ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2498ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2499ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
2500938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn
2501938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn    /**
2502938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     * Report a new conference state to the current {@link ImsCall} and inform listeners of the
2503938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     * change.  Marked as {@code VisibleForTesting} so that the
2504938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     * {@code com.android.internal.telephony.TelephonyTester} class can inject a test conference
2505938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     * event package into a regular ongoing IMS call.
2506938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     *
2507938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     * @param state The {@link ImsConferenceState}.
2508938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     */
2509938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn    @VisibleForTesting
2510938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn    public void conferenceStateUpdated(ImsConferenceState state) {
2511938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn        Listener listener;
2512938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn
2513938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn        synchronized(this) {
2514938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn            notifyConferenceStateUpdated(state);
2515938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn            listener = mListener;
2516938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn        }
2517938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn
2518938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn        if (listener != null) {
2519938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn            try {
2520938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn                listener.onCallConferenceStateUpdated(this, state);
2521938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn            } catch (Throwable t) {
2522938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn                loge("callSessionConferenceStateUpdated :: ", t);
2523938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn            }
2524938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn        }
2525938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn    }
2526ef36ef67e009449300b0150c60c9f637e205d79eWink Saville}
2527