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;
325aec2e957365f20b2e75d3b8c7034e3289729b81Rekha Kumarimport android.telecom.Connection;
3395be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingamimport java.util.Objects;
349bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunnimport android.util.Log;
35ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
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    // Mode of USSD message
49ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public static final int USSD_MODE_NOTIFY = 0;
50ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public static final int USSD_MODE_REQUEST = 1;
51ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
52ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final String TAG = "ImsCall";
536804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
546804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    // This flag is meant to be used as a debugging tool to quickly see all logs
556804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    // regardless of the actual log level set on this component.
566cb99be298f8b1b4363fdacc1cc631c3671380ecTyler Gunn    private static final boolean FORCE_DEBUG = false; /* STOPSHIP if true */
576804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
586804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    // We will log messages guarded by these flags at the info level. If logging is required
596804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    // to occur at (and only at) a particular log level, please use the logd, logv and loge
606804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    // functions as those will not be affected by the value of FORCE_DEBUG at all.
616804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    // Otherwise, anything guarded by these flags will be logged at the info level since that
626804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    // level allows those statements ot be logged by default which supports the workflow of
636804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    // setting FORCE_DEBUG and knowing these logs will show up regardless of the actual log
646804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    // level of this component.
656804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    private static final boolean DBG = FORCE_DEBUG || Log.isLoggable(TAG, Log.DEBUG);
666804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    private static final boolean VDBG = FORCE_DEBUG || Log.isLoggable(TAG, Log.VERBOSE);
676804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    // This is a special flag that is used only to highlight specific log around bringing
686804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    // up and tearing down conference calls. At times, these errors are transient and hard to
696804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    // reproduce so we need to capture this information the first time.
706804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    // TODO: Set this flag to FORCE_DEBUG once the new conference call logic gets more mileage
716804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    // across different IMS implementations.
726804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    private static final boolean CONF_DBG = true;
73ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
74a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam    private List<ConferenceParticipant> mConferenceParticipants;
75ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
76ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Listener for events relating to an IMS call, such as when a call is being
77c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * received ("on ringing") or a call is outgoing ("on calling").
78ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * <p>Many of these events are also received by {@link ImsCallSession.Listener}.</p>
79ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
80ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public static class Listener {
81ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
82ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when a request is sent out to initiate a new call
83ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * and 1xx response is received from the network.
84ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
85ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
86ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
87ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
88ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallProgressing(ImsCall call) {
89ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallStateChanged(call);
90ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
91ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
92ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
93ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call is established.
94ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
95ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
96ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
97ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
98ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallStarted(ImsCall call) {
99ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallStateChanged(call);
100ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
101ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
102ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
103ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call setup is failed.
104ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallError}.
105ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
106ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
107ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the call setup failure
108ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
109ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallStartFailed(ImsCall call, ImsReasonInfo reasonInfo) {
110ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallError(call, reasonInfo);
111ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
112ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
113ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
114ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call is terminated.
115ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
116ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
117ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
118ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the call termination
119ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
120ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallTerminated(ImsCall call, ImsReasonInfo reasonInfo) {
121ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // Store the call termination reason
122ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
123ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallStateChanged(call);
124ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
125ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
126ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
127ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call is in hold.
128ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
129ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
130ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
131ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
132ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallHeld(ImsCall call) {
133ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallStateChanged(call);
134ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
135ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
136ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
137ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call hold is failed.
138ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallError}.
139ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
140ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
141ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the call hold failure
142ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
143ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallHoldFailed(ImsCall call, ImsReasonInfo reasonInfo) {
144ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallError(call, reasonInfo);
145ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
146ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
147ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
148ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call hold is received from the remote user.
149ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
150ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
151ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
152ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
153ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallHoldReceived(ImsCall call) {
154ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallStateChanged(call);
155ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
156ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
157ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
158ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call is in call.
159ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
160ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
161ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
162ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
163ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallResumed(ImsCall call) {
164ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallStateChanged(call);
165ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
166ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
167ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
168ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call resume is failed.
169ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallError}.
170ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
171ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
172ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the call resume failure
173ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
174ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallResumeFailed(ImsCall call, ImsReasonInfo reasonInfo) {
175ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallError(call, reasonInfo);
176ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
177ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
178ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
179ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call resume is received from the remote user.
180ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
181ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
182ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
183ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
184ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallResumeReceived(ImsCall call) {
185ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallStateChanged(call);
186ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
187ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
188ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
189ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call is in call.
190ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
191ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
19295be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam         * @param call the call object that carries out the active IMS call
19395be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam         * @param peerCall the call object that carries out the held IMS call
194047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn         * @param swapCalls {@code true} if the foreground and background calls should be swapped
195047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn         *                              now that the merge has completed.
196ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
19795be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam        public void onCallMerged(ImsCall call, ImsCall peerCall, boolean swapCalls) {
19871382693cbc81b1d131085f52d97879976706f55Anthony Lee            onCallStateChanged(call);
199ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
200ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
201ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
202ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call merge is failed.
203ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallError}.
204ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
205ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
206ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the call merge failure
207ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
208ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallMergeFailed(ImsCall call, ImsReasonInfo reasonInfo) {
209ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallError(call, reasonInfo);
210ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
211ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
212ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
213ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call is updated (except for hold/unhold).
214ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
215ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
216ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
217ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
218ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallUpdated(ImsCall call) {
219ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallStateChanged(call);
220ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
221ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
222ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
223ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call update is failed.
224ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallError}.
225ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
226ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
227ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the call update failure
228ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
229ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallUpdateFailed(ImsCall call, ImsReasonInfo reasonInfo) {
230ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallError(call, reasonInfo);
231ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
232ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
233ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
234ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call update is received from the remote user.
235ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
236ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
237ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
238ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallUpdateReceived(ImsCall call) {
239ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
240ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
241ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
242ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
243ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call is extended to the conference call.
244ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
245ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
246ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
247ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param newCall the call object that is extended to the conference from the active call
248ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
249ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallConferenceExtended(ImsCall call, ImsCall newCall) {
25071382693cbc81b1d131085f52d97879976706f55Anthony Lee            onCallStateChanged(call);
251ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
252ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
253ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
254ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the conference extension is failed.
255ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallError}.
256ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
257ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
258ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the conference extension failure
259ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
260ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallConferenceExtendFailed(ImsCall call,
261ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsReasonInfo reasonInfo) {
262ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallError(call, reasonInfo);
263ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
264ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
265ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
266ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the conference extension is received from the remote user.
267ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
268ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
269ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param newCall the call object that is extended to the conference from the active call
270ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
271ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallConferenceExtendReceived(ImsCall call, ImsCall newCall) {
27271382693cbc81b1d131085f52d97879976706f55Anthony Lee            onCallStateChanged(call);
273ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
274ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
275ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
276ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the invitation request of the participants is delivered to
277ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * the conference server.
278ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
279ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
280ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
281ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallInviteParticipantsRequestDelivered(ImsCall call) {
282ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
283ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
284ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
285ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
286ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the invitation request of the participants is failed.
287ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
288ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
289ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the conference invitation failure
290ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
291ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallInviteParticipantsRequestFailed(ImsCall call,
292ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsReasonInfo reasonInfo) {
293ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
294ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
295ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
296ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
297ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the removal request of the participants is delivered to
298ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * the conference server.
299ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
300ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
301ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
302ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallRemoveParticipantsRequestDelivered(ImsCall call) {
303ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
304ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
305ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
306ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
307ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the removal request of the participants is failed.
308ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
309ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
310ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the conference removal failure
311ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
312ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallRemoveParticipantsRequestFailed(ImsCall call,
313ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsReasonInfo reasonInfo) {
314ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
315ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
316ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
317ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
318ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the conference state is updated.
319ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
320ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
321ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param state state of the participant who is participated in the conference call
322ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
323ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallConferenceStateUpdated(ImsCall call, ImsConferenceState state) {
324ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
325ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
326ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
327ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
3281c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn         * Called when the state of IMS conference participant(s) has changed.
3295965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn         *
3305965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn         * @param call the call object that carries out the IMS call.
3311c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn         * @param participants the participant(s) and their new state information.
3325965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn         */
3331c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn        public void onConferenceParticipantsStateChanged(ImsCall call,
3341c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn                List<ConferenceParticipant> participants) {
3355965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn            // no-op
3365965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn        }
3375965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn
3385965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn        /**
339ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the USSD message is received from the network.
340ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
341ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param mode mode of the USSD message (REQUEST / NOTIFY)
342ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param ussdMessage USSD message
343ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
344ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallUssdMessageReceived(ImsCall call,
345ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                int mode, String ussdMessage) {
346ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
347ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
348ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
349ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
350ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when an error occurs. The default implementation is no op.
351ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * overridden. The default implementation is no op. Error events are
352ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * not re-directed to this callback and are handled in {@link #onCallError}.
353ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
354ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
355ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of this error
356ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @see ImsReasonInfo
357ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
358ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallError(ImsCall call, ImsReasonInfo reasonInfo) {
359ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
360ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
361ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
362ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
363ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when an event occurs and the corresponding callback is not
364ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * overridden. The default implementation is no op. Error events are
365ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * not re-directed to this callback and are handled in {@link #onCallError}.
366ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
367ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
368ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
369ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallStateChanged(ImsCall call) {
370ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
371ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
372ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
373ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
374ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call moves the hold state to the conversation state.
375ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * For example, when merging the active & hold call, the state of all the hold call
376ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * will be changed from hold state to conversation state.
377ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * This callback method can be invoked even though the application does not trigger
378ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * any operations.
379ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
380ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
381ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param state the detailed state of call state changes;
382ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *      Refer to CALL_STATE_* in {@link ImsCall}
383ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
384ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallStateChanged(ImsCall call, int state) {
385ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
386ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
387a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak
388a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak        /**
389d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh         * Called when the call supp service is received
390d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh         * The default implementation calls {@link #onCallStateChanged}.
391d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh         *
392d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh         * @param call the call object that carries out the IMS call
393d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh         */
394d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh        public void onCallSuppServiceReceived(ImsCall call,
395d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh            ImsSuppServiceNotification suppServiceInfo) {
396d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh        }
397d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh
398d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh        /**
399a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak         * Called when TTY mode of remote party changed
400a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak         *
401a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak         * @param call the call object that carries out the IMS call
402a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak         * @param mode TTY mode of remote party
403a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak         */
404a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak        public void onCallSessionTtyModeReceived(ImsCall call, int mode) {
405a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak            // no-op
406a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak        }
4071463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar
4081463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar        /**
4091463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         * Called when handover occurs from one access technology to another.
4101463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         *
4116804851b58264d7e82b09a845118d24d36c8d831Anthony Lee         * @param imsCall ImsCall object
4121463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         * @param srcAccessTech original access technology
4131463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         * @param targetAccessTech new access technology
4141463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         * @param reasonInfo
4151463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         */
4161463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar        public void onCallHandover(ImsCall imsCall, int srcAccessTech, int targetAccessTech,
4171463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            ImsReasonInfo reasonInfo) {
4181463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar        }
4191463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar
4201463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar        /**
4211463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         * Called when handover from one access technology to another fails.
4221463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         *
4236804851b58264d7e82b09a845118d24d36c8d831Anthony Lee         * @param imsCall call that failed the handover.
4241463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         * @param srcAccessTech original access technology
4251463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         * @param targetAccessTech new access technology
4261463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         * @param reasonInfo
4271463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         */
4281463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar        public void onCallHandoverFailed(ImsCall imsCall, int srcAccessTech, int targetAccessTech,
4291463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            ImsReasonInfo reasonInfo) {
4301463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar        }
43125394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn
43225394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn        /**
43325394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn         * Notifies of a change to the multiparty state for this {@code ImsCall}.
43425394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn         *
43525394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn         * @param imsCall The IMS call.
43625394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn         * @param isMultiParty {@code true} if the call became multiparty, {@code false}
43725394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn         *      otherwise.
43825394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn         */
43925394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn        public void onMultipartyStateChanged(ImsCall imsCall, boolean isMultiParty) {
44025394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn        }
441ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
442ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
443ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // List of update operation for IMS call control
444ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_NONE = 0;
445ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_HOLD = 1;
446ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_HOLD_MERGE = 2;
447ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_RESUME = 3;
448ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_MERGE = 4;
449ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_EXTEND_TO_CONFERENCE = 5;
450ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_UNSPECIFIED = 6;
451ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
452ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // For synchronization of private variables
453ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private Object mLockObj = new Object();
454ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private Context mContext;
455ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
456ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // true if the call is established & in the conversation state
457ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private boolean mInCall = false;
458ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // true if the call is on hold
459ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // If it is triggered by the local, mute the call. Otherwise, play local hold tone
460ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // or network generated media.
461ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private boolean mHold = false;
462ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // true if the call is on mute
463ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private boolean mMute = false;
464ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // It contains the exclusive call update request. Refer to UPDATE_*.
465ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private int mUpdateRequest = UPDATE_NONE;
466ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
467ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsCall.Listener mListener = null;
4689bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
4699bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    // When merging two calls together, the "peer" call that will merge into this call.
4709bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    private ImsCall mMergePeer = null;
4719bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    // When merging two calls together, the "host" call we are merging into.
4729bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    private ImsCall mMergeHost = null;
473ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
47495be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam    // True if Conference request was initiated by
47595be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam    // Foreground Conference call else it will be false
47695be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam    private boolean mMergeRequestedByConference = false;
477ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // Wrapper call session to interworking the IMS service (server).
478ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsCallSession mSession = null;
479ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // Call profile of the current session.
480ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // It can be changed at anytime when the call is updated.
481ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsCallProfile mCallProfile = null;
482ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // Call profile to be updated after the application's action (accept/reject)
483ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // to the call update. After the application's action (accept/reject) is done,
484ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // it will be set to null.
485ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsCallProfile mProposedCallProfile = null;
486ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsReasonInfo mLastReasonInfo = null;
487ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
488ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // Media session to control media (audio/video) operations for an IMS call
489ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsStreamMediaSession mMediaSession = null;
490ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
491b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // The temporary ImsCallSession that could represent the merged call once
492b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // we receive notification that the merge was successful.
49371382693cbc81b1d131085f52d97879976706f55Anthony Lee    private ImsCallSession mTransientConferenceSession = null;
494b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // While a merge is progressing, we bury any session termination requests
495b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // made on the original ImsCallSession until we have closure on the merge request
496b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // If the request ultimately fails, we need to act on the termination request
497b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // that we buried temporarily. We do this because we feel that timing issues could
498b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // cause the termination request to occur just because the merge is succeeding.
499b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    private boolean mSessionEndDuringMerge = false;
500b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // Just like mSessionEndDuringMerge, we need to keep track of the reason why the
501b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // termination request was made on the original session in case we need to act
502b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // on it in the case of a merge failure.
503b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    private ImsReasonInfo mSessionEndDuringMergeReasonInfo = null;
504c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    // This flag is used to indicate if this ImsCall was merged into a conference
505c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    // or not.  It is used primarily to determine if a disconnect sound should
506c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    // be heard when the call is terminated.
5078ae59492156d9cef275f559c5ee09a44315989beAndrew Lee    private boolean mIsMerged = false;
508c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    // If true, this flag means that this ImsCall is in the process of merging
509c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    // into a conference but it does not yet have closure on if it was
510c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    // actually added to the conference or not. false implies that it either
511c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    // is not part of a merging conference or already knows if it was
512c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    // successfully added.
513047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    private boolean mCallSessionMergePending = false;
514047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
515ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
51695d563ed2a215d67a4f789c3ebb5a526fb95cc7fTyler Gunn     * If {@code true}, this flag indicates that a request to terminate the call was made by
51795d563ed2a215d67a4f789c3ebb5a526fb95cc7fTyler Gunn     * Telephony (could be from the user or some internal telephony logic)
51895d563ed2a215d67a4f789c3ebb5a526fb95cc7fTyler Gunn     * and that when we receive a {@link #processCallTerminated(ImsReasonInfo)} callback from the
51995d563ed2a215d67a4f789c3ebb5a526fb95cc7fTyler Gunn     * radio indicating that the call was terminated, we should override any burying of the
52095d563ed2a215d67a4f789c3ebb5a526fb95cc7fTyler Gunn     * termination due to an ongoing conference merge.
52195d563ed2a215d67a4f789c3ebb5a526fb95cc7fTyler Gunn     */
52295d563ed2a215d67a4f789c3ebb5a526fb95cc7fTyler Gunn    private boolean mTerminationRequestPending = false;
52395d563ed2a215d67a4f789c3ebb5a526fb95cc7fTyler Gunn
52495d563ed2a215d67a4f789c3ebb5a526fb95cc7fTyler Gunn    /**
52525394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn     * For multi-party IMS calls (e.g. conferences), determines if this {@link ImsCall} is the one
52625394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn     * hosting the call.  This is used to distinguish between a situation where an {@link ImsCall}
52725394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn     * is {@link #isMultiparty()} because calls were merged on the device, and a situation where
52825394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn     * an {@link ImsCall} is {@link #isMultiparty()} because it is a member of a conference started
52925394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn     * on another device.
53025394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn     * <p>
53125394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn     * When {@code true}, this {@link ImsCall} is is the origin of the conference call.
53225394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn     * When {@code false}, this {@link ImsCall} is a member of a conference started on another
53325394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn     * device.
53425394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn     */
53525394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn    private boolean mIsConferenceHost = false;
53625394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn
53725394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn    /**
538ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Create an IMS call object.
539ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
540ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param context the context for accessing system services
541ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param profile the call profile to make/take a call
542ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
543ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsCall(Context context, ImsCallProfile profile) {
544ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mContext = context;
545ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mCallProfile = profile;
546ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
547ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
548ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
549ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Closes this object. This object is not usable after being closed.
550ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
551ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    @Override
552ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void close() {
553ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
554ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession != null) {
555ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mSession.close();
556ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mSession = null;
55795be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam            } else {
55895be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                logi("close :: Cannot close Null call session!");
559ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
560ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
561ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mCallProfile = null;
562ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mProposedCallProfile = null;
563ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mLastReasonInfo = null;
564ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mMediaSession = null;
565ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
566ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
567ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
568ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
569ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Checks if the call has a same remote user identity or not.
570ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
571ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param userId the remote user identity
572ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return true if the remote user identity is equal; otherwise, false
573ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
574ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    @Override
575ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public boolean checkIfRemoteUserIsSame(String userId) {
576ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (userId == null) {
577ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return false;
578ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
579ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
580ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        return userId.equals(mCallProfile.getCallExtra(ImsCallProfile.EXTRA_REMOTE_URI, ""));
581ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
582ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
583ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
584ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Checks if the call is equal or not.
585ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
586ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param call the call to be compared
587ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return true if the call is equal; otherwise, false
588ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
589ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    @Override
590ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public boolean equalsTo(ICall call) {
591ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (call == null) {
592ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return false;
593ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
594ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
595ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (call instanceof ImsCall) {
59616b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen            return this.equals(call);
597ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
598ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
599ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        return false;
600ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
601ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
602c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    public static boolean isSessionAlive(ImsCallSession session) {
603c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        return session != null && session.isAlive();
604c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    }
605c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
606ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
607ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the negotiated (local & remote) call profile.
608ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
609ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return a {@link ImsCallProfile} object that has the negotiated call profile
610ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
611ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsCallProfile getCallProfile() {
612ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
613ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mCallProfile;
614ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
615ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
616ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
617ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
618ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the local call profile (local capabilities).
619ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
620ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return a {@link ImsCallProfile} object that has the local call profile
621ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
622ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsCallProfile getLocalCallProfile() throws ImsException {
623ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
624ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
625ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
626ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
627ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
628ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
629ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            try {
630ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return mSession.getLocalCallProfile();
631ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } catch (Throwable t) {
632ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("getLocalCallProfile :: ", t);
633ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("getLocalCallProfile()", t, 0);
634ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
635ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
636ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
637ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
638ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
639e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh     * Gets the remote call profile (remote capabilities).
640e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh     *
641e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh     * @return a {@link ImsCallProfile} object that has the remote call profile
642e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh     */
643e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh    public ImsCallProfile getRemoteCallProfile() throws ImsException {
644e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh        synchronized(mLockObj) {
645e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh            if (mSession == null) {
646e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh                throw new ImsException("No call session",
647e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
648e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh            }
649e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh
650e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh            try {
651e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh                return mSession.getRemoteCallProfile();
652e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh            } catch (Throwable t) {
653e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh                loge("getRemoteCallProfile :: ", t);
654e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh                throw new ImsException("getRemoteCallProfile()", t, 0);
655e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh            }
656e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh        }
657e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh    }
658e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh
659e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh    /**
660ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the call profile proposed by the local/remote user.
661ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
662ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return a {@link ImsCallProfile} object that has the proposed call profile
663ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
664ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsCallProfile getProposedCallProfile() {
665ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
666ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (!isInCall()) {
667ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return null;
668ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
669ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
670ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mProposedCallProfile;
671ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
672ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
673ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
674ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
675a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam     * Gets the list of conference participants currently
676a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam     * associated with this call.
677a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam     *
678a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam     * @return The list of conference participants.
679a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam     */
680a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam    public List<ConferenceParticipant> getConferenceParticipants() {
681a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam        synchronized(mLockObj) {
682a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam            logi("getConferenceParticipants :: mConferenceParticipants"
683a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam                    + mConferenceParticipants);
684a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam            return mConferenceParticipants;
685a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam        }
686a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam    }
687a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam
688a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam    /**
689ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the state of the {@link ImsCallSession} that carries this call.
690ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * The value returned must be one of the states in {@link ImsCallSession#State}.
691ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
692ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return the session state
693ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
694ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public int getState() {
695ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
696ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
697ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return ImsCallSession.State.IDLE;
698ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
699ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
700ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mSession.getState();
701ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
702ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
703ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
704ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
705ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the {@link ImsCallSession} that carries this call.
706ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
707ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return the session object that carries this call
708ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @hide
709ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
710ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsCallSession getCallSession() {
711ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
712ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mSession;
713ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
714ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
715ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
716ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
717ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the {@link ImsStreamMediaSession} that handles the media operation of this call.
718ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Almost interface APIs are for the VT (Video Telephony).
719ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
720ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return the media session object that handles the media operation of this call
721ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @hide
722ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
723ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsStreamMediaSession getMediaSession() {
724ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
725ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mMediaSession;
726ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
727ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
728ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
729ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
730ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the specified property of this call.
731ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
732ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param name key to get the extra call information defined in {@link ImsCallProfile}
733ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return the extra call information as string
734ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
735ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public String getCallExtra(String name) throws ImsException {
736ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        // Lookup the cache
737ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
738ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
739ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // If not found, try to get the property from the remote
740ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
741ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
742ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
743ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
744ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
745ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            try {
746ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return mSession.getProperty(name);
747ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } catch (Throwable t) {
748ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("getCallExtra :: ", t);
749ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("getCallExtra()", t, 0);
750ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
751ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
752ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
753ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
754ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
755ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the last reason information when the call is not established, cancelled or terminated.
756ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
757ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return the last reason information
758ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
759ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsReasonInfo getLastReasonInfo() {
760ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
761ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mLastReasonInfo;
762ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
763ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
764ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
765ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
766ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Checks if the call has a pending update operation.
767ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
768ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return true if the call has a pending update operation
769ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
770ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public boolean hasPendingUpdate() {
771ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
772ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return (mUpdateRequest != UPDATE_NONE);
773ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
774ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
775ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
776ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
7776c0b0d0e83b8d06f40ec814573adc69f362704a9Tyler Gunn     * Checks if the call is pending a hold operation.
7786c0b0d0e83b8d06f40ec814573adc69f362704a9Tyler Gunn     *
7796c0b0d0e83b8d06f40ec814573adc69f362704a9Tyler Gunn     * @return true if the call is pending a hold operation.
7806c0b0d0e83b8d06f40ec814573adc69f362704a9Tyler Gunn     */
7816c0b0d0e83b8d06f40ec814573adc69f362704a9Tyler Gunn    public boolean isPendingHold() {
7826c0b0d0e83b8d06f40ec814573adc69f362704a9Tyler Gunn        synchronized(mLockObj) {
7836c0b0d0e83b8d06f40ec814573adc69f362704a9Tyler Gunn            return (mUpdateRequest == UPDATE_HOLD);
7846c0b0d0e83b8d06f40ec814573adc69f362704a9Tyler Gunn        }
7856c0b0d0e83b8d06f40ec814573adc69f362704a9Tyler Gunn    }
7866c0b0d0e83b8d06f40ec814573adc69f362704a9Tyler Gunn
7876c0b0d0e83b8d06f40ec814573adc69f362704a9Tyler Gunn    /**
788ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Checks if the call is established.
789ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
790ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return true if the call is established
791ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
792ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public boolean isInCall() {
793ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
794ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mInCall;
795ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
796ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
797ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
798ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
799ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Checks if the call is muted.
800ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
801ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return true if the call is muted
802ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
803ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public boolean isMuted() {
804ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
805ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mMute;
806ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
807ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
808ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
809ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
810ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Checks if the call is on hold.
811ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
812ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return true if the call is on hold
813ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
814ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public boolean isOnHold() {
815ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
816ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mHold;
817ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
818ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
819ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
820ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
821725ad373383798c1516348475b1f6304484e031eTyler Gunn     * Determines if the call is a multiparty call.
822725ad373383798c1516348475b1f6304484e031eTyler Gunn     *
823725ad373383798c1516348475b1f6304484e031eTyler Gunn     * @return {@code True} if the call is a multiparty call.
824725ad373383798c1516348475b1f6304484e031eTyler Gunn     */
825725ad373383798c1516348475b1f6304484e031eTyler Gunn    public boolean isMultiparty() {
82616b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen        synchronized(mLockObj) {
82716b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen            if (mSession == null) {
82816b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen                return false;
82916b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen            }
83016b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen
83171382693cbc81b1d131085f52d97879976706f55Anthony Lee            return mSession.isMultiparty();
83216b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen        }
833725ad373383798c1516348475b1f6304484e031eTyler Gunn    }
834725ad373383798c1516348475b1f6304484e031eTyler Gunn
835725ad373383798c1516348475b1f6304484e031eTyler Gunn    /**
83625394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn     * Where {@link #isMultiparty()} is {@code true}, determines if this {@link ImsCall} is the
83725394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn     * origin of the conference call (i.e. {@code #isConferenceHost()} is {@code true}), or if this
83825394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn     * {@link ImsCall} is a member of a conference hosted on another device.
83925394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn     *
84025394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn     * @return {@code true} if this call is the origin of the conference call it is a member of,
84125394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn     *      {@code false} otherwise.
84225394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn     */
84325394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn    public boolean isConferenceHost() {
84425394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn        synchronized(mLockObj) {
84525394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn            return isMultiparty() && mIsConferenceHost;
84625394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn        }
84725394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn    }
84825394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn
84925394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn    /**
8509bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * Marks whether an IMS call is merged. This should be set {@code true} when the call merges
8519bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * into a conference.
8528ae59492156d9cef275f559c5ee09a44315989beAndrew Lee     *
8538ae59492156d9cef275f559c5ee09a44315989beAndrew Lee     * @param isMerged Whether the call is merged.
8548ae59492156d9cef275f559c5ee09a44315989beAndrew Lee     */
8558ae59492156d9cef275f559c5ee09a44315989beAndrew Lee    public void setIsMerged(boolean isMerged) {
8568ae59492156d9cef275f559c5ee09a44315989beAndrew Lee        mIsMerged = isMerged;
8578ae59492156d9cef275f559c5ee09a44315989beAndrew Lee    }
8588ae59492156d9cef275f559c5ee09a44315989beAndrew Lee
8598ae59492156d9cef275f559c5ee09a44315989beAndrew Lee    /**
8609bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * @return {@code true} if the call recently merged into a conference call.
8618ae59492156d9cef275f559c5ee09a44315989beAndrew Lee     */
8628ae59492156d9cef275f559c5ee09a44315989beAndrew Lee    public boolean isMerged() {
8638ae59492156d9cef275f559c5ee09a44315989beAndrew Lee        return mIsMerged;
8648ae59492156d9cef275f559c5ee09a44315989beAndrew Lee    }
8658ae59492156d9cef275f559c5ee09a44315989beAndrew Lee
8668ae59492156d9cef275f559c5ee09a44315989beAndrew Lee    /**
867ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Sets the listener to listen to the IMS call events.
868ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * The method calls {@link #setListener setListener(listener, false)}.
869ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
870ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param listener to listen to the IMS call events of this object; null to remove listener
871ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see #setListener(Listener, boolean)
872ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
873ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void setListener(ImsCall.Listener listener) {
874ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        setListener(listener, false);
875ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
876ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
877ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
878ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Sets the listener to listen to the IMS call events.
879ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * A {@link ImsCall} can only hold one listener at a time. Subsequent calls
880ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * to this method override the previous listener.
881ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
882ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param listener to listen to the IMS call events of this object; null to remove listener
883ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param callbackImmediately set to true if the caller wants to be called
884ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *        back immediately on the current state
885ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
886ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void setListener(ImsCall.Listener listener, boolean callbackImmediately) {
887ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        boolean inCall;
888ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        boolean onHold;
889ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        int state;
890ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        ImsReasonInfo lastReasonInfo;
891ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
892ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
893ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mListener = listener;
894ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
895ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if ((listener == null) || !callbackImmediately) {
896ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return;
897ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
898ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
899ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            inCall = mInCall;
900ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onHold = mHold;
901ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            state = getState();
902ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            lastReasonInfo = mLastReasonInfo;
903ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
904ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
905ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        try {
906ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (lastReasonInfo != null) {
907ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener.onCallError(this, lastReasonInfo);
908ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } else if (inCall) {
909ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (onHold) {
910ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallHeld(this);
911ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } else {
912ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallStarted(this);
913ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
914ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } else {
915ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                switch (state) {
916ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    case ImsCallSession.State.ESTABLISHING:
917ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        listener.onCallProgressing(this);
918ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        break;
919ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    case ImsCallSession.State.TERMINATED:
920ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        listener.onCallTerminated(this, lastReasonInfo);
921ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        break;
922ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    default:
923ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        // Ignore it. There is no action in the other state.
924ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        break;
925ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
926ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
927ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        } catch (Throwable t) {
9286804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            loge("setListener() :: ", t);
929ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
930ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
931ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
932ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
933ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Mutes or unmutes the mic for the active call.
934ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
935ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param muted true if the call is muted, false otherwise
936ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
937ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void setMute(boolean muted) throws ImsException {
938ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
939ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mMute != muted) {
9406804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("setMute :: turning mute " + (muted ? "on" : "off"));
941ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mMute = muted;
942ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
943ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
944ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    mSession.setMute(muted);
945ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
946ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("setMute :: ", t);
947ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    throwImsException(t, 0);
948ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
949ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
950ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
951ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
952ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
953ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     /**
954ef36ef67e009449300b0150c60c9f637e205d79eWink Saville      * Attaches an incoming call to this call object.
955ef36ef67e009449300b0150c60c9f637e205d79eWink Saville      *
956ef36ef67e009449300b0150c60c9f637e205d79eWink Saville      * @param session the session that receives the incoming call
957ef36ef67e009449300b0150c60c9f637e205d79eWink Saville      * @throws ImsException if the IMS service fails to attach this object to the session
958ef36ef67e009449300b0150c60c9f637e205d79eWink Saville      */
959ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     public void attachSession(ImsCallSession session) throws ImsException {
9606804851b58264d7e82b09a845118d24d36c8d831Anthony Lee         logi("attachSession :: session=" + session);
961ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
962ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         synchronized(mLockObj) {
963ef36ef67e009449300b0150c60c9f637e205d79eWink Saville             mSession = session;
964ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
965ef36ef67e009449300b0150c60c9f637e205d79eWink Saville             try {
966ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                 mSession.setListener(createCallSessionListener());
967ef36ef67e009449300b0150c60c9f637e205d79eWink Saville             } catch (Throwable t) {
968ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                 loge("attachSession :: ", t);
969ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                 throwImsException(t, 0);
970ef36ef67e009449300b0150c60c9f637e205d79eWink Saville             }
971ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         }
972ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     }
973ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
974ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
975ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Initiates an IMS call with the call profile which is provided
976ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * when creating a {@link ImsCall}.
977ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
978ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param session the {@link ImsCallSession} for carrying out the call
979ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param callee callee information to initiate an IMS call
980ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to initiate the call
981ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
982ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void start(ImsCallSession session, String callee)
983ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            throws ImsException {
9846804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        logi("start(1) :: session=" + session + ", callee=" + callee);
985ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
986ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
987ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession = session;
988ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
989ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            try {
990ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                session.setListener(createCallSessionListener());
991ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                session.start(callee, mCallProfile);
992ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } catch (Throwable t) {
993ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("start(1) :: ", t);
994ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("start(1)", t, 0);
995ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
996ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
997ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
998ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
999ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1000ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Initiates an IMS conferenca call with the call profile which is provided
1001ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * when creating a {@link ImsCall}.
1002ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1003ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param session the {@link ImsCallSession} for carrying out the call
1004ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param participants participant list to initiate an IMS conference call
1005ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to initiate the call
1006ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1007ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void start(ImsCallSession session, String[] participants)
1008ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            throws ImsException {
10096804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        logi("start(n) :: session=" + session + ", callee=" + participants);
1010ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1011ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1012ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession = session;
1013ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1014ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            try {
1015ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                session.setListener(createCallSessionListener());
1016ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                session.start(participants, mCallProfile);
1017ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } catch (Throwable t) {
1018ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("start(n) :: ", t);
1019ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("start(n)", t, 0);
1020ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1021ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1022ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1023ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1024ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1025ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Accepts a call.
1026ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1027ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallStarted
1028d1edfd8cf9ffeb191a84e08522bb570cd8cd4381Tyler Gunn     *
1029d1edfd8cf9ffeb191a84e08522bb570cd8cd4381Tyler Gunn     * @param callType The call type the user agreed to for accepting the call.
1030ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to accept the call
1031ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1032d1edfd8cf9ffeb191a84e08522bb570cd8cd4381Tyler Gunn    public void accept(int callType) throws ImsException {
1033d1edfd8cf9ffeb191a84e08522bb570cd8cd4381Tyler Gunn        accept(callType, new ImsStreamMediaProfile());
1034ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1035ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1036ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1037ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Accepts a call.
1038ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1039ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param callType call type to be answered in {@link ImsCallProfile}
1040ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param profile a media profile to be answered (audio/audio & video, direction, ...)
1041ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallStarted
1042ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to accept the call
1043ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1044ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void accept(int callType, ImsStreamMediaProfile profile) throws ImsException {
10456804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        logi("accept :: callType=" + callType + ", profile=" + profile);
1046ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1047ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1048ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1049ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call to answer",
1050ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1051ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1052ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1053ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            try {
1054ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mSession.accept(callType, profile);
1055ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } catch (Throwable t) {
1056ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("accept :: ", t);
1057ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("accept()", t, 0);
1058ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1059ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1060ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mInCall && (mProposedCallProfile != null)) {
1061ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (DBG) {
10626804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    logi("accept :: call profile will be updated");
1063ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1064ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1065ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallProfile = mProposedCallProfile;
1066ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mProposedCallProfile = null;
1067ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1068ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1069ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // Other call update received
1070ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mInCall && (mUpdateRequest == UPDATE_UNSPECIFIED)) {
1071ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
1072ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1073ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1074ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1075ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1076ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1077ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Rejects a call.
1078ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1079ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param reason reason code to reject an incoming call
1080ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallStartFailed
10816804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     * @throws ImsException if the IMS service fails to reject the call
1082ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1083ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void reject(int reason) throws ImsException {
10846804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        logi("reject :: reason=" + reason);
1085ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1086ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1087ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession != null) {
1088ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mSession.reject(reason);
1089ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1090ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1091ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mInCall && (mProposedCallProfile != null)) {
1092ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (DBG) {
10936804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    logi("reject :: call profile is not updated; destroy it...");
1094ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1095ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1096ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mProposedCallProfile = null;
1097ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1098ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1099ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // Other call update received
1100ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mInCall && (mUpdateRequest == UPDATE_UNSPECIFIED)) {
1101ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
1102ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1103ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1104ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1105ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1106ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
110795d563ed2a215d67a4f789c3ebb5a526fb95cc7fTyler Gunn     * Terminates an IMS call (e.g. user initiated).
1108ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1109ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param reason reason code to terminate a call
1110ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to terminate the call
1111ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1112ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void terminate(int reason) throws ImsException {
11136804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        logi("terminate :: reason=" + reason);
1114ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1115ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1116ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mHold = false;
1117ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mInCall = false;
111895d563ed2a215d67a4f789c3ebb5a526fb95cc7fTyler Gunn            mTerminationRequestPending = true;
1119ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1120ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession != null) {
1121c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // TODO: Fix the fact that user invoked call terminations during
1122c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // the process of establishing a conference call needs to be handled
1123c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // as a special case.
1124c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // Currently, any terminations (both invoked by the user or
1125c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // by the network results in a callSessionTerminated() callback
1126c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // from the network.  When establishing a conference call we bury
1127c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // these callbacks until we get closure on all participants of the
1128c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // conference. In some situations, we will throw away the callback
1129c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // (when the underlying session of the host of the new conference
1130c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // is terminated) or will will unbury it when the conference has been
1131c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // established, like when the peer of the new conference goes away
1132c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // after the conference has been created.  The UI relies on the callback
1133c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // to reflect the fact that the call is gone.
1134c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // So if a user decides to terminated a call while it is merging, it
1135c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // could take a long time to reflect in the UI due to the conference
1136c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // processing but we should probably cancel that and just terminate
1137c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // the call immediately and clean up.  This is not a huge issue right
1138c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // now because we have not seen instances where establishing a
1139c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // conference takes a long time (more than a second or two).
1140ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mSession.terminate(reason);
1141ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1142ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1143ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1144ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1145d43b5302d8edf4df90a28055f043786f542df219Uma Maheswari Ramalingam
1146ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1147ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Puts a call on hold. When succeeds, {@link Listener#onCallHeld} is called.
1148ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1149ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallHeld, Listener#onCallHoldFailed
1150ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to hold the call
1151ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1152ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void hold() throws ImsException {
11536804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        logi("hold :: ");
1154111eecc9845826e985c48133b754e453fb3aca84Etan Cohen
1155ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (isOnHold()) {
1156ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
11576804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("hold :: call is already on hold");
1158ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1159ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return;
1160ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1161ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1162ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1163ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mUpdateRequest != UPDATE_NONE) {
11649bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                loge("hold :: update is in progress; request=" +
11659bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                        updateRequestToString(mUpdateRequest));
1166ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("Call update is in progress",
1167ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
1168ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1169ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1170ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1171ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1172ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1173ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1174ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1175ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession.hold(createHoldMediaProfile());
11766804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            // FIXME: We should update the state on the callback because that is where
11776804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            // we can confirm that the hold request was successful or not.
1178ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mHold = true;
1179ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mUpdateRequest = UPDATE_HOLD;
1180ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1181ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1182ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1183ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1184ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Continues a call that's on hold. When succeeds, {@link Listener#onCallResumed} is called.
1185ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1186ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallResumed, Listener#onCallResumeFailed
1187ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to resume the call
1188ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1189ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void resume() throws ImsException {
11906804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        logi("resume :: ");
1191111eecc9845826e985c48133b754e453fb3aca84Etan Cohen
1192ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (!isOnHold()) {
1193ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
11946804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("resume :: call is not being held");
1195ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1196ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return;
1197ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1198ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1199ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1200ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mUpdateRequest != UPDATE_NONE) {
12019bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                loge("resume :: update is in progress; request=" +
12029bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                        updateRequestToString(mUpdateRequest));
1203ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("Call update is in progress",
1204ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
1205ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1206ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1207ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1208ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("resume :: ");
1209ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1210ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1211ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1212ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1213c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // mHold is set to false in confirmation callback that the
1214c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // ImsCall was resumed.
1215ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mUpdateRequest = UPDATE_RESUME;
1216c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            mSession.resume(createResumeMediaProfile());
1217ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1218ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1219ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1220ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1221ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Merges the active & hold call.
1222ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1223ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallMerged, Listener#onCallMergeFailed
1224ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to merge the call
1225ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1226047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    private void merge() throws ImsException {
12276804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        logi("merge :: ");
1228ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1229ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1230ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mUpdateRequest != UPDATE_NONE) {
12319bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                loge("merge :: update is in progress; request=" +
12329bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                        updateRequestToString(mUpdateRequest));
1233ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("Call update is in progress",
1234ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
1235ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1236ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1237ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1238c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                loge("merge :: no call session");
1239ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1240ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1241ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1242ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1243ca45f58a57eb782153c034ae067f59c0018799caUma Maheswari Ramalingam            // if skipHoldBeforeMerge = true, IMS service implementation will
1244ca45f58a57eb782153c034ae067f59c0018799caUma Maheswari Ramalingam            // merge without explicitly holding the call.
1245ca45f58a57eb782153c034ae067f59c0018799caUma Maheswari Ramalingam            if (mHold || (mContext.getResources().getBoolean(
1246ca45f58a57eb782153c034ae067f59c0018799caUma Maheswari Ramalingam                    com.android.internal.R.bool.skipHoldBeforeMerge))) {
1247b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee
12489bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                if (mMergePeer != null && !mMergePeer.isMultiparty() && !isMultiparty()) {
12499bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                    // We only set UPDATE_MERGE when we are adding the first
12509bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                    // calls to the Conference.  If there is already a conference
1251047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                    // no special handling is needed. The existing conference
12529bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                    // session will just go active and any other sessions will be terminated
12539bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                    // if needed.  There will be no merge failed callback.
1254047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                    // Mark both the host and peer UPDATE_MERGE to ensure both are aware that a
1255047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                    // merge is pending.
12569bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                    mUpdateRequest = UPDATE_MERGE;
1257047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                    mMergePeer.mUpdateRequest = UPDATE_MERGE;
1258b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                }
12599bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
12609bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                mSession.merge();
1261ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } else {
126271382693cbc81b1d131085f52d97879976706f55Anthony Lee                // This code basically says, we need to explicitly hold before requesting a merge
126371382693cbc81b1d131085f52d97879976706f55Anthony Lee                // when we get the callback that the hold was successful (or failed), we should
126471382693cbc81b1d131085f52d97879976706f55Anthony Lee                // automatically request a merge.
1265ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mSession.hold(createHoldMediaProfile());
1266ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mHold = true;
1267ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_HOLD_MERGE;
1268ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1269ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1270ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1271ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1272ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1273ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Merges the active & hold call.
1274ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1275ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param bgCall the background (holding) call
1276ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallMerged, Listener#onCallMergeFailed
1277ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to merge the call
1278ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1279ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void merge(ImsCall bgCall) throws ImsException {
12806804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        logi("merge(1) :: bgImsCall=" + bgCall);
1281ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1282ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (bgCall == null) {
1283ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            throw new ImsException("No background call",
1284ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
1285ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1286ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1287ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1288047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            // Mark both sessions as pending merge.
1289047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            this.setCallSessionMergePending(true);
1290047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            bgCall.setCallSessionMergePending(true);
1291047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
129287466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn            if ((!isMultiparty() && !bgCall.isMultiparty()) || isMultiparty()) {
129387466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                // If neither call is multiparty, the current call is the merge host and the bg call
129487466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                // is the merge peer (ie we're starting a new conference).
129587466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                // OR
129687466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                // If this call is multiparty, it is the merge host and the other call is the merge
129787466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                // peer.
129887466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                setMergePeer(bgCall);
129987466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn            } else {
130087466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                // If the bg call is multiparty, it is the merge host.
130187466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                setMergeHost(bgCall);
130287466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn            }
1303ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1304a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam
130595be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam        if (isMultiparty()) {
130695be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam            mMergeRequestedByConference = true;
130795be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam        } else {
130895be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam            logi("merge : mMergeRequestedByConference not set");
130995be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam        }
1310ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        merge();
1311ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1312ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1313ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1314ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Updates the current call's properties (ex. call mode change: video upgrade / downgrade).
1315ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1316ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void update(int callType, ImsStreamMediaProfile mediaProfile) throws ImsException {
13176804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        logi("update :: callType=" + callType + ", mediaProfile=" + mediaProfile);
1318ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1319ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (isOnHold()) {
1320ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
13216804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("update :: call is on hold");
1322ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1323ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            throw new ImsException("Not in a call to update call",
1324ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
1325ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1326ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1327ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1328ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mUpdateRequest != UPDATE_NONE) {
1329ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (DBG) {
13306804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    logi("update :: update is in progress; request=" +
13319bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                            updateRequestToString(mUpdateRequest));
1332ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1333ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("Call update is in progress",
1334ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
1335ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1336ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1337ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1338ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("update :: ");
1339ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1340ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1341ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1342ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1343ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession.update(callType, mediaProfile);
1344ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mUpdateRequest = UPDATE_UNSPECIFIED;
1345ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1346ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1347ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1348ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1349ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Extends this call (1-to-1 call) to the conference call
1350ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * inviting the specified participants to.
1351ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1352ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1353ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void extendToConference(String[] participants) throws ImsException {
13546804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        logi("extendToConference ::");
1355ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1356ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (isOnHold()) {
1357ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
13586804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("extendToConference :: call is on hold");
1359ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1360ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            throw new ImsException("Not in a call to extend a call to conference",
1361ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
1362ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1363ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1364ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1365ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mUpdateRequest != UPDATE_NONE) {
13666804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                if (CONF_DBG) {
13676804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    logi("extendToConference :: update is in progress; request=" +
13689bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                            updateRequestToString(mUpdateRequest));
1369ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1370ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("Call update is in progress",
1371ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
1372ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1373ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1374ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1375ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("extendToConference :: ");
1376ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1377ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1378ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1379ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1380ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession.extendToConference(participants);
1381ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mUpdateRequest = UPDATE_EXTEND_TO_CONFERENCE;
1382ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1383ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1384ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1385ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1386ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Requests the conference server to invite an additional participants to the conference.
1387ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1388ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1389ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void inviteParticipants(String[] participants) throws ImsException {
13906804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        logi("inviteParticipants ::");
1391ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1392ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1393ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1394ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("inviteParticipants :: ");
1395ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1396ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1397ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1398ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1399ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession.inviteParticipants(participants);
1400ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1401ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1402ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1403ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1404ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Requests the conference server to remove the specified participants from the conference.
1405ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1406ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1407ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void removeParticipants(String[] participants) throws ImsException {
1408a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam        logi("removeParticipants :: session=" + mSession);
1409ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1410ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1411ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("removeParticipants :: ");
1412ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1413ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1414ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1415ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1416ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession.removeParticipants(participants);
1417a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam
1418ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1419ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1420ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1421ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1422ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Sends a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2833</a>,
1423ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * event 0 ~ 9 maps to decimal value 0 ~ 9, '*' to 10, '#' to 11, event 'A' ~ 'D' to 12 ~ 15,
1424ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * and event flash to 16. Currently, event flash is not supported.
1425ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
14262f92daf76a66d7d2fe6fb7b1a28fc1b5888a7b7cLibin.Tang@motorola.com     * @param c that represents the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs.
14272f92daf76a66d7d2fe6fb7b1a28fc1b5888a7b7cLibin.Tang@motorola.com     * @param result the result message to send when done.
1428ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
14292f92daf76a66d7d2fe6fb7b1a28fc1b5888a7b7cLibin.Tang@motorola.com    public void sendDtmf(char c, Message result) {
14306804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        logi("sendDtmf :: code=" + c);
1431ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1432ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1433ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession != null) {
1434a4710d5d926d8112179acece620f49cb79257e98Andrew Lee                mSession.sendDtmf(c, result);
1435ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1436ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1437ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1438ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1439ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1440a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam     * Start a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2833</a>,
1441a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam     * event 0 ~ 9 maps to decimal value 0 ~ 9, '*' to 10, '#' to 11, event 'A' ~ 'D' to 12 ~ 15,
1442a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam     * and event flash to 16. Currently, event flash is not supported.
1443a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam     *
1444a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam     * @param c that represents the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs.
1445a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam     */
1446a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam    public void startDtmf(char c) {
14476804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        logi("startDtmf :: code=" + c);
1448a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam
1449a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam        synchronized(mLockObj) {
1450a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam            if (mSession != null) {
1451a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam                mSession.startDtmf(c);
1452a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam            }
1453a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam        }
1454a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam    }
1455a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam
1456a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam    /**
1457a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam     * Stop a DTMF code.
1458a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam     */
1459a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam    public void stopDtmf() {
14606804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        logi("stopDtmf :: ");
1461a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam
1462a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam        synchronized(mLockObj) {
1463a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam            if (mSession != null) {
1464a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam                mSession.stopDtmf();
1465a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam            }
1466a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam        }
1467a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam    }
1468a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam
1469a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam    /**
1470ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Sends an USSD message.
1471ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1472ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param ussdMessage USSD message to send
1473ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1474ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void sendUssd(String ussdMessage) throws ImsException {
14756804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        logi("sendUssd :: ussdMessage=" + ussdMessage);
1476ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1477ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1478ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1479ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("sendUssd :: ");
1480ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1481ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1482ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1483ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1484ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession.sendUssd(ussdMessage);
1485ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1486ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1487ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1488ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void clear(ImsReasonInfo lastReasonInfo) {
1489ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mInCall = false;
1490ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mHold = false;
1491ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mUpdateRequest = UPDATE_NONE;
1492ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mLastReasonInfo = lastReasonInfo;
1493ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1494ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1495ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1496ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Creates an IMS call session listener.
1497ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1498ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsCallSession.Listener createCallSessionListener() {
1499ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        return new ImsCallSessionListenerProxy();
1500ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1501ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1502ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsCall createNewCall(ImsCallSession session, ImsCallProfile profile) {
1503ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        ImsCall call = new ImsCall(mContext, profile);
1504ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1505ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        try {
1506ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            call.attachSession(session);
1507ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        } catch (ImsException e) {
1508ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (call != null) {
1509ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                call.close();
1510ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                call = null;
1511ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1512ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1513ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1514ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        // Do additional operations...
1515ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1516ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        return call;
1517ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1518ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1519ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsStreamMediaProfile createHoldMediaProfile() {
1520ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        ImsStreamMediaProfile mediaProfile = new ImsStreamMediaProfile();
1521ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1522ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (mCallProfile == null) {
1523ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mediaProfile;
1524ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1525ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1526ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mediaProfile.mAudioQuality = mCallProfile.mMediaProfile.mAudioQuality;
1527ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mediaProfile.mVideoQuality = mCallProfile.mMediaProfile.mVideoQuality;
1528ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mediaProfile.mAudioDirection = ImsStreamMediaProfile.DIRECTION_SEND;
1529ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1530ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (mediaProfile.mVideoQuality != ImsStreamMediaProfile.VIDEO_QUALITY_NONE) {
1531ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mediaProfile.mVideoDirection = ImsStreamMediaProfile.DIRECTION_SEND;
1532ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1533ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1534ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        return mediaProfile;
1535ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1536ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1537ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsStreamMediaProfile createResumeMediaProfile() {
1538ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        ImsStreamMediaProfile mediaProfile = new ImsStreamMediaProfile();
1539ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1540ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (mCallProfile == null) {
1541ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mediaProfile;
1542ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1543ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1544ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mediaProfile.mAudioQuality = mCallProfile.mMediaProfile.mAudioQuality;
1545ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mediaProfile.mVideoQuality = mCallProfile.mMediaProfile.mVideoQuality;
1546ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mediaProfile.mAudioDirection = ImsStreamMediaProfile.DIRECTION_SEND_RECEIVE;
1547ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1548ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (mediaProfile.mVideoQuality != ImsStreamMediaProfile.VIDEO_QUALITY_NONE) {
1549ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mediaProfile.mVideoDirection = ImsStreamMediaProfile.DIRECTION_SEND_RECEIVE;
1550ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1551ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1552ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        return mediaProfile;
1553ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1554ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1555ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void enforceConversationMode() {
1556ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (mInCall) {
1557ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mHold = false;
1558ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mUpdateRequest = UPDATE_NONE;
1559ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1560ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1561ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1562ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void mergeInternal() {
15636804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        if (CONF_DBG) {
15646804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("mergeInternal :: ");
1565ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1566ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1567ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mSession.merge();
1568ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mUpdateRequest = UPDATE_MERGE;
1569ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1570ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1571ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void notifyConferenceSessionTerminated(ImsReasonInfo reasonInfo) {
15729bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        ImsCall.Listener listener = mListener;
1573ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        clear(reasonInfo);
1574ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1575ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (listener != null) {
1576ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            try {
1577ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener.onCallTerminated(this, reasonInfo);
1578ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } catch (Throwable t) {
1579ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("notifyConferenceSessionTerminated :: ", t);
1580ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1581ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1582ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1583ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1584ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void notifyConferenceStateUpdated(ImsConferenceState state) {
15859e3452a8efa430f9ca04379be3da6baf0bb0f51aTyler Gunn        if (state == null || state.mParticipants == null) {
15869e3452a8efa430f9ca04379be3da6baf0bb0f51aTyler Gunn            return;
15879e3452a8efa430f9ca04379be3da6baf0bb0f51aTyler Gunn        }
15889e3452a8efa430f9ca04379be3da6baf0bb0f51aTyler Gunn
15891c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn        Set<Entry<String, Bundle>> participants = state.mParticipants.entrySet();
1590ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
15911c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn        if (participants == null) {
1592ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return;
1593ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1594ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
15951c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn        Iterator<Entry<String, Bundle>> iterator = participants.iterator();
1596a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam        mConferenceParticipants = new ArrayList<>(participants.size());
1597ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        while (iterator.hasNext()) {
1598ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            Entry<String, Bundle> entry = iterator.next();
1599ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1600ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            String key = entry.getKey();
1601ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            Bundle confInfo = entry.getValue();
1602ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            String status = confInfo.getString(ImsConferenceState.STATUS);
1603ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            String user = confInfo.getString(ImsConferenceState.USER);
16045965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn            String displayName = confInfo.getString(ImsConferenceState.DISPLAY_TEXT);
1605ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            String endpoint = confInfo.getString(ImsConferenceState.ENDPOINT);
1606ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
16076804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            if (CONF_DBG) {
16086804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("notifyConferenceStateUpdated :: key=" + key +
1609ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ", status=" + status +
1610ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ", user=" + user +
16115965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn                        ", displayName= " + displayName +
1612ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ", endpoint=" + endpoint);
1613ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1614ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
16159bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            Uri handle = Uri.parse(user);
1616a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam            if (endpoint == null) {
1617a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam                endpoint = "";
1618a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam            }
16199bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            Uri endpointUri = Uri.parse(endpoint);
16209bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            int connectionState = ImsConferenceState.getConnectionStateForStatus(status);
1621ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1622a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam            if (connectionState != Connection.STATE_DISCONNECTED) {
1623a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam                ConferenceParticipant conferenceParticipant = new ConferenceParticipant(handle,
1624a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam                        displayName, endpointUri, connectionState);
1625a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam                mConferenceParticipants.add(conferenceParticipant);
1626a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam            }
1627ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
16281c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn
16290f108033df343d446e42c403494cc2ab079895d5Anju Mathapati        if (mConferenceParticipants != null && mListener != null) {
16301c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn            try {
1631a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam                mListener.onConferenceParticipantsStateChanged(this, mConferenceParticipants);
16321c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn            } catch (Throwable t) {
16331c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn                loge("notifyConferenceStateUpdated :: ", t);
16341c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn            }
16351c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn        }
1636ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1637ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1638b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    /**
1639b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee     * Perform all cleanup and notification around the termination of a session.
1640b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee     * Note that there are 2 distinct modes of operation.  The first is when
1641b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee     * we receive a session termination on the primary session when we are
1642b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee     * in the processing of merging.  The second is when we are not merging anything
1643b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee     * and the call is terminated.
1644b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee     *
1645b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee     * @param reasonInfo The reason for the session termination
1646b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee     */
1647b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    private void processCallTerminated(ImsReasonInfo reasonInfo) {
164895d563ed2a215d67a4f789c3ebb5a526fb95cc7fTyler Gunn        logi("processCallTerminated :: reason=" + reasonInfo + " userInitiated = " +
164995d563ed2a215d67a4f789c3ebb5a526fb95cc7fTyler Gunn                mTerminationRequestPending);
1650b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee
1651b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee        ImsCall.Listener listener = null;
1652b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee        synchronized(ImsCall.this) {
1653047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            // If we are in the midst of establishing a conference, we will bury the termination
165495d563ed2a215d67a4f789c3ebb5a526fb95cc7fTyler Gunn            // until the merge has completed.  If necessary we can surface the termination at
165595d563ed2a215d67a4f789c3ebb5a526fb95cc7fTyler Gunn            // this point.
165695d563ed2a215d67a4f789c3ebb5a526fb95cc7fTyler Gunn            // We will also NOT bury the termination if a termination was initiated locally.
165795d563ed2a215d67a4f789c3ebb5a526fb95cc7fTyler Gunn            if (isCallSessionMergePending() && !mTerminationRequestPending) {
1658b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                // Since we are in the process of a merge, this trigger means something
1659b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                // else because it is probably due to the merge happening vs. the
1660b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                // session is really terminated. Let's flag this and revisit if
1661b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                // the merge() ends up failing because we will need to take action on the
1662b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                // mSession in that case since the termination was not due to the merge
1663b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                // succeeding.
16646804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                if (CONF_DBG) {
16656804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    logi("processCallTerminated :: burying termination during ongoing merge.");
1666b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                }
1667b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                mSessionEndDuringMerge = true;
1668b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                mSessionEndDuringMergeReasonInfo = reasonInfo;
1669b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                return;
1670b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee            }
1671b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee
16729bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            // If we are terminating the conference call, notify using conference listeners.
16739bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (isMultiparty()) {
1674b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                notifyConferenceSessionTerminated(reasonInfo);
16759bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                return;
1676b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee            } else {
1677b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                listener = mListener;
1678b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                clear(reasonInfo);
1679b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee            }
1680b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee        }
1681b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee
1682b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee        if (listener != null) {
1683b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee            try {
1684b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                listener.onCallTerminated(ImsCall.this, reasonInfo);
1685b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee            } catch (Throwable t) {
1686c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                loge("processCallTerminated :: ", t);
1687b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee            }
1688b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee        }
1689b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    }
169071382693cbc81b1d131085f52d97879976706f55Anthony Lee
169171382693cbc81b1d131085f52d97879976706f55Anthony Lee    /**
169271382693cbc81b1d131085f52d97879976706f55Anthony Lee     * This function determines if the ImsCallSession is our actual ImsCallSession or if is
169371382693cbc81b1d131085f52d97879976706f55Anthony Lee     * the transient session used in the process of creating a conference. This function should only
169471382693cbc81b1d131085f52d97879976706f55Anthony Lee     * be called within  callbacks that are not directly related to conference merging but might
169571382693cbc81b1d131085f52d97879976706f55Anthony Lee     * potentially still be called on the transient ImsCallSession sent to us from
169671382693cbc81b1d131085f52d97879976706f55Anthony Lee     * callSessionMergeStarted() when we don't really care. In those situations, we probably don't
169771382693cbc81b1d131085f52d97879976706f55Anthony Lee     * want to take any action so we need to know that we can return early.
169871382693cbc81b1d131085f52d97879976706f55Anthony Lee     *
169971382693cbc81b1d131085f52d97879976706f55Anthony Lee     * @param session - The {@link ImsCallSession} that the function needs to analyze
170071382693cbc81b1d131085f52d97879976706f55Anthony Lee     * @return true if this is the transient {@link ImsCallSession}, false otherwise.
170171382693cbc81b1d131085f52d97879976706f55Anthony Lee     */
170271382693cbc81b1d131085f52d97879976706f55Anthony Lee    private boolean isTransientConferenceSession(ImsCallSession session) {
170371382693cbc81b1d131085f52d97879976706f55Anthony Lee        if (session != null && session != mSession && session == mTransientConferenceSession) {
170471382693cbc81b1d131085f52d97879976706f55Anthony Lee            return true;
170571382693cbc81b1d131085f52d97879976706f55Anthony Lee        }
170671382693cbc81b1d131085f52d97879976706f55Anthony Lee        return false;
170771382693cbc81b1d131085f52d97879976706f55Anthony Lee    }
170871382693cbc81b1d131085f52d97879976706f55Anthony Lee
1709c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    private void setTransientSessionAsPrimary(ImsCallSession transientSession) {
1710c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        synchronized (ImsCall.this) {
1711c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            mSession.setListener(null);
1712c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            mSession = transientSession;
1713c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            mSession.setListener(createCallSessionListener());
1714c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        }
1715c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    }
1716c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
1717818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati    private void markCallAsMerged(boolean playDisconnectTone) {
1718818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati        if (!isSessionAlive(mSession)) {
171995be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam            // If the peer is dead, let's not play a disconnect sound for it when we
172095be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam            // unbury the termination callback.
1721818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati            logi("markCallAsMerged");
1722818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati            setIsMerged(playDisconnectTone);
1723818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati            mSessionEndDuringMerge = true;
1724818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati            String reasonInfo;
1725818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati            if (playDisconnectTone) {
1726818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati                reasonInfo = "Call ended by network";
1727818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati            } else {
1728818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati                reasonInfo = "Call ended during conference merge process.";
1729818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati            }
1730818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati            mSessionEndDuringMergeReasonInfo = new ImsReasonInfo(
1731818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati                    ImsReasonInfo.CODE_UNSPECIFIED, 0, reasonInfo);
173295be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam        }
173395be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam    }
173495be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam
173571382693cbc81b1d131085f52d97879976706f55Anthony Lee    /**
173695be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam     * Checks if the merge was requested by foreground conference call
173795be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam     *
173895be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam     * @return true if the merge was requested by foreground conference call
1739047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     */
174095be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam    public boolean isMergeRequestedByConf() {
174195be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam        synchronized(mLockObj) {
174295be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam            return mMergeRequestedByConference;
174395be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam        }
174495be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam    }
174595be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam
174695be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam    /**
174795be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam     * Resets the flag which indicates merge request was sent by
174895be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam     * foreground conference call
174995be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam     */
175095be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam    public void resetIsMergeRequestedByConf(boolean value) {
175195be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam        synchronized(mLockObj) {
175295be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam            mMergeRequestedByConference = value;
175395be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam        }
175495be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam    }
175595be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam
175695be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam    /**
175795be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam     * Returns current ImsCallSession
175895be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam     *
175995be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam     * @return current session
176095be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam     */
176195be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam    public ImsCallSession getSession() {
176295be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam        synchronized(mLockObj) {
176395be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam            return mSession;
1764c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        }
1765047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    }
1766047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
1767047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    /**
1768c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * We have detected that a initial conference call has been fully configured. The internal
1769c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * state of both {@code ImsCall} objects need to be cleaned up to reflect the new state.
1770c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * This function should only be called in the context of the merge host to simplify logic
177171382693cbc81b1d131085f52d97879976706f55Anthony Lee     *
177271382693cbc81b1d131085f52d97879976706f55Anthony Lee     */
1773b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    private void processMergeComplete() {
17746804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        logi("processMergeComplete :: ");
1775c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
1776c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        // The logic simplifies if we can assume that this function is only called on
1777c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        // the merge host.
1778c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        if (!isMergeHost()) {
1779c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            loge("processMergeComplete :: We are not the merge host!");
1780c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            return;
1781b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee        }
1782b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee
178371382693cbc81b1d131085f52d97879976706f55Anthony Lee        ImsCall.Listener listener;
1784047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        boolean swapRequired = false;
17859bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
178695be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam        ImsCall finalHostCall;
178795be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam        ImsCall finalPeerCall;
178895be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam
178995be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam        synchronized(ImsCall.this) {
1790c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            if (isMultiparty()) {
1791c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                setIsMerged(false);
179295be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                // if case handles Case 4 explained in callSessionMergeComplete
179395be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                // otherwise it is case 5
179495be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                if (!mMergeRequestedByConference) {
179595be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                    // single call in fg, conference call in bg.
179695be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                    // Finally conf call becomes active after conference
179795be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                    this.mHold = false;
179895be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                    swapRequired = true;
1799047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                }
1800818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati                mMergePeer.markCallAsMerged(false);
180195be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                finalHostCall = this;
180295be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                finalPeerCall = mMergePeer;
1803047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            } else {
1804c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // If we are here, we are not trying to merge a new call into an existing
1805c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // conference.  That means that there is a transient session on the merge
1806c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // host that represents the future conference once all the parties
1807c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // have been added to it.  So make sure that it exists or else something
1808c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // very wrong is going on.
1809c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                if (mTransientConferenceSession == null) {
1810c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    loge("processMergeComplete :: No transient session!");
1811c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    return;
1812047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                }
1813c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                if (mMergePeer == null) {
1814c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    loge("processMergeComplete :: No merge peer!");
1815c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    return;
1816047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                }
1817047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
1818c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // Since we are the host, we have the transient session attached to us. Let's detach
1819c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // it and figure out where we need to set it for the final conference configuration.
1820c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                ImsCallSession transientConferenceSession = mTransientConferenceSession;
1821c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                mTransientConferenceSession = null;
1822c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
1823c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // Clear the listener for this transient session, we'll create a new listener
1824c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // when it is attached to the final ImsCall that it should live on.
1825c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                transientConferenceSession.setListener(null);
1826c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
1827c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // Determine which call the transient session should be moved to.  If the current
1828c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // call session is still alive and the merge peer's session is not, we have a
1829c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // situation where the current call failed to merge into the conference but the
1830c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // merge peer did merge in to the conference.  In this type of scenario the current
1831c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // call will continue as a single party call, yet the background call will become
1832c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // the conference.
1833c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
183495be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                // handles Case 3 explained in callSessionMergeComplete
1835c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                if (isSessionAlive(mSession) && !isSessionAlive(mMergePeer.getCallSession())) {
1836c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // I'm the host but we are moving the transient session to the peer since its
1837c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // session was disconnected and my session is still alive.  This signifies that
1838c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // their session was properly added to the conference but mine was not because
1839c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // it is probably in the held state as opposed to part of the final conference.
1840c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // In this case, we need to set isMerged to false on both calls so the
1841c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // disconnect sound is called when either call disconnects.
1842c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // Note that this case is only valid if this is an initial conference being
1843c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // brought up.
184495be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                    mMergePeer.mHold = false;
184595be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                    this.mHold = true;
1846d0fb66402074528deccd6a85f3d1eca8d2d0714fAnju Mathapati                    if (mConferenceParticipants != null && !mConferenceParticipants.isEmpty()) {
1847d0fb66402074528deccd6a85f3d1eca8d2d0714fAnju Mathapati                        mMergePeer.mConferenceParticipants = mConferenceParticipants;
1848d0fb66402074528deccd6a85f3d1eca8d2d0714fAnju Mathapati                    }
1849d0fb66402074528deccd6a85f3d1eca8d2d0714fAnju Mathapati                    // At this point both host & peer will have participant information.
1850d0fb66402074528deccd6a85f3d1eca8d2d0714fAnju Mathapati                    // Peer will transition to host & the participant information
1851d0fb66402074528deccd6a85f3d1eca8d2d0714fAnju Mathapati                    // from that will be used
1852d0fb66402074528deccd6a85f3d1eca8d2d0714fAnju Mathapati                    // HostCall that failed to merge will remain as a single call with
1853d0fb66402074528deccd6a85f3d1eca8d2d0714fAnju Mathapati                    // mConferenceParticipants, which should not be used.
1854d0fb66402074528deccd6a85f3d1eca8d2d0714fAnju Mathapati                    // Expectation is that if this call becomes part of a conference call in future,
1855d0fb66402074528deccd6a85f3d1eca8d2d0714fAnju Mathapati                    // mConferenceParticipants will be overriten with new CEP that is received.
1856c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    finalHostCall = mMergePeer;
1857c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    finalPeerCall = this;
1858c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    swapRequired = true;
1859c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    setIsMerged(false);
1860c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    mMergePeer.setIsMerged(false);
18616804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    if (CONF_DBG) {
18626804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                        logi("processMergeComplete :: transient will transfer to merge peer");
1863047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                    }
18646804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                } else if (!isSessionAlive(mSession) &&
18656804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                                isSessionAlive(mMergePeer.getCallSession())) {
186695be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                    // Handles case 2 explained in callSessionMergeComplete
1867c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // The transient session stays with us and the disconnect sound should be played
1868c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // when the merge peer eventually disconnects since it was not actually added to
1869c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // the conference and is probably sitting in the held state.
1870c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    finalHostCall = this;
1871c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    finalPeerCall = mMergePeer;
1872c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    swapRequired = false;
1873c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    setIsMerged(false);
1874c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    mMergePeer.setIsMerged(false); // Play the disconnect sound
18756804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    if (CONF_DBG) {
18766804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                        logi("processMergeComplete :: transient will stay with the merge host");
1877c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    }
1878c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                } else {
187995be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                    // Handles case 1 explained in callSessionMergeComplete
1880c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // The transient session stays with us and the disconnect sound should not be
1881c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // played when we ripple up the disconnect for the merge peer because it was
1882c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // only disconnected to be added to the conference.
1883c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    finalHostCall = this;
1884c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    finalPeerCall = mMergePeer;
1885818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati                    mMergePeer.markCallAsMerged(false);
1886c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    swapRequired = false;
1887c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    setIsMerged(false);
1888c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    mMergePeer.setIsMerged(true);
18896804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    if (CONF_DBG) {
18906804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                        logi("processMergeComplete :: transient will stay with us (I'm the host).");
1891047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                    }
1892047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                }
1893047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
18946804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                if (CONF_DBG) {
18956804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    logi("processMergeComplete :: call=" + finalHostCall + " is the final host");
1896c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                }
1897c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
1898c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // Add the transient session to the ImsCall that ended up being the host for the
1899c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // conference.
1900c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                finalHostCall.setTransientSessionAsPrimary(transientConferenceSession);
1901047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            }
1902047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
1903c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            listener = finalHostCall.mListener;
1904c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
19051c1088887347d682b7b186027d98ad3617dcfb68Anju Mathapati            updateCallProfile(finalPeerCall);
19061c1088887347d682b7b186027d98ad3617dcfb68Anju Mathapati            updateCallProfile(finalHostCall);
19071c1088887347d682b7b186027d98ad3617dcfb68Anju Mathapati
1908c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // Clear all the merge related flags.
1909c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            clearMergeInfo();
1910c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
1911c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // For the final peer...let's bubble up any possible disconnects that we had
1912c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // during the merge process
1913c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            finalPeerCall.notifySessionTerminatedDuringMerge();
1914c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // For the final host, let's just bury the disconnects that we my have received
1915c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // during the merge process since we are now the host of the conference call.
1916c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            finalHostCall.clearSessionTerminationFlags();
191725394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn
191825394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn            // Keep track of the fact that merge host is the origin of a conference call in
191925394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn            // progress.  This is important so that we can later determine if a multiparty ImsCall
192025394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn            // is multiparty because it was the origin of a conference call, or because it is a
192125394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn            // member of a conference on another device.
192225394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn            finalHostCall.mIsConferenceHost = true;
192371382693cbc81b1d131085f52d97879976706f55Anthony Lee        }
192471382693cbc81b1d131085f52d97879976706f55Anthony Lee        if (listener != null) {
192571382693cbc81b1d131085f52d97879976706f55Anthony Lee            try {
192695be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                // finalPeerCall will have the participant that was not merged and
192795be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                // it will be held state
192895be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                // if peer was merged successfully, finalPeerCall will be null
192995be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                listener.onCallMerged(finalHostCall, finalPeerCall, swapRequired);
193071382693cbc81b1d131085f52d97879976706f55Anthony Lee            } catch (Throwable t) {
1931b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                loge("processMergeComplete :: ", t);
193271382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
19336c0b0d0e83b8d06f40ec814573adc69f362704a9Tyler Gunn            if (mConferenceParticipants != null && !mConferenceParticipants.isEmpty()) {
1934a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam                try {
1935d0fb66402074528deccd6a85f3d1eca8d2d0714fAnju Mathapati                    listener.onConferenceParticipantsStateChanged(finalHostCall,
1936d0fb66402074528deccd6a85f3d1eca8d2d0714fAnju Mathapati                            mConferenceParticipants);
1937a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam                } catch (Throwable t) {
1938a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam                    loge("processMergeComplete :: ", t);
1939a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam                }
1940a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam            }
194171382693cbc81b1d131085f52d97879976706f55Anthony Lee        }
194271382693cbc81b1d131085f52d97879976706f55Anthony Lee        return;
194371382693cbc81b1d131085f52d97879976706f55Anthony Lee    }
194471382693cbc81b1d131085f52d97879976706f55Anthony Lee
19451c1088887347d682b7b186027d98ad3617dcfb68Anju Mathapati    private static void updateCallProfile(ImsCall call) {
19461c1088887347d682b7b186027d98ad3617dcfb68Anju Mathapati        if (call != null) {
19471c1088887347d682b7b186027d98ad3617dcfb68Anju Mathapati            call.updateCallProfile();
19481c1088887347d682b7b186027d98ad3617dcfb68Anju Mathapati        }
19491c1088887347d682b7b186027d98ad3617dcfb68Anju Mathapati    }
19501c1088887347d682b7b186027d98ad3617dcfb68Anju Mathapati
19511c1088887347d682b7b186027d98ad3617dcfb68Anju Mathapati    private void updateCallProfile() {
19521c1088887347d682b7b186027d98ad3617dcfb68Anju Mathapati        synchronized (mLockObj) {
19531c1088887347d682b7b186027d98ad3617dcfb68Anju Mathapati            if (mSession != null) {
19541c1088887347d682b7b186027d98ad3617dcfb68Anju Mathapati                mCallProfile = mSession.getCallProfile();
19551c1088887347d682b7b186027d98ad3617dcfb68Anju Mathapati            }
19561c1088887347d682b7b186027d98ad3617dcfb68Anju Mathapati        }
19571c1088887347d682b7b186027d98ad3617dcfb68Anju Mathapati    }
19581c1088887347d682b7b186027d98ad3617dcfb68Anju Mathapati
195971382693cbc81b1d131085f52d97879976706f55Anthony Lee    /**
1960047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * Handles the case where the session has ended during a merge by reporting the termination
1961047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * reason to listeners.
1962047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     */
1963047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    private void notifySessionTerminatedDuringMerge() {
1964047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        ImsCall.Listener listener;
1965047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        boolean notifyFailure = false;
1966047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        ImsReasonInfo notifyFailureReasonInfo = null;
1967047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
1968047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        synchronized(ImsCall.this) {
1969047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            listener = mListener;
1970047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            if (mSessionEndDuringMerge) {
1971047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                // Set some local variables that will send out a notification about a
1972047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                // previously buried termination callback for our primary session now that
1973047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                // we know that this is not due to the conference call merging successfully.
19746804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                if (CONF_DBG) {
19756804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    logi("notifySessionTerminatedDuringMerge ::reporting terminate during merge");
1976047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                }
1977047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                notifyFailure = true;
1978047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                notifyFailureReasonInfo = mSessionEndDuringMergeReasonInfo;
1979047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            }
1980c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            clearSessionTerminationFlags();
1981047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        }
1982047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
1983047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        if (listener != null && notifyFailure) {
1984047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            try {
1985047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                processCallTerminated(notifyFailureReasonInfo);
1986047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            } catch (Throwable t) {
1987047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                loge("notifySessionTerminatedDuringMerge :: ", t);
1988047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            }
1989047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        }
1990047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    }
1991047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
1992c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    private void clearSessionTerminationFlags() {
1993c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        mSessionEndDuringMerge = false;
1994c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        mSessionEndDuringMergeReasonInfo = null;
1995c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    }
1996c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
1997a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam   /**
199871382693cbc81b1d131085f52d97879976706f55Anthony Lee     * We received a callback from ImsCallSession that a merge failed. Clean up all
1999c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * internal state to represent this state change.  The calling function is a callback
2000c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * and should have been called on the session that was in the foreground
2001c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * when merge() was originally called.  It is assumed that this function will be called
2002c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * on the merge host.
200371382693cbc81b1d131085f52d97879976706f55Anthony Lee     *
200471382693cbc81b1d131085f52d97879976706f55Anthony Lee     * @param reasonInfo The {@link ImsReasonInfo} why the merge failed.
200571382693cbc81b1d131085f52d97879976706f55Anthony Lee     */
2006b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    private void processMergeFailed(ImsReasonInfo reasonInfo) {
20076804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        logi("processMergeFailed :: reason=" + reasonInfo);
2008047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
2009047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        ImsCall.Listener listener;
201071382693cbc81b1d131085f52d97879976706f55Anthony Lee        synchronized(ImsCall.this) {
2011c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // The logic simplifies if we can assume that this function is only called on
2012c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // the merge host.
2013c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            if (!isMergeHost()) {
2014c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                loge("processMergeFailed :: We are not the merge host!");
2015c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                return;
2016c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            }
2017c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
201861d41c1f9ba249bd0df575cc1b551a9e70f54645Anthony Lee            // Try to clean up the transient session if it exists.
201961d41c1f9ba249bd0df575cc1b551a9e70f54645Anthony Lee            if (mTransientConferenceSession != null) {
202071382693cbc81b1d131085f52d97879976706f55Anthony Lee                mTransientConferenceSession.setListener(null);
202171382693cbc81b1d131085f52d97879976706f55Anthony Lee                mTransientConferenceSession = null;
2022b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee            }
2023047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
2024c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            listener = mListener;
2025c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
202661d41c1f9ba249bd0df575cc1b551a9e70f54645Anthony Lee            // Ensure the calls being conferenced into the conference has isMerged = false.
2027c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // Ensure any terminations are surfaced from this session.
2028818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati            markCallAsMerged(true);
2029818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati            setCallSessionMergePending(false);
2030c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            notifySessionTerminatedDuringMerge();
203161d41c1f9ba249bd0df575cc1b551a9e70f54645Anthony Lee
2032818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati            // Perform the same cleanup on the merge peer if it exists.
203361d41c1f9ba249bd0df575cc1b551a9e70f54645Anthony Lee            if (mMergePeer != null) {
2034818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati                mMergePeer.markCallAsMerged(true);
2035818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati                mMergePeer.setCallSessionMergePending(false);
203661d41c1f9ba249bd0df575cc1b551a9e70f54645Anthony Lee                mMergePeer.notifySessionTerminatedDuringMerge();
203761d41c1f9ba249bd0df575cc1b551a9e70f54645Anthony Lee            } else {
203861d41c1f9ba249bd0df575cc1b551a9e70f54645Anthony Lee                loge("processMergeFailed :: No merge peer!");
203961d41c1f9ba249bd0df575cc1b551a9e70f54645Anthony Lee            }
2040c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
2041c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // Clear all the various flags around coordinating this merge.
2042c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            clearMergeInfo();
204371382693cbc81b1d131085f52d97879976706f55Anthony Lee        }
204471382693cbc81b1d131085f52d97879976706f55Anthony Lee        if (listener != null) {
204571382693cbc81b1d131085f52d97879976706f55Anthony Lee            try {
204671382693cbc81b1d131085f52d97879976706f55Anthony Lee                listener.onCallMergeFailed(ImsCall.this, reasonInfo);
204771382693cbc81b1d131085f52d97879976706f55Anthony Lee            } catch (Throwable t) {
2048b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                loge("processMergeFailed :: ", t);
204971382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
205071382693cbc81b1d131085f52d97879976706f55Anthony Lee        }
2051c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
205271382693cbc81b1d131085f52d97879976706f55Anthony Lee        return;
205371382693cbc81b1d131085f52d97879976706f55Anthony Lee    }
205471382693cbc81b1d131085f52d97879976706f55Anthony Lee
2055ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private class ImsCallSessionListenerProxy extends ImsCallSession.Listener {
2056ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
205771382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionProgressing(ImsCallSession session, ImsStreamMediaProfile profile) {
20586804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionProgressing :: session=" + session + " profile=" + profile);
20596804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
206071382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2061c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // If it is a transient (conference) session, there is no action for this signal.
20626804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionProgressing :: not supported for transient conference session=" +
2063b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
206471382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
206571382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
206671382693cbc81b1d131085f52d97879976706f55Anthony Lee
2067ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2068ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2069ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2070ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2071ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallProfile.mMediaProfile.copyFrom(profile);
2072ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2073ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2074ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2075ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2076ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallProgressing(ImsCall.this);
2077ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2078ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionProgressing :: ", t);
2079ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2080ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2081ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2082ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2083ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
208471382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionStarted(ImsCallSession session, ImsCallProfile profile) {
20856804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionStarted :: session=" + session + " profile=" + profile);
2086c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
2087c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            if (!isTransientConferenceSession(session)) {
2088c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // In the case that we are in the middle of a merge (either host or peer), we have
2089c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // closure as far as this call's primary session is concerned.  If we are not
2090c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // merging...its a NOOP.
2091c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                setCallSessionMergePending(false);
2092c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            } else {
20936804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionStarted :: on transient session=" + session);
2094c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                return;
2095ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2096ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2097c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            if (isTransientConferenceSession(session)) {
2098c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // No further processing is needed if this is the transient session.
2099b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                return;
2100b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee            }
2101b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee
2102ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2103ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2104ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2105ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2106ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallProfile = profile;
2107ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2108ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2109ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2110ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2111ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallStarted(ImsCall.this);
2112ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2113ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionStarted :: ", t);
2114ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2115ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2116ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2117ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2118ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
211971382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionStartFailed(ImsCallSession session, ImsReasonInfo reasonInfo) {
21206804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            loge("callSessionStartFailed :: session=" + session + " reasonInfo=" + reasonInfo);
21216804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
212271382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2123c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // We should not get this callback for a transient session.
21246804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionStartFailed :: not supported for transient conference session=" +
2125b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
212671382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
212771382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
212871382693cbc81b1d131085f52d97879976706f55Anthony Lee
2129ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2130ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2131ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2132ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2133ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mLastReasonInfo = reasonInfo;
2134ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2135ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2136ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2137ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2138ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallStartFailed(ImsCall.this, reasonInfo);
2139ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2140ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionStarted :: ", t);
2141ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2142ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2143ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2144ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2145ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
214671382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionTerminated(ImsCallSession session, ImsReasonInfo reasonInfo) {
21476804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionTerminated :: session=" + session + " reasonInfo=" + reasonInfo);
21486804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
2149c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            if (isTransientConferenceSession(session)) {
21506804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionTerminated :: on transient session=" + session);
2151c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // This is bad, it should be treated much a callSessionMergeFailed since the
2152c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // transient session only exists when in the process of a merge and the
2153c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // termination of this session is effectively the end of the merge.
2154c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                processMergeFailed(reasonInfo);
215571382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
215671382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
215771382693cbc81b1d131085f52d97879976706f55Anthony Lee
2158c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // Process the termination first.  If we are in the midst of establishing a conference
2159c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // call, we may bury this callback until we are done.  If there so no conference
2160c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // call, the code after this function will be a NOOP.
2161c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            processCallTerminated(reasonInfo);
2162c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
2163047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            // If session has terminated, it is no longer pending merge.
2164047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            setCallSessionMergePending(false);
2165047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
2166ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2167ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2168ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
216971382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionHeld(ImsCallSession session, ImsCallProfile profile) {
21706804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionHeld :: session=" + session + "profile=" + profile);
2171ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2172ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2173ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2174047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                // If the session was held, it is no longer pending a merge -- this means it could
2175047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                // not be merged into the conference and was held instead.
2176047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                setCallSessionMergePending(false);
2177047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
2178ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallProfile = profile;
2179ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2180ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (mUpdateRequest == UPDATE_HOLD_MERGE) {
2181c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // This hold request was made to set the stage for a merge.
2182ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    mergeInternal();
2183ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    return;
2184ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2185ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2186ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2187ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2188ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2189ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2190ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2191ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2192ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallHeld(ImsCall.this);
2193ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2194ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionHeld :: ", t);
2195ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2196ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2197ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2198ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2199ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
220071382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionHoldFailed(ImsCallSession session, ImsReasonInfo reasonInfo) {
22016804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            loge("callSessionHoldFailed :: session" + session + "reasonInfo=" + reasonInfo);
22026804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
220371382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2204c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // We should not get this callback for a transient session.
22056804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionHoldFailed :: not supported for transient conference session=" +
2206b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
220771382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
220871382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
220971382693cbc81b1d131085f52d97879976706f55Anthony Lee
2210d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh            logi("callSessionHoldFailed :: session=" + session +
2211d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh                    ", reasonInfo=" + reasonInfo);
2212d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh
2213d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh            synchronized (mLockObj) {
2214a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam                mHold = false;
2215a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam            }
2216a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam
2217ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            boolean isHoldForMerge = false;
2218ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2219ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2220ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2221ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (mUpdateRequest == UPDATE_HOLD_MERGE) {
2222ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    isHoldForMerge = true;
2223ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2224ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2225ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2226ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2227ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2228ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2229ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2230ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2231ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallHoldFailed(ImsCall.this, reasonInfo);
2232ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2233ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionHoldFailed :: ", t);
2234ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2235ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2236ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2237ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2238ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
223971382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionHoldReceived(ImsCallSession session, ImsCallProfile profile) {
22406804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionHoldReceived :: session=" + session + "profile=" + profile);
22416804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
224271382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2243c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // We should not get this callback for a transient session.
22446804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionHoldReceived :: not supported for transient conference session=" +
2245b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
224671382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
224771382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
224871382693cbc81b1d131085f52d97879976706f55Anthony Lee
2249ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2250ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2251ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2252ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2253ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallProfile = profile;
2254ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2255ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2256ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2257ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2258ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallHoldReceived(ImsCall.this);
2259ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2260ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionHoldReceived :: ", t);
2261ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2262ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2263ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2264ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2265ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
226671382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionResumed(ImsCallSession session, ImsCallProfile profile) {
22676804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionResumed :: session=" + session + "profile=" + profile);
22686804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
226971382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
22706804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionResumed :: not supported for transient conference session=" +
2271b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
227271382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
227371382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
227471382693cbc81b1d131085f52d97879976706f55Anthony Lee
2275c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // If this call was pending a merge, it is not anymore. This is the case when we
2276c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // are merging in a new call into an existing conference.
2277c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            setCallSessionMergePending(false);
2278c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
2279c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // TOOD: When we are merging a new call into an existing conference we are waiting
2280c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // for 2 triggers to let us know that the conference has been established, the first
2281c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // is a termination for the new calls (since it is added to the conference) the second
2282c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // would be a resume on the existing conference.  If the resume comes first, then
2283c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // we will make the onCallResumed() callback and its unclear how this will behave if
2284c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // the termination has not come yet.
2285ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2286c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            ImsCall.Listener listener;
2287ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2288ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2289ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallProfile = profile;
2290ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2291095839a66699a128c76cd5002459fcba7c3a9a0dUma Maheswari Ramalingam                mHold = false;
2292ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2293ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2294ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2295ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2296ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallResumed(ImsCall.this);
2297ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2298ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionResumed :: ", t);
2299ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2300ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2301ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2302ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2303ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
230471382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionResumeFailed(ImsCallSession session, ImsReasonInfo reasonInfo) {
23056804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            loge("callSessionResumeFailed :: session=" + session + "reasonInfo=" + reasonInfo);
23066804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
230771382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
23086804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionResumeFailed :: not supported for transient conference session=" +
2309b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
231071382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
231171382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
231271382693cbc81b1d131085f52d97879976706f55Anthony Lee
2313a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam            synchronized(mLockObj) {
2314a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam                mHold = true;
2315a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam            }
2316a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam
2317ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2318ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2319ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2320ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2321ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2322ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2323ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2324ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2325ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2326ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallResumeFailed(ImsCall.this, reasonInfo);
2327ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2328ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionResumeFailed :: ", t);
2329ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2330ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2331ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2332ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2333ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
233471382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionResumeReceived(ImsCallSession session, ImsCallProfile profile) {
23356804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionResumeReceived :: session=" + session + "profile=" + profile);
23366804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
233771382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
23386804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionResumeReceived :: not supported for transient conference session=" +
2339b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
234071382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
234171382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
234271382693cbc81b1d131085f52d97879976706f55Anthony Lee
2343ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2344ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2345ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2346ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2347ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallProfile = profile;
2348ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2349ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2350ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2351ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2352ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallResumeReceived(ImsCall.this);
2353ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2354ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionResumeReceived :: ", t);
2355ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2356ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2357ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2358ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2359ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
23603f2b0aaa277545886571cbf90fc90fd5d304e714Tyler Gunn        public void callSessionMergeStarted(ImsCallSession session,
2361ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsCallSession newSession, ImsCallProfile profile) {
23626804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionMergeStarted :: session=" + session + " newSession=" + newSession +
23636804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    ", profile=" + profile);
2364ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
236571382693cbc81b1d131085f52d97879976706f55Anthony Lee            return;
2366ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2367ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
236895be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam        /*
236995be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam         * This method check if session exists as a session on the current
237095be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam         * ImsCall or its counterpart if it is in the process of a conference
237195be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam         */
237295be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam        private boolean doesCallSessionExistsInMerge(ImsCallSession cs) {
237395be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam            String callId = cs.getCallId();
237495be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam            return ((isMergeHost() && Objects.equals(mMergePeer.mSession.getCallId(), callId)) ||
237595be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                    (isMergePeer() && Objects.equals(mMergeHost.mSession.getCallId(), callId)) ||
237695be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                    Objects.equals(mSession.getCallId(), callId));
237795be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam        }
237895be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam
237995be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam        /**
238095be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam         * We received a callback from ImsCallSession that merge completed.
2381d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati         * @param newSession - this session can have 2 values based on the below scenarios
238295be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam         *
238395be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam	 * Conference Scenarios :
238495be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam         * Case 1 - 3 way success case
238595be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam         * Case 2 - 3 way success case but held call fails to merge
238695be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam         * Case 3 - 3 way success case but active call fails to merge
238795be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam         * case 4 - 4 way success case, where merge is initiated on the foreground single-party
238895be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam         *          call and the conference (mergeHost) is the background call.
238995be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam         * case 5 - 4 way success case, where merge is initiated on the foreground conference
239095be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam         *          call (mergeHost) and the single party call is in the background.
239195be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam         *
239295be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam         * Conference Result:
2393d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati         * session : new session after conference
2394d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati         * newSession = new session for case 1, 2, 3.
2395d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati         *              Should be considered as mTransientConferencession
2396d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati         * newSession = Active conference session for case 5 will be null
2397d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati         *              mergehost was foreground call
2398d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati         *              mTransientConferencession will be null
2399d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati         * newSession = Active conference session for case 4 will be null
2400d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati         *              mergeHost was background call
2401d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati         *              mTransientConferencession will be null
240295be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam         */
2403ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2404d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati        public void callSessionMergeComplete(ImsCallSession newSession) {
2405d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati            logi("callSessionMergeComplete :: newSession =" + newSession);
240695be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam            if (!isMergeHost()) {
240795be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                // Handles case 4
240895be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                mMergeHost.processMergeComplete();
240995be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam            } else {
2410d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati                // Handles case 1, 2, 3
2411d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati                if (newSession != null) {
2412d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati                    mTransientConferenceSession = doesCallSessionExistsInMerge(newSession) ?
2413d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati                            null: newSession;
2414d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati                }
2415d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati                // Handles case 5
241695be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                processMergeComplete();
241795be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam            }
24183f2b0aaa277545886571cbf90fc90fd5d304e714Tyler Gunn        }
24193f2b0aaa277545886571cbf90fc90fd5d304e714Tyler Gunn
24203f2b0aaa277545886571cbf90fc90fd5d304e714Tyler Gunn        @Override
242171382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionMergeFailed(ImsCallSession session, ImsReasonInfo reasonInfo) {
24226804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            loge("callSessionMergeFailed :: session=" + session + "reasonInfo=" + reasonInfo);
2423c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
2424c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // Its possible that there could be threading issues with the other thread handling
2425c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // the other call. This could affect our state.
2426c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            synchronized (ImsCall.this) {
2427c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // Let's tell our parent ImsCall that the merge has failed and we need to clean
2428c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // up any temporary, transient state.  Note this only gets called for an initial
2429c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // conference.  If a merge into an existing conference fails, the two sessions will
2430c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // just go back to their original state (ACTIVE or HELD).
2431c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                if (isMergeHost()) {
2432c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    processMergeFailed(reasonInfo);
2433c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                } else if (mMergeHost != null) {
2434c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    mMergeHost.processMergeFailed(reasonInfo);
2435c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                } else {
2436c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    loge("callSessionMergeFailed :: No merge host for this conference!");
2437c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                }
2438ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2439ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2440ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2441ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
244271382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionUpdated(ImsCallSession session, ImsCallProfile profile) {
24436804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionUpdated :: session=" + session + " profile=" + profile);
24446804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
244571382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
24466804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionUpdated :: not supported for transient conference session=" +
2447b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
244871382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
244971382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
245071382693cbc81b1d131085f52d97879976706f55Anthony Lee
2451ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2452ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2453ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2454ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2455ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallProfile = profile;
2456ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2457ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2458ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2459ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2460ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallUpdated(ImsCall.this);
2461ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2462ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionUpdated :: ", t);
2463ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2464ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2465ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2466ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2467ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
246871382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionUpdateFailed(ImsCallSession session, ImsReasonInfo reasonInfo) {
24696804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            loge("callSessionUpdateFailed :: session=" + session + " reasonInfo=" + reasonInfo);
24706804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
247171382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
24726804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionUpdateFailed :: not supported for transient conference session=" +
2473b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
247471382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
247571382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
247671382693cbc81b1d131085f52d97879976706f55Anthony Lee
2477ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2478ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2479ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2480ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2481ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2482ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2483ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2484ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2485ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2486ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallUpdateFailed(ImsCall.this, reasonInfo);
2487ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2488ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionUpdateFailed :: ", t);
2489ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2490ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2491ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2492ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2493ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
249471382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionUpdateReceived(ImsCallSession session, ImsCallProfile profile) {
24956804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionUpdateReceived :: session=" + session + " profile=" + profile);
24966804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
249771382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
24986804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionUpdateReceived :: not supported for transient conference " +
2499b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        "session=" + session);
250071382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
250171382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
250271382693cbc81b1d131085f52d97879976706f55Anthony Lee
2503ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2504ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2505ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2506ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2507ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mProposedCallProfile = profile;
2508ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_UNSPECIFIED;
2509ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2510ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2511ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2512ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2513ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallUpdateReceived(ImsCall.this);
2514ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2515ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionUpdateReceived :: ", t);
2516ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2517ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2518ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2519ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2520ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
252171382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionConferenceExtended(ImsCallSession session, ImsCallSession newSession,
252271382693cbc81b1d131085f52d97879976706f55Anthony Lee                ImsCallProfile profile) {
25236804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionConferenceExtended :: session=" + session  + " newSession=" +
25246804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    newSession + ", profile=" + profile);
25256804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
252671382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
25276804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionConferenceExtended :: not supported for transient conference " +
2528b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        "session=" + session);
252971382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
253071382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
253171382693cbc81b1d131085f52d97879976706f55Anthony Lee
2532ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall newCall = createNewCall(newSession, profile);
2533ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2534ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (newCall == null) {
2535ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                callSessionConferenceExtendFailed(session, new ImsReasonInfo());
2536ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return;
2537ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2538ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2539ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2540ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2541ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2542ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2543ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2544ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2545ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2546ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2547ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2548ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallConferenceExtended(ImsCall.this, newCall);
2549ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2550ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionConferenceExtended :: ", t);
2551ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2552ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2553ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2554ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2555ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2556ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionConferenceExtendFailed(ImsCallSession session,
2557ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsReasonInfo reasonInfo) {
25586804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            loge("callSessionConferenceExtendFailed :: reasonInfo=" + reasonInfo);
25596804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
256071382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
25616804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionConferenceExtendFailed :: not supported for transient " +
2562b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        "conference session=" + session);
256371382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
256471382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
256571382693cbc81b1d131085f52d97879976706f55Anthony Lee
2566ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2567ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2568ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2569ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2570ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2571ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2572ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2573ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2574ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2575ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallConferenceExtendFailed(ImsCall.this, reasonInfo);
2576ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2577ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionConferenceExtendFailed :: ", t);
2578ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2579ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2580ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2581ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2582ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2583ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionConferenceExtendReceived(ImsCallSession session,
2584ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsCallSession newSession, ImsCallProfile profile) {
25856804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionConferenceExtendReceived :: newSession=" + newSession +
25866804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    ", profile=" + profile);
25876804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
258871382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
25896804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionConferenceExtendReceived :: not supported for transient " +
25909bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                        "conference session" + session);
259171382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
259271382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
259371382693cbc81b1d131085f52d97879976706f55Anthony Lee
2594ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall newCall = createNewCall(newSession, profile);
2595ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2596ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (newCall == null) {
2597ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                // Should all the calls be terminated...???
2598ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return;
2599ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2600ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2601ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2602ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2603ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2604ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2605ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2606ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2607ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2608ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2609ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallConferenceExtendReceived(ImsCall.this, newCall);
2610ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2611ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionConferenceExtendReceived :: ", t);
2612ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2613ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2614ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2615ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2616ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2617ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionInviteParticipantsRequestDelivered(ImsCallSession session) {
26186804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionInviteParticipantsRequestDelivered ::");
26196804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
262071382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
26216804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionInviteParticipantsRequestDelivered :: not supported for " +
262271382693cbc81b1d131085f52d97879976706f55Anthony Lee                        "conference session=" + session);
262371382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
262471382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
262571382693cbc81b1d131085f52d97879976706f55Anthony Lee
2626ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2627ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2628ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2629ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2630ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2631ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2632ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2633ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2634ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallInviteParticipantsRequestDelivered(ImsCall.this);
2635ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2636ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionInviteParticipantsRequestDelivered :: ", t);
2637ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2638ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2639ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2640ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2641ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2642ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionInviteParticipantsRequestFailed(ImsCallSession session,
2643ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsReasonInfo reasonInfo) {
26446804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            loge("callSessionInviteParticipantsRequestFailed :: reasonInfo=" + reasonInfo);
26456804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
264671382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
26476804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionInviteParticipantsRequestFailed :: not supported for " +
264871382693cbc81b1d131085f52d97879976706f55Anthony Lee                        "conference session=" + session);
264971382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
265071382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
265171382693cbc81b1d131085f52d97879976706f55Anthony Lee
2652ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2653ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2654ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2655ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2656ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2657ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2658ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2659ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2660ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallInviteParticipantsRequestFailed(ImsCall.this, reasonInfo);
2661ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2662ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionInviteParticipantsRequestFailed :: ", t);
2663ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2664ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2665ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2666ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2667ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2668ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionRemoveParticipantsRequestDelivered(ImsCallSession session) {
26696804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionRemoveParticipantsRequestDelivered ::");
26706804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
267171382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
26726804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionRemoveParticipantsRequestDelivered :: not supported for " +
267371382693cbc81b1d131085f52d97879976706f55Anthony Lee                        "conference session=" + session);
267471382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
267571382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
267671382693cbc81b1d131085f52d97879976706f55Anthony Lee
2677ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2678ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2679ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2680ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2681ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2682ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2683ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2684ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2685ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallRemoveParticipantsRequestDelivered(ImsCall.this);
2686ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2687ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionRemoveParticipantsRequestDelivered :: ", t);
2688ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2689ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2690ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2691ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2692ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2693ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionRemoveParticipantsRequestFailed(ImsCallSession session,
2694ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsReasonInfo reasonInfo) {
26956804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            loge("callSessionRemoveParticipantsRequestFailed :: reasonInfo=" + reasonInfo);
26966804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
269771382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
26986804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionRemoveParticipantsRequestFailed :: not supported for " +
26999bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                        "conference session=" + session);
270071382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
270171382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
270271382693cbc81b1d131085f52d97879976706f55Anthony Lee
2703ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2704ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2705ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2706ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2707ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2708ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2709ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2710ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2711ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallRemoveParticipantsRequestFailed(ImsCall.this, reasonInfo);
2712ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2713ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionRemoveParticipantsRequestFailed :: ", t);
2714ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2715ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2716ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2717ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2718ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2719ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionConferenceStateUpdated(ImsCallSession session,
2720ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsConferenceState state) {
27216804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionConferenceStateUpdated :: state=" + state);
27226804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
2723938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn            conferenceStateUpdated(state);
2724ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2725ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2726ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
272771382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionUssdMessageReceived(ImsCallSession session, int mode,
272871382693cbc81b1d131085f52d97879976706f55Anthony Lee                String ussdMessage) {
27296804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionUssdMessageReceived :: mode=" + mode + ", ussdMessage=" +
27306804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    ussdMessage);
27316804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
273271382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
27336804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionUssdMessageReceived :: not supported for transient " +
2734b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        "conference session=" + session);
273571382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
273671382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
273771382693cbc81b1d131085f52d97879976706f55Anthony Lee
2738ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2739ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2740ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2741ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2742ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2743ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2744ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2745ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2746ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallUssdMessageReceived(ImsCall.this, mode, ussdMessage);
2747ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2748ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionUssdMessageReceived :: ", t);
2749ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2750ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2751ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2752987bab859324396c0d1fc00c375f98f3f74c9067Pavel Zhamaitsiak
2753987bab859324396c0d1fc00c375f98f3f74c9067Pavel Zhamaitsiak        @Override
2754987bab859324396c0d1fc00c375f98f3f74c9067Pavel Zhamaitsiak        public void callSessionTtyModeReceived(ImsCallSession session, int mode) {
27556804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionTtyModeReceived :: mode=" + mode);
2756987bab859324396c0d1fc00c375f98f3f74c9067Pavel Zhamaitsiak
2757a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak            ImsCall.Listener listener;
2758a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak
2759a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak            synchronized(ImsCall.this) {
2760a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak                listener = mListener;
2761a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak            }
2762a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak
2763a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak            if (listener != null) {
2764a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak                try {
2765a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak                    listener.onCallSessionTtyModeReceived(ImsCall.this, mode);
2766a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak                } catch (Throwable t) {
2767a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak                    loge("callSessionTtyModeReceived :: ", t);
2768987bab859324396c0d1fc00c375f98f3f74c9067Pavel Zhamaitsiak                }
2769987bab859324396c0d1fc00c375f98f3f74c9067Pavel Zhamaitsiak            }
2770987bab859324396c0d1fc00c375f98f3f74c9067Pavel Zhamaitsiak        }
27711463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar
277225394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn        /**
277325394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn         * Notifies of a change to the multiparty state for this {@code ImsCallSession}.
277425394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn         *
277525394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn         * @param session The call session.
277625394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn         * @param isMultiParty {@code true} if the session became multiparty, {@code false}
277725394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn         *      otherwise.
277825394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn         */
277925394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn        @Override
278025394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn        public void callSessionMultipartyStateChanged(ImsCallSession session,
278125394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn                boolean isMultiParty) {
278225394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn            if (VDBG) {
2783691a1cc831e1bade18cb39f917f9aebbb5939ab8Pavel Zhamaitsiak                logi("callSessionMultipartyStateChanged isMultiParty: " + (isMultiParty ? "Y"
278425394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn                        : "N"));
278525394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn            }
278625394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn
278725394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn            ImsCall.Listener listener;
278825394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn
278925394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn            synchronized(ImsCall.this) {
279025394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn                listener = mListener;
279125394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn            }
279225394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn
279325394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn            if (listener != null) {
279425394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn                try {
279525394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn                    listener.onMultipartyStateChanged(ImsCall.this, isMultiParty);
279625394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn                } catch (Throwable t) {
279725394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn                    loge("callSessionMultipartyStateChanged :: ", t);
279825394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn                }
279925394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn            }
280025394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn        }
280125394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn
28021463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar        public void callSessionHandover(ImsCallSession session, int srcAccessTech,
28031463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            int targetAccessTech, ImsReasonInfo reasonInfo) {
28046804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionHandover :: session=" + session + ", srcAccessTech=" +
28056804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                srcAccessTech + ", targetAccessTech=" + targetAccessTech + ", reasonInfo=" +
28066804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                reasonInfo);
28071463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar
28081463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            ImsCall.Listener listener;
28091463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar
28101463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            synchronized(ImsCall.this) {
28111463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                listener = mListener;
28121463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            }
28131463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar
28141463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            if (listener != null) {
28151463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                try {
28161463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                    listener.onCallHandover(ImsCall.this, srcAccessTech, targetAccessTech,
28171463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                        reasonInfo);
28181463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                } catch (Throwable t) {
28191463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                    loge("callSessionHandover :: ", t);
28201463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                }
28211463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            }
28221463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar        }
28231463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar
28241463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar        @Override
28251463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar        public void callSessionHandoverFailed(ImsCallSession session, int srcAccessTech,
28261463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            int targetAccessTech, ImsReasonInfo reasonInfo) {
28276804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            loge("callSessionHandoverFailed :: session=" + session + ", srcAccessTech=" +
28286804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                srcAccessTech + ", targetAccessTech=" + targetAccessTech + ", reasonInfo=" +
28296804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                reasonInfo);
28301463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar
28311463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            ImsCall.Listener listener;
28321463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar
28331463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            synchronized(ImsCall.this) {
28341463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                listener = mListener;
28351463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            }
28361463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar
28371463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            if (listener != null) {
28381463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                try {
28391463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                    listener.onCallHandoverFailed(ImsCall.this, srcAccessTech, targetAccessTech,
28401463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                        reasonInfo);
28411463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                } catch (Throwable t) {
28421463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                    loge("callSessionHandoverFailed :: ", t);
28431463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                }
28441463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            }
28451463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar        }
2846d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh
2847d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh        @Override
2848d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh        public void callSessionSuppServiceReceived(ImsCallSession session,
2849d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh                ImsSuppServiceNotification suppServiceInfo ) {
2850d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh            if (isTransientConferenceSession(session)) {
2851d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh                logi("callSessionSuppServiceReceived :: not supported for transient conference"
2852d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh                        + " session=" + session);
2853d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh                return;
2854d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh            }
2855d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh
2856d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh            logi("callSessionSuppServiceReceived :: session=" + session +
2857d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh                     ", suppServiceInfo" + suppServiceInfo);
2858d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh
2859d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh            ImsCall.Listener listener;
2860d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh
2861d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh            synchronized(ImsCall.this) {
2862d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh                listener = mListener;
2863d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh            }
2864d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh
2865d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh            if (listener != null) {
2866d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh                try {
2867d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh                    listener.onCallSuppServiceReceived(ImsCall.this, suppServiceInfo);
2868d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh                } catch (Throwable t) {
2869d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh                    loge("callSessionSuppServiceReceived :: ", t);
2870d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh                }
2871d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh            }
2872d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh        }
2873ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
2874938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn
2875938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn    /**
2876938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     * Report a new conference state to the current {@link ImsCall} and inform listeners of the
2877938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     * change.  Marked as {@code VisibleForTesting} so that the
2878938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     * {@code com.android.internal.telephony.TelephonyTester} class can inject a test conference
2879938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     * event package into a regular ongoing IMS call.
2880938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     *
2881938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     * @param state The {@link ImsConferenceState}.
2882938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     */
2883938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn    @VisibleForTesting
2884938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn    public void conferenceStateUpdated(ImsConferenceState state) {
2885938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn        Listener listener;
2886938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn
2887938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn        synchronized(this) {
2888938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn            notifyConferenceStateUpdated(state);
2889938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn            listener = mListener;
2890938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn        }
2891938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn
2892938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn        if (listener != null) {
2893938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn            try {
2894938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn                listener.onCallConferenceStateUpdated(this, state);
2895938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn            } catch (Throwable t) {
2896938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn                loge("callSessionConferenceStateUpdated :: ", t);
2897938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn            }
2898938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn        }
2899938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn    }
2900168c634eef29f21c73129164207d04b8cce23738Tyler Gunn
2901168c634eef29f21c73129164207d04b8cce23738Tyler Gunn    /**
2902168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     * Provides a human-readable string representation of an update request.
2903168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     *
2904168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     * @param updateRequest The update request.
2905168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     * @return The string representation.
2906168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     */
2907168c634eef29f21c73129164207d04b8cce23738Tyler Gunn    private String updateRequestToString(int updateRequest) {
2908168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        switch (updateRequest) {
2909168c634eef29f21c73129164207d04b8cce23738Tyler Gunn            case UPDATE_NONE:
2910168c634eef29f21c73129164207d04b8cce23738Tyler Gunn                return "NONE";
2911168c634eef29f21c73129164207d04b8cce23738Tyler Gunn            case UPDATE_HOLD:
2912168c634eef29f21c73129164207d04b8cce23738Tyler Gunn                return "HOLD";
2913168c634eef29f21c73129164207d04b8cce23738Tyler Gunn            case UPDATE_HOLD_MERGE:
2914168c634eef29f21c73129164207d04b8cce23738Tyler Gunn                return "HOLD_MERGE";
2915168c634eef29f21c73129164207d04b8cce23738Tyler Gunn            case UPDATE_RESUME:
2916168c634eef29f21c73129164207d04b8cce23738Tyler Gunn                return "RESUME";
2917168c634eef29f21c73129164207d04b8cce23738Tyler Gunn            case UPDATE_MERGE:
2918168c634eef29f21c73129164207d04b8cce23738Tyler Gunn                return "MERGE";
2919168c634eef29f21c73129164207d04b8cce23738Tyler Gunn            case UPDATE_EXTEND_TO_CONFERENCE:
2920168c634eef29f21c73129164207d04b8cce23738Tyler Gunn                return "EXTEND_TO_CONFERENCE";
2921168c634eef29f21c73129164207d04b8cce23738Tyler Gunn            case UPDATE_UNSPECIFIED:
2922168c634eef29f21c73129164207d04b8cce23738Tyler Gunn                return "UNSPECIFIED";
2923168c634eef29f21c73129164207d04b8cce23738Tyler Gunn            default:
2924168c634eef29f21c73129164207d04b8cce23738Tyler Gunn                return "UNKNOWN";
2925168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        }
2926168c634eef29f21c73129164207d04b8cce23738Tyler Gunn    }
2927168c634eef29f21c73129164207d04b8cce23738Tyler Gunn
2928168c634eef29f21c73129164207d04b8cce23738Tyler Gunn    /**
29299bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * Clears the merge peer for this call, ensuring that the peer's connection to this call is also
29309bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * severed at the same time.
29319bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     */
2932c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    private void clearMergeInfo() {
29336804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        if (CONF_DBG) {
29346804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("clearMergeInfo :: clearing all merge info");
2935c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        }
2936047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
2937c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        // First clear out the merge partner then clear ourselves out.
29389bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (mMergeHost != null) {
29399bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            mMergeHost.mMergePeer = null;
2940165aed55d289ae2a5cdf34de4164c2395f46b8c1Libin.Tang@motorola.com            mMergeHost.mUpdateRequest = UPDATE_NONE;
2941c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            mMergeHost.mCallSessionMergePending = false;
29429bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        }
29439bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (mMergePeer != null) {
29449bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            mMergePeer.mMergeHost = null;
2945165aed55d289ae2a5cdf34de4164c2395f46b8c1Libin.Tang@motorola.com            mMergePeer.mUpdateRequest = UPDATE_NONE;
2946c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            mMergePeer.mCallSessionMergePending = false;
29479bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        }
2948c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        mMergeHost = null;
2949c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        mMergePeer = null;
2950c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        mUpdateRequest = UPDATE_NONE;
2951c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        mCallSessionMergePending = false;
29529bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    }
29539bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
29549bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    /**
29559bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * Sets the merge peer for the current call.  The merge peer is the background call that will be
29569bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * merged into this call.  On the merge peer, sets the merge host to be this call.
29579bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     *
29589bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * @param mergePeer The peer call to be merged into this one.
29599bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     */
29609bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    private void setMergePeer(ImsCall mergePeer) {
29619bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        mMergePeer = mergePeer;
29629bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        mMergeHost = null;
29639bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
29649bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        mergePeer.mMergeHost = ImsCall.this;
29659bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        mergePeer.mMergePeer = null;
29669bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    }
29679bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
29689bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    /**
29699bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * Sets the merge hody for the current call.  The merge host is the foreground call this call
29709bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * will be merged into.  On the merge host, sets the merge peer to be this call.
29719bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     *
29729bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * @param mergeHost The merge host this call will be merged into.
29739bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     */
29749bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    public void setMergeHost(ImsCall mergeHost) {
29759bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        mMergeHost = mergeHost;
29769bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        mMergePeer = null;
29779bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
29789bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        mergeHost.mMergeHost = null;
29799bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        mergeHost.mMergePeer = ImsCall.this;
29809bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    }
29819bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
29829bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    /**
29839bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * Determines if the current call is in the process of merging with another call or conference.
29849bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     *
29859bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * @return {@code true} if in the process of merging.
29869bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     */
29879bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    private boolean isMerging() {
29889bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        return mMergePeer != null || mMergeHost != null;
29899bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    }
29909bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
29919bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    /**
29929bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * Determines if the current call is the host of the merge.
29939bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     *
29949bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * @return {@code true} if the call is the merge host.
29959bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     */
29969bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    private boolean isMergeHost() {
29979bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        return mMergePeer != null && mMergeHost == null;
29989bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    }
29999bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
30009bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    /**
30019bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * Determines if the current call is the peer of the merge.
30029bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     *
30039bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * @return {@code true} if the call is the merge peer.
30049bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     */
30059bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    private boolean isMergePeer() {
30069bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        return mMergePeer == null && mMergeHost != null;
30079bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    }
30089bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
30099bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    /**
3010047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * Determines if the call session is pending merge into a conference or not.
3011047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     *
3012047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * @return {@code true} if a merge into a conference is pending, {@code false} otherwise.
3013047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     */
3014047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    private boolean isCallSessionMergePending() {
3015047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        return mCallSessionMergePending;
3016047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    }
3017047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
3018047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    /**
3019047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * Sets flag indicating whether the call session is pending merge into a conference or not.
3020047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     *
3021047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * @param callSessionMergePending {@code true} if a merge into the conference is pending,
3022047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     *      {@code false} otherwise.
3023047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     */
3024047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    private void setCallSessionMergePending(boolean callSessionMergePending) {
3025047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        mCallSessionMergePending = callSessionMergePending;
3026047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    }
3027047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
3028047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    /**
3029047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * Determines if there is a conference merge in process.  If there is a merge in process,
3030047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * determines if both the merge host and peer sessions have completed the merge process.  This
3031047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * means that we have received terminate or hold signals for the sessions, indicating that they
3032047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * are no longer in the process of being merged into the conference.
3033047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * <p>
3034c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * The sessions are considered to have merged if: both calls still have merge peer/host
3035c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * relationships configured,  both sessions are not waiting to be merged into the conference,
3036c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * and the transient conference session is alive in the case of an initial conference.
3037047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     *
3038047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * @return {@code true} where the host and peer sessions have finished merging into the
3039047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     *      conference, {@code false} if the merge has not yet completed, and {@code false} if there
3040047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     *      is no conference merge in progress.
3041047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     */
3042c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    private boolean shouldProcessConferenceResult() {
3043c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        boolean areMergeTriggersDone = false;
3044c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
3045c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        synchronized (ImsCall.this) {
3046c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // if there is a merge going on, then the merge host/peer relationships should have been
3047c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // set up.  This works for both the initial conference or merging a call into an
3048c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // existing conference.
3049c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            if (!isMergeHost() && !isMergePeer()) {
30506804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                if (CONF_DBG) {
30516804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    loge("shouldProcessConferenceResult :: no merge in progress");
3052c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                }
3053c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                return false;
3054c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            }
3055047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
3056c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // There is a merge in progress, so check the sessions to ensure:
3057c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // 1. Both calls have completed being merged (or failing to merge) into the conference.
3058c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // 2. The transient conference session is alive.
3059c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            if (isMergeHost()) {
30606804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                if (CONF_DBG) {
30616804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    logi("shouldProcessConferenceResult :: We are a merge host");
30626804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    logi("shouldProcessConferenceResult :: Here is the merge peer=" + mMergePeer);
3063c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                }
3064c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                areMergeTriggersDone = !isCallSessionMergePending() &&
3065c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                        !mMergePeer.isCallSessionMergePending();
3066c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                if (!isMultiparty()) {
3067c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // Only check the transient session when there is no existing conference
3068c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    areMergeTriggersDone &= isSessionAlive(mTransientConferenceSession);
3069c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                }
3070c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            } else if (isMergePeer()) {
30716804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                if (CONF_DBG) {
30726804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    logi("shouldProcessConferenceResult :: We are a merge peer");
30736804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    logi("shouldProcessConferenceResult :: Here is the merge host=" + mMergeHost);
3074c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                }
3075c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                areMergeTriggersDone = !isCallSessionMergePending() &&
3076c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                        !mMergeHost.isCallSessionMergePending();
3077c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                if (!mMergeHost.isMultiparty()) {
3078c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // Only check the transient session when there is no existing conference
3079c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    areMergeTriggersDone &= isSessionAlive(mMergeHost.mTransientConferenceSession);
3080c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                } else {
3081c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // This else block is a special case for Verizon to handle these steps
3082c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // 1. Establish a conference call.
3083c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // 2. Add a new call (conference in in BG)
3084c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // 3. Swap (conference active on FG)
3085c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // 4. Merge
3086c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // What happens here is that the BG call gets a terminated callback
3087c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // because it was added to the conference. I've seen where
3088c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // the FG gets no callback at all because its already active.
3089c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // So if we continue to wait for it to set its isCallSessionMerging
3090c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // flag to false...we'll be waiting forever.
3091c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    areMergeTriggersDone = !isCallSessionMergePending();
3092c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                }
3093c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            } else {
3094c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // Realistically this shouldn't happen, but best to be safe.
3095c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                loge("shouldProcessConferenceResult : merge in progress but call is neither" +
30966804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                        " host nor peer.");
3097c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            }
30986804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            if (CONF_DBG) {
30996804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("shouldProcessConferenceResult :: returning:" +
3100c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                        (areMergeTriggersDone ? "true" : "false"));
3101c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            }
3102047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        }
3103c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        return areMergeTriggersDone;
3104047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    }
3105047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
3106047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    /**
3107168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     * Provides a string representation of the {@link ImsCall}.  Primarily intended for use in log
3108168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     * statements.
3109168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     *
3110168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     * @return String representation of call.
3111168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     */
3112168c634eef29f21c73129164207d04b8cce23738Tyler Gunn    @Override
3113168c634eef29f21c73129164207d04b8cce23738Tyler Gunn    public String toString() {
3114168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        StringBuilder sb = new StringBuilder();
3115168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        sb.append("[ImsCall objId:");
3116168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        sb.append(System.identityHashCode(this));
31179bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        sb.append(" onHold:");
31189bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        sb.append(isOnHold() ? "Y" : "N");
31199bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        sb.append(" mute:");
31209bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        sb.append(isMuted() ? "Y" : "N");
312150b03e9261c7717817ebfb8e4086f949d0ad9c18Pavel Zhamaitsiak        if (mCallProfile != null) {
312250b03e9261c7717817ebfb8e4086f949d0ad9c18Pavel Zhamaitsiak            sb.append(" tech:");
312350b03e9261c7717817ebfb8e4086f949d0ad9c18Pavel Zhamaitsiak            sb.append(mCallProfile.getCallExtra(ImsCallProfile.EXTRA_CALL_RAT_TYPE));
312450b03e9261c7717817ebfb8e4086f949d0ad9c18Pavel Zhamaitsiak        }
31259bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        sb.append(" updateRequest:");
31269bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        sb.append(updateRequestToString(mUpdateRequest));
312787466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn        sb.append(" merging:");
312887466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn        sb.append(isMerging() ? "Y" : "N");
312987466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn        if (isMerging()) {
313087466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn            if (isMergePeer()) {
313187466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                sb.append("P");
313287466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn            } else {
313387466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                sb.append("H");
313487466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn            }
313587466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn        }
3136c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        sb.append(" merge action pending:");
3137c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        sb.append(isCallSessionMergePending() ? "Y" : "N");
313887466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn        sb.append(" merged:");
313987466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn        sb.append(isMerged() ? "Y" : "N");
3140168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        sb.append(" multiParty:");
31419bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        sb.append(isMultiparty() ? "Y" : "N");
314225394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn        sb.append(" confHost:");
314325394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn        sb.append(isConferenceHost() ? "Y" : "N");
3144c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        sb.append(" buried term:");
3145c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        sb.append(mSessionEndDuringMerge ? "Y" : "N");
3146168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        sb.append(" session:");
3147168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        sb.append(mSession);
3148168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        sb.append(" transientSession:");
3149168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        sb.append(mTransientConferenceSession);
3150168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        sb.append("]");
3151168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        return sb.toString();
3152168c634eef29f21c73129164207d04b8cce23738Tyler Gunn    }
31536804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
31546804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    private void throwImsException(Throwable t, int code) throws ImsException {
31556804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        if (t instanceof ImsException) {
31566804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            throw (ImsException) t;
31576804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        } else {
31586804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            throw new ImsException(String.valueOf(code), t, code);
31596804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        }
31606804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    }
31616804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
31626804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    /**
31636804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     * Append the ImsCall information to the provided string. Usefull for as a logging helper.
31646804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     * @param s The original string
31656804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     * @return The original string with {@code ImsCall} information appended to it.
31666804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     */
31676804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    private String appendImsCallInfoToString(String s) {
31686804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        StringBuilder sb = new StringBuilder();
31696804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        sb.append(s);
31706804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        sb.append(" ImsCall=");
31716804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        sb.append(ImsCall.this);
31726804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        return sb.toString();
31736804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    }
31746804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
31756804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    /**
31766804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     * Log a string to the radio buffer at the info level.
31776804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     * @param s The message to log
31786804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     */
31796804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    private void logi(String s) {
31806804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        Log.i(TAG, appendImsCallInfoToString(s));
31816804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    }
31826804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
31836804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    /**
31846804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     * Log a string to the radio buffer at the debug level.
31856804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     * @param s The message to log
31866804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     */
31876804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    private void logd(String s) {
31886804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        Log.d(TAG, appendImsCallInfoToString(s));
31896804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    }
31906804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
31916804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    /**
31926804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     * Log a string to the radio buffer at the verbose level.
31936804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     * @param s The message to log
31946804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     */
31956804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    private void logv(String s) {
31966804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        Log.v(TAG, appendImsCallInfoToString(s));
31976804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    }
31986804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
31996804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    /**
32006804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     * Log a string to the radio buffer at the error level.
32016804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     * @param s The message to log
32026804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     */
32036804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    private void loge(String s) {
32046804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        Log.e(TAG, appendImsCallInfoToString(s));
32056804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    }
32066804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
32076804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    /**
32086804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     * Log a string to the radio buffer at the error level with a throwable
32096804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     * @param s The message to log
32106804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     * @param t The associated throwable
32116804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     */
32126804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    private void loge(String s, Throwable t) {
32136804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        Log.e(TAG, appendImsCallInfoToString(s), t);
32146804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    }
32156804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
3216ef36ef67e009449300b0150c60c9f637e205d79eWink Saville}
3217