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;
31bd3f377399138291ffcd072f4572be84c87dfa44Hall Liuimport android.os.Parcel;
325965614f5b813f2739722589f84cec69c572b0a2Tyler Gunnimport android.telecom.ConferenceParticipant;
335aec2e957365f20b2e75d3b8c7034e3289729b81Rekha Kumarimport android.telecom.Connection;
34fb688ca8113d6dae87e2d18ea29f09c630360c03Shunta Sakaiimport android.telephony.Rlog;
3595be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingamimport java.util.Objects;
36b42ff55315201e1c971ff601eab6a5e645f8641dJack Yuimport java.util.concurrent.atomic.AtomicInteger;
371ac24854dba02556692dbbd779434e5596f6daedTyler Gunn
381ac24854dba02556692dbbd779434e5596f6daedTyler Gunnimport android.telephony.ServiceState;
399bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunnimport android.util.Log;
40ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
41ef36ef67e009449300b0150c60c9f637e205d79eWink Savilleimport com.android.ims.internal.ICall;
42ef36ef67e009449300b0150c60c9f637e205d79eWink Savilleimport com.android.ims.internal.ImsCallSession;
43ef36ef67e009449300b0150c60c9f637e205d79eWink Savilleimport com.android.ims.internal.ImsStreamMediaSession;
44938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunnimport com.android.internal.annotations.VisibleForTesting;
45ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
46ef36ef67e009449300b0150c60c9f637e205d79eWink Saville/**
47ef36ef67e009449300b0150c60c9f637e205d79eWink Saville * Handles an IMS voice / video call over LTE. You can instantiate this class with
48ef36ef67e009449300b0150c60c9f637e205d79eWink Saville * {@link ImsManager}.
49ef36ef67e009449300b0150c60c9f637e205d79eWink Saville *
50ef36ef67e009449300b0150c60c9f637e205d79eWink Saville * @hide
51ef36ef67e009449300b0150c60c9f637e205d79eWink Saville */
52ef36ef67e009449300b0150c60c9f637e205d79eWink Savillepublic class ImsCall implements ICall {
53ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // Mode of USSD message
54ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public static final int USSD_MODE_NOTIFY = 0;
55ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public static final int USSD_MODE_REQUEST = 1;
56ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
57ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final String TAG = "ImsCall";
586804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
596804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    // This flag is meant to be used as a debugging tool to quickly see all logs
606804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    // regardless of the actual log level set on this component.
616cb99be298f8b1b4363fdacc1cc631c3671380ecTyler Gunn    private static final boolean FORCE_DEBUG = false; /* STOPSHIP if true */
626804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
636804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    // We will log messages guarded by these flags at the info level. If logging is required
646804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    // to occur at (and only at) a particular log level, please use the logd, logv and loge
656804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    // functions as those will not be affected by the value of FORCE_DEBUG at all.
666804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    // Otherwise, anything guarded by these flags will be logged at the info level since that
676804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    // level allows those statements ot be logged by default which supports the workflow of
686804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    // setting FORCE_DEBUG and knowing these logs will show up regardless of the actual log
696804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    // level of this component.
706804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    private static final boolean DBG = FORCE_DEBUG || Log.isLoggable(TAG, Log.DEBUG);
716804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    private static final boolean VDBG = FORCE_DEBUG || Log.isLoggable(TAG, Log.VERBOSE);
726804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    // This is a special flag that is used only to highlight specific log around bringing
736804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    // up and tearing down conference calls. At times, these errors are transient and hard to
746804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    // reproduce so we need to capture this information the first time.
756804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    // TODO: Set this flag to FORCE_DEBUG once the new conference call logic gets more mileage
766804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    // across different IMS implementations.
776804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    private static final boolean CONF_DBG = true;
78ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
79a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam    private List<ConferenceParticipant> mConferenceParticipants;
80ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
81ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Listener for events relating to an IMS call, such as when a call is being
82c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * received ("on ringing") or a call is outgoing ("on calling").
83ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * <p>Many of these events are also received by {@link ImsCallSession.Listener}.</p>
84ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
85ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public static class Listener {
86ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
87ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when a request is sent out to initiate a new call
88ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * and 1xx response is received from the network.
89ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
90ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
91ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
92ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
93ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallProgressing(ImsCall call) {
94ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallStateChanged(call);
95ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
96ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
97ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
98ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call is established.
99ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
100ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
101ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
102ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
103ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallStarted(ImsCall call) {
104ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallStateChanged(call);
105ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
106ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
107ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
108ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call setup is failed.
109ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallError}.
110ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
111ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
112ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the call setup failure
113ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
114ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallStartFailed(ImsCall call, ImsReasonInfo reasonInfo) {
115ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallError(call, reasonInfo);
116ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
117ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
118ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
119ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call is terminated.
120ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
121ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
122ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
123ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the call termination
124ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
125ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallTerminated(ImsCall call, ImsReasonInfo reasonInfo) {
126ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // Store the call termination reason
127ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
128ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallStateChanged(call);
129ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
130ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
131ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
132ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call is in hold.
133ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
134ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
135ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
136ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
137ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallHeld(ImsCall call) {
138ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallStateChanged(call);
139ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
140ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
141ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
142ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call hold is failed.
143ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallError}.
144ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
145ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
146ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the call hold failure
147ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
148ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallHoldFailed(ImsCall call, ImsReasonInfo reasonInfo) {
149ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallError(call, reasonInfo);
150ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
151ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
152ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
153ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call hold is received from the remote user.
154ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
155ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
156ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
157ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
158ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallHoldReceived(ImsCall call) {
159ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallStateChanged(call);
160ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
161ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
162ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
163ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call is in call.
164ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
165ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
166ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
167ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
168ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallResumed(ImsCall call) {
169ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallStateChanged(call);
170ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
171ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
172ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
173ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call resume is failed.
174ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallError}.
175ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
176ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
177ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the call resume failure
178ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
179ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallResumeFailed(ImsCall call, ImsReasonInfo reasonInfo) {
180ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallError(call, reasonInfo);
181ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
182ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
183ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
184ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call resume is received from the remote user.
185ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
186ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
187ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
188ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
189ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallResumeReceived(ImsCall call) {
190ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallStateChanged(call);
191ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
192ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
193ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
194ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call is in call.
195ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
196ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
19795be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam         * @param call the call object that carries out the active IMS call
19895be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam         * @param peerCall the call object that carries out the held IMS call
199047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn         * @param swapCalls {@code true} if the foreground and background calls should be swapped
200047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn         *                              now that the merge has completed.
201ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
20295be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam        public void onCallMerged(ImsCall call, ImsCall peerCall, boolean swapCalls) {
20371382693cbc81b1d131085f52d97879976706f55Anthony Lee            onCallStateChanged(call);
204ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
205ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
206ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
207ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call merge is failed.
208ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallError}.
209ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
210ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
211ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the call merge failure
212ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
213ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallMergeFailed(ImsCall call, ImsReasonInfo reasonInfo) {
214ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallError(call, reasonInfo);
215ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
216ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
217ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
218ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call is updated (except for hold/unhold).
219ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
220ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
221ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
222ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
223ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallUpdated(ImsCall call) {
224ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallStateChanged(call);
225ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
226ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
227ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
228ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call update is failed.
229ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallError}.
230ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
231ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
232ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the call update failure
233ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
234ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallUpdateFailed(ImsCall call, ImsReasonInfo reasonInfo) {
235ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallError(call, reasonInfo);
236ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
237ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
238ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
239ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call update is received from the remote user.
240ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
241ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
242ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
243ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallUpdateReceived(ImsCall call) {
244ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
245ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
246ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
247ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
248ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call is extended to the conference call.
249ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallStateChanged}.
250ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
251ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
252ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param newCall the call object that is extended to the conference from the active call
253ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
254ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallConferenceExtended(ImsCall call, ImsCall newCall) {
25571382693cbc81b1d131085f52d97879976706f55Anthony Lee            onCallStateChanged(call);
256ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
257ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
258ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
259ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the conference extension is failed.
260ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * The default implementation calls {@link #onCallError}.
261ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
262ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
263ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the conference extension failure
264ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
265ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallConferenceExtendFailed(ImsCall call,
266ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsReasonInfo reasonInfo) {
267ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onCallError(call, reasonInfo);
268ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
269ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
270ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
271ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the conference extension is received from the remote user.
272ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
273ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
274ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param newCall the call object that is extended to the conference from the active call
275ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
276ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallConferenceExtendReceived(ImsCall call, ImsCall newCall) {
27771382693cbc81b1d131085f52d97879976706f55Anthony Lee            onCallStateChanged(call);
278ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
279ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
280ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
281ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the invitation request of the participants is delivered to
282ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * the conference server.
283ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
284ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
285ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
286ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallInviteParticipantsRequestDelivered(ImsCall call) {
287ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
288ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
289ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
290ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
291ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the invitation request of the participants is failed.
292ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
293ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
294ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the conference invitation failure
295ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
296ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallInviteParticipantsRequestFailed(ImsCall call,
297ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsReasonInfo reasonInfo) {
298ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
299ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
300ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
301ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
302ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the removal request of the participants is delivered to
303ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * the conference server.
304ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
305ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
306ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
307ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallRemoveParticipantsRequestDelivered(ImsCall call) {
308ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
309ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
310ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
311ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
312ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the removal request of the participants is failed.
313ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
314ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
315ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of the conference removal failure
316ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
317ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallRemoveParticipantsRequestFailed(ImsCall call,
318ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsReasonInfo reasonInfo) {
319ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
320ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
321ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
322ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
323ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the conference state is updated.
324ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
325ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
326ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param state state of the participant who is participated in the conference call
327ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
328ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallConferenceStateUpdated(ImsCall call, ImsConferenceState state) {
329ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
330ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
331ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
332ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
3331c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn         * Called when the state of IMS conference participant(s) has changed.
3345965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn         *
3355965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn         * @param call the call object that carries out the IMS call.
3361c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn         * @param participants the participant(s) and their new state information.
3375965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn         */
3381c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn        public void onConferenceParticipantsStateChanged(ImsCall call,
3391c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn                List<ConferenceParticipant> participants) {
3405965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn            // no-op
3415965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn        }
3425965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn
3435965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn        /**
344ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the USSD message is received from the network.
345ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
346ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param mode mode of the USSD message (REQUEST / NOTIFY)
347ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param ussdMessage USSD message
348ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
349ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallUssdMessageReceived(ImsCall call,
350ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                int mode, String ussdMessage) {
351ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
352ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
353ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
354ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
355ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when an error occurs. The default implementation is no op.
356ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * overridden. The default implementation is no op. Error events are
357ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * not re-directed to this callback and are handled in {@link #onCallError}.
358ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
359ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
360ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param reasonInfo detailed reason of this error
361ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @see ImsReasonInfo
362ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
363ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallError(ImsCall call, ImsReasonInfo reasonInfo) {
364ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
365ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
366ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
367ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
368ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when an event occurs and the corresponding callback is not
369ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * overridden. The default implementation is no op. Error events are
370ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * not re-directed to this callback and are handled in {@link #onCallError}.
371ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
372ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
373ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
374ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallStateChanged(ImsCall call) {
375ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
376ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
377ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
378ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        /**
379ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * Called when the call moves the hold state to the conversation state.
380ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * For example, when merging the active & hold call, the state of all the hold call
381ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * will be changed from hold state to conversation state.
382ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * This callback method can be invoked even though the application does not trigger
383ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * any operations.
384ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *
385ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param call the call object that carries out the IMS call
386ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         * @param state the detailed state of call state changes;
387ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         *      Refer to CALL_STATE_* in {@link ImsCall}
388ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         */
389ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void onCallStateChanged(ImsCall call, int state) {
390ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // no-op
391ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
392a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak
393a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak        /**
394d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh         * Called when the call supp service is received
395d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh         * The default implementation calls {@link #onCallStateChanged}.
396d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh         *
397d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh         * @param call the call object that carries out the IMS call
398d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh         */
399d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh        public void onCallSuppServiceReceived(ImsCall call,
400d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh            ImsSuppServiceNotification suppServiceInfo) {
401d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh        }
402d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh
403d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh        /**
404a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak         * Called when TTY mode of remote party changed
405a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak         *
406a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak         * @param call the call object that carries out the IMS call
407a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak         * @param mode TTY mode of remote party
408a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak         */
409a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak        public void onCallSessionTtyModeReceived(ImsCall call, int mode) {
410a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak            // no-op
411a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak        }
4121463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar
4131463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar        /**
4141463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         * Called when handover occurs from one access technology to another.
4151463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         *
4166804851b58264d7e82b09a845118d24d36c8d831Anthony Lee         * @param imsCall ImsCall object
4171463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         * @param srcAccessTech original access technology
4181463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         * @param targetAccessTech new access technology
4191463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         * @param reasonInfo
4201463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         */
4211463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar        public void onCallHandover(ImsCall imsCall, int srcAccessTech, int targetAccessTech,
4221463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            ImsReasonInfo reasonInfo) {
4231463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar        }
4241463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar
4251463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar        /**
426bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu         * Called when the remote party issues an RTT modify request
427bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu         *
428bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu         * @param imsCall ImsCall object
429bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu         */
430bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu        public void onRttModifyRequestReceived(ImsCall imsCall) {
431bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu        }
432bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu
433bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu        /**
434bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu         * Called when the remote party responds to a locally-issued RTT request.
435bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu         *
436bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu         * @param imsCall ImsCall object
437bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu         * @param status The status of the request. See
438bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu         *               {@link Connection.RttModifyStatus} for possible values.
439bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu         */
440bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu        public void onRttModifyResponseReceived(ImsCall imsCall, int status) {
441bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu        }
442bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu
443bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu        /**
444bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu         * Called when the remote party has sent some characters via RTT
445bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu         *
446bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu         * @param imsCall ImsCall object
447bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu         * @param message A string containing the transmitted characters.
448bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu         */
449bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu        public void onRttMessageReceived(ImsCall imsCall, String message) {
450bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu        }
451bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu
452bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu        /**
4531463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         * Called when handover from one access technology to another fails.
4541463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         *
4556804851b58264d7e82b09a845118d24d36c8d831Anthony Lee         * @param imsCall call that failed the handover.
4561463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         * @param srcAccessTech original access technology
4571463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         * @param targetAccessTech new access technology
4581463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         * @param reasonInfo
4591463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar         */
4601463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar        public void onCallHandoverFailed(ImsCall imsCall, int srcAccessTech, int targetAccessTech,
4611463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            ImsReasonInfo reasonInfo) {
4621463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar        }
46325394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn
46425394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn        /**
46525394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn         * Notifies of a change to the multiparty state for this {@code ImsCall}.
46625394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn         *
46725394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn         * @param imsCall The IMS call.
46825394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn         * @param isMultiParty {@code true} if the call became multiparty, {@code false}
46925394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn         *      otherwise.
47025394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn         */
47125394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn        public void onMultipartyStateChanged(ImsCall imsCall, boolean isMultiParty) {
47225394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn        }
473ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
474ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
475ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // List of update operation for IMS call control
476ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_NONE = 0;
477ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_HOLD = 1;
478ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_HOLD_MERGE = 2;
479ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_RESUME = 3;
480ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_MERGE = 4;
481ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_EXTEND_TO_CONFERENCE = 5;
482ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private static final int UPDATE_UNSPECIFIED = 6;
483ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
484ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // For synchronization of private variables
485ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private Object mLockObj = new Object();
486ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private Context mContext;
487ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
488ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // true if the call is established & in the conversation state
489ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private boolean mInCall = false;
490ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // true if the call is on hold
491ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // If it is triggered by the local, mute the call. Otherwise, play local hold tone
492ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // or network generated media.
493ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private boolean mHold = false;
494ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // true if the call is on mute
495ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private boolean mMute = false;
496ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // It contains the exclusive call update request. Refer to UPDATE_*.
497ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private int mUpdateRequest = UPDATE_NONE;
498ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
499ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsCall.Listener mListener = null;
5009bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
5019bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    // When merging two calls together, the "peer" call that will merge into this call.
5029bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    private ImsCall mMergePeer = null;
5039bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    // When merging two calls together, the "host" call we are merging into.
5049bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    private ImsCall mMergeHost = null;
505ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
50695be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam    // True if Conference request was initiated by
50795be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam    // Foreground Conference call else it will be false
50895be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam    private boolean mMergeRequestedByConference = false;
509ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // Wrapper call session to interworking the IMS service (server).
510ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsCallSession mSession = null;
511ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // Call profile of the current session.
512ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // It can be changed at anytime when the call is updated.
513ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsCallProfile mCallProfile = null;
514ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // Call profile to be updated after the application's action (accept/reject)
515ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // to the call update. After the application's action (accept/reject) is done,
516ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // it will be set to null.
517ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsCallProfile mProposedCallProfile = null;
518ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsReasonInfo mLastReasonInfo = null;
519ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
520ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    // Media session to control media (audio/video) operations for an IMS call
521ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsStreamMediaSession mMediaSession = null;
522ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
523b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // The temporary ImsCallSession that could represent the merged call once
524b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // we receive notification that the merge was successful.
52571382693cbc81b1d131085f52d97879976706f55Anthony Lee    private ImsCallSession mTransientConferenceSession = null;
526b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // While a merge is progressing, we bury any session termination requests
527b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // made on the original ImsCallSession until we have closure on the merge request
528b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // If the request ultimately fails, we need to act on the termination request
529b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // that we buried temporarily. We do this because we feel that timing issues could
530b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // cause the termination request to occur just because the merge is succeeding.
531b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    private boolean mSessionEndDuringMerge = false;
532b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // Just like mSessionEndDuringMerge, we need to keep track of the reason why the
533b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // termination request was made on the original session in case we need to act
534b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    // on it in the case of a merge failure.
535b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    private ImsReasonInfo mSessionEndDuringMergeReasonInfo = null;
536c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    // This flag is used to indicate if this ImsCall was merged into a conference
537c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    // or not.  It is used primarily to determine if a disconnect sound should
538c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    // be heard when the call is terminated.
5398ae59492156d9cef275f559c5ee09a44315989beAndrew Lee    private boolean mIsMerged = false;
540c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    // If true, this flag means that this ImsCall is in the process of merging
541c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    // into a conference but it does not yet have closure on if it was
542c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    // actually added to the conference or not. false implies that it either
543c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    // is not part of a merging conference or already knows if it was
544c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    // successfully added.
545047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    private boolean mCallSessionMergePending = false;
546047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
547ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
54895d563ed2a215d67a4f789c3ebb5a526fb95cc7fTyler Gunn     * If {@code true}, this flag indicates that a request to terminate the call was made by
54995d563ed2a215d67a4f789c3ebb5a526fb95cc7fTyler Gunn     * Telephony (could be from the user or some internal telephony logic)
55095d563ed2a215d67a4f789c3ebb5a526fb95cc7fTyler Gunn     * and that when we receive a {@link #processCallTerminated(ImsReasonInfo)} callback from the
55195d563ed2a215d67a4f789c3ebb5a526fb95cc7fTyler Gunn     * radio indicating that the call was terminated, we should override any burying of the
55295d563ed2a215d67a4f789c3ebb5a526fb95cc7fTyler Gunn     * termination due to an ongoing conference merge.
55395d563ed2a215d67a4f789c3ebb5a526fb95cc7fTyler Gunn     */
55495d563ed2a215d67a4f789c3ebb5a526fb95cc7fTyler Gunn    private boolean mTerminationRequestPending = false;
55595d563ed2a215d67a4f789c3ebb5a526fb95cc7fTyler Gunn
55695d563ed2a215d67a4f789c3ebb5a526fb95cc7fTyler Gunn    /**
55725394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn     * For multi-party IMS calls (e.g. conferences), determines if this {@link ImsCall} is the one
55825394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn     * hosting the call.  This is used to distinguish between a situation where an {@link ImsCall}
55925394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn     * is {@link #isMultiparty()} because calls were merged on the device, and a situation where
56025394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn     * an {@link ImsCall} is {@link #isMultiparty()} because it is a member of a conference started
56125394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn     * on another device.
56225394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn     * <p>
56325394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn     * When {@code true}, this {@link ImsCall} is is the origin of the conference call.
56425394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn     * When {@code false}, this {@link ImsCall} is a member of a conference started on another
56525394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn     * device.
56625394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn     */
56725394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn    private boolean mIsConferenceHost = false;
56825394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn
56925394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn    /**
5701ac24854dba02556692dbbd779434e5596f6daedTyler Gunn     * Tracks whether this {@link ImsCall} has been a video call at any point in its lifetime.
5711ac24854dba02556692dbbd779434e5596f6daedTyler Gunn     * Some examples of calls which are/were video calls:
5721ac24854dba02556692dbbd779434e5596f6daedTyler Gunn     * 1. A call which has been a video call for its duration.
5731ac24854dba02556692dbbd779434e5596f6daedTyler Gunn     * 2. An audio call upgraded to video (and potentially downgraded to audio later).
5741ac24854dba02556692dbbd779434e5596f6daedTyler Gunn     * 3. A call answered as video which was downgraded to audio.
5751ac24854dba02556692dbbd779434e5596f6daedTyler Gunn     */
5761ac24854dba02556692dbbd779434e5596f6daedTyler Gunn    private boolean mWasVideoCall = false;
5771ac24854dba02556692dbbd779434e5596f6daedTyler Gunn
5781ac24854dba02556692dbbd779434e5596f6daedTyler Gunn    /**
579b42ff55315201e1c971ff601eab6a5e645f8641dJack Yu     * Unique id generator used to generate call id.
580b42ff55315201e1c971ff601eab6a5e645f8641dJack Yu     */
581b42ff55315201e1c971ff601eab6a5e645f8641dJack Yu    private static final AtomicInteger sUniqueIdGenerator = new AtomicInteger();
582b42ff55315201e1c971ff601eab6a5e645f8641dJack Yu
583b42ff55315201e1c971ff601eab6a5e645f8641dJack Yu    /**
584b42ff55315201e1c971ff601eab6a5e645f8641dJack Yu     * Unique identifier.
585b42ff55315201e1c971ff601eab6a5e645f8641dJack Yu     */
586b42ff55315201e1c971ff601eab6a5e645f8641dJack Yu    public final int uniqueId;
587b42ff55315201e1c971ff601eab6a5e645f8641dJack Yu
588b42ff55315201e1c971ff601eab6a5e645f8641dJack Yu    /**
589afb53c826d0f4614311a93d24a9bf8fe2b0a51a5Tyler Gunn     * The current ImsCallSessionListenerProxy.
590afb53c826d0f4614311a93d24a9bf8fe2b0a51a5Tyler Gunn     */
591afb53c826d0f4614311a93d24a9bf8fe2b0a51a5Tyler Gunn    private ImsCallSessionListenerProxy mImsCallSessionListenerProxy;
592afb53c826d0f4614311a93d24a9bf8fe2b0a51a5Tyler Gunn
593afb53c826d0f4614311a93d24a9bf8fe2b0a51a5Tyler Gunn    /**
59425a72fccf3313ab46a1dd03096f8944a96499406Tyler Gunn     * When calling {@link #terminate(int, int)}, an override for the termination reason which the
59525a72fccf3313ab46a1dd03096f8944a96499406Tyler Gunn     * modem returns.
59625a72fccf3313ab46a1dd03096f8944a96499406Tyler Gunn     *
59725a72fccf3313ab46a1dd03096f8944a96499406Tyler Gunn     * Necessary because passing in an unexpected {@link ImsReasonInfo} reason code to
59825a72fccf3313ab46a1dd03096f8944a96499406Tyler Gunn     * {@link #terminate(int)} will cause the modem to ignore the terminate request.
59925a72fccf3313ab46a1dd03096f8944a96499406Tyler Gunn     */
60025a72fccf3313ab46a1dd03096f8944a96499406Tyler Gunn    private int mOverrideReason = ImsReasonInfo.CODE_UNSPECIFIED;
60125a72fccf3313ab46a1dd03096f8944a96499406Tyler Gunn
60225a72fccf3313ab46a1dd03096f8944a96499406Tyler Gunn    /**
603ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Create an IMS call object.
604ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
605ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param context the context for accessing system services
606ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param profile the call profile to make/take a call
607ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
608ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsCall(Context context, ImsCallProfile profile) {
609ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mContext = context;
6101ac24854dba02556692dbbd779434e5596f6daedTyler Gunn        setCallProfile(profile);
611b42ff55315201e1c971ff601eab6a5e645f8641dJack Yu        uniqueId = sUniqueIdGenerator.getAndIncrement();
612ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
613ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
614ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
615ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Closes this object. This object is not usable after being closed.
616ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
617ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    @Override
618ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void close() {
619ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
620ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession != null) {
621ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mSession.close();
622ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mSession = null;
62395be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam            } else {
62495be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                logi("close :: Cannot close Null call session!");
625ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
626ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
627ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mCallProfile = null;
628ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mProposedCallProfile = null;
629ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mLastReasonInfo = null;
630ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mMediaSession = null;
631ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
632ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
633ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
634ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
635ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Checks if the call has a same remote user identity or not.
636ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
637ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param userId the remote user identity
638ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return true if the remote user identity is equal; otherwise, false
639ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
640ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    @Override
641ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public boolean checkIfRemoteUserIsSame(String userId) {
642ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (userId == null) {
643ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return false;
644ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
645ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
646ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        return userId.equals(mCallProfile.getCallExtra(ImsCallProfile.EXTRA_REMOTE_URI, ""));
647ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
648ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
649ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
650ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Checks if the call is equal or not.
651ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
652ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param call the call to be compared
653ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return true if the call is equal; otherwise, false
654ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
655ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    @Override
656ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public boolean equalsTo(ICall call) {
657ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (call == null) {
658ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return false;
659ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
660ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
661ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (call instanceof ImsCall) {
66216b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen            return this.equals(call);
663ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
664ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
665ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        return false;
666ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
667ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
668c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    public static boolean isSessionAlive(ImsCallSession session) {
669c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        return session != null && session.isAlive();
670c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    }
671c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
672ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
673ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the negotiated (local & remote) call profile.
674ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
675ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return a {@link ImsCallProfile} object that has the negotiated call profile
676ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
677ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsCallProfile getCallProfile() {
678ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
679ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mCallProfile;
680ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
681ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
682ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
683ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
6841ac24854dba02556692dbbd779434e5596f6daedTyler Gunn     * Replaces the current call profile with a new one, tracking whethere this was previously a
6851ac24854dba02556692dbbd779434e5596f6daedTyler Gunn     * video call or not.
6861ac24854dba02556692dbbd779434e5596f6daedTyler Gunn     *
6871ac24854dba02556692dbbd779434e5596f6daedTyler Gunn     * @param profile The new call profile.
6881ac24854dba02556692dbbd779434e5596f6daedTyler Gunn     */
6891ac24854dba02556692dbbd779434e5596f6daedTyler Gunn    private void setCallProfile(ImsCallProfile profile) {
6901ac24854dba02556692dbbd779434e5596f6daedTyler Gunn        synchronized(mLockObj) {
6911ac24854dba02556692dbbd779434e5596f6daedTyler Gunn            mCallProfile = profile;
6921ac24854dba02556692dbbd779434e5596f6daedTyler Gunn            trackVideoStateHistory(mCallProfile);
6931ac24854dba02556692dbbd779434e5596f6daedTyler Gunn        }
6941ac24854dba02556692dbbd779434e5596f6daedTyler Gunn    }
6951ac24854dba02556692dbbd779434e5596f6daedTyler Gunn
6961ac24854dba02556692dbbd779434e5596f6daedTyler Gunn    /**
697ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the local call profile (local capabilities).
698ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
699ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return a {@link ImsCallProfile} object that has the local call profile
700ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
701ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsCallProfile getLocalCallProfile() throws ImsException {
702ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
703ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
704ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
705ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
706ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
707ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
708ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            try {
709ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return mSession.getLocalCallProfile();
710ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } catch (Throwable t) {
711ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("getLocalCallProfile :: ", t);
712ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("getLocalCallProfile()", t, 0);
713ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
714ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
715ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
716ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
717ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
718e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh     * Gets the remote call profile (remote capabilities).
719e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh     *
720e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh     * @return a {@link ImsCallProfile} object that has the remote call profile
721e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh     */
722e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh    public ImsCallProfile getRemoteCallProfile() throws ImsException {
723e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh        synchronized(mLockObj) {
724e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh            if (mSession == null) {
725e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh                throw new ImsException("No call session",
726e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
727e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh            }
728e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh
729e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh            try {
730e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh                return mSession.getRemoteCallProfile();
731e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh            } catch (Throwable t) {
732e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh                loge("getRemoteCallProfile :: ", t);
733e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh                throw new ImsException("getRemoteCallProfile()", t, 0);
734e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh            }
735e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh        }
736e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh    }
737e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh
738e871989b4d1c6590e7c280cbdd90c75ca82a877eShriram Ganesh    /**
739ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the call profile proposed by the local/remote user.
740ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
741ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return a {@link ImsCallProfile} object that has the proposed call profile
742ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
743ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsCallProfile getProposedCallProfile() {
744ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
745ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (!isInCall()) {
746ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return null;
747ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
748ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
749ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mProposedCallProfile;
750ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
751ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
752ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
753ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
754a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam     * Gets the list of conference participants currently
755a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam     * associated with this call.
756a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam     *
7573a3d8ebcc536dea3fbda0b27ac257523a0a0f8a7Tyler Gunn     * @return Copy of the list of conference participants.
758a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam     */
759a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam    public List<ConferenceParticipant> getConferenceParticipants() {
760a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam        synchronized(mLockObj) {
761a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam            logi("getConferenceParticipants :: mConferenceParticipants"
762a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam                    + mConferenceParticipants);
763108a6b728367e8e68b00cc120759ce7651cc7671Tyler Gunn            if (mConferenceParticipants == null) {
764108a6b728367e8e68b00cc120759ce7651cc7671Tyler Gunn                return null;
765108a6b728367e8e68b00cc120759ce7651cc7671Tyler Gunn            }
766108a6b728367e8e68b00cc120759ce7651cc7671Tyler Gunn            if (mConferenceParticipants.isEmpty()) {
767108a6b728367e8e68b00cc120759ce7651cc7671Tyler Gunn                return new ArrayList<ConferenceParticipant>(0);
768108a6b728367e8e68b00cc120759ce7651cc7671Tyler Gunn            }
7693a3d8ebcc536dea3fbda0b27ac257523a0a0f8a7Tyler Gunn            return new ArrayList<ConferenceParticipant>(mConferenceParticipants);
770a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam        }
771a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam    }
772a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam
773a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam    /**
774ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the state of the {@link ImsCallSession} that carries this call.
775ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * The value returned must be one of the states in {@link ImsCallSession#State}.
776ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
777ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return the session state
778ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
779ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public int getState() {
780ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
781ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
782ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return ImsCallSession.State.IDLE;
783ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
784ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
785ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mSession.getState();
786ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
787ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
788ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
789ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
790ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the {@link ImsCallSession} that carries this call.
791ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
792ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return the session object that carries this call
793ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @hide
794ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
795ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsCallSession getCallSession() {
796ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
797ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mSession;
798ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
799ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
800ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
801ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
802ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the {@link ImsStreamMediaSession} that handles the media operation of this call.
803ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Almost interface APIs are for the VT (Video Telephony).
804ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
805ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return the media session object that handles the media operation of this call
806ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @hide
807ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
808ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsStreamMediaSession getMediaSession() {
809ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
810ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mMediaSession;
811ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
812ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
813ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
814ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
815ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the specified property of this call.
816ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
817ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param name key to get the extra call information defined in {@link ImsCallProfile}
818ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return the extra call information as string
819ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
820ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public String getCallExtra(String name) throws ImsException {
821ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        // Lookup the cache
822ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
823ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
824ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // If not found, try to get the property from the remote
825ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
826ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
827ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
828ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
829ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
830ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            try {
831ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return mSession.getProperty(name);
832ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } catch (Throwable t) {
833ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("getCallExtra :: ", t);
834ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("getCallExtra()", t, 0);
835ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
836ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
837ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
838ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
839ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
840ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Gets the last reason information when the call is not established, cancelled or terminated.
841ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
842ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return the last reason information
843ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
844ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public ImsReasonInfo getLastReasonInfo() {
845ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
846ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mLastReasonInfo;
847ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
848ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
849ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
850ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
851ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Checks if the call has a pending update operation.
852ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
853ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return true if the call has a pending update operation
854ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
855ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public boolean hasPendingUpdate() {
856ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
857ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return (mUpdateRequest != UPDATE_NONE);
858ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
859ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
860ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
861ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
8626c0b0d0e83b8d06f40ec814573adc69f362704a9Tyler Gunn     * Checks if the call is pending a hold operation.
8636c0b0d0e83b8d06f40ec814573adc69f362704a9Tyler Gunn     *
8646c0b0d0e83b8d06f40ec814573adc69f362704a9Tyler Gunn     * @return true if the call is pending a hold operation.
8656c0b0d0e83b8d06f40ec814573adc69f362704a9Tyler Gunn     */
8666c0b0d0e83b8d06f40ec814573adc69f362704a9Tyler Gunn    public boolean isPendingHold() {
8676c0b0d0e83b8d06f40ec814573adc69f362704a9Tyler Gunn        synchronized(mLockObj) {
8686c0b0d0e83b8d06f40ec814573adc69f362704a9Tyler Gunn            return (mUpdateRequest == UPDATE_HOLD);
8696c0b0d0e83b8d06f40ec814573adc69f362704a9Tyler Gunn        }
8706c0b0d0e83b8d06f40ec814573adc69f362704a9Tyler Gunn    }
8716c0b0d0e83b8d06f40ec814573adc69f362704a9Tyler Gunn
8726c0b0d0e83b8d06f40ec814573adc69f362704a9Tyler Gunn    /**
873ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Checks if the call is established.
874ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
875ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return true if the call is established
876ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
877ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public boolean isInCall() {
878ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
879ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mInCall;
880ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
881ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
882ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
883ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
884ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Checks if the call is muted.
885ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
886ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return true if the call is muted
887ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
888ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public boolean isMuted() {
889ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
890ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mMute;
891ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
892ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
893ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
894ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
895ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Checks if the call is on hold.
896ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
897ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @return true if the call is on hold
898ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
899ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public boolean isOnHold() {
900ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
901ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mHold;
902ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
903ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
904ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
905ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
906725ad373383798c1516348475b1f6304484e031eTyler Gunn     * Determines if the call is a multiparty call.
907725ad373383798c1516348475b1f6304484e031eTyler Gunn     *
908725ad373383798c1516348475b1f6304484e031eTyler Gunn     * @return {@code True} if the call is a multiparty call.
909725ad373383798c1516348475b1f6304484e031eTyler Gunn     */
910725ad373383798c1516348475b1f6304484e031eTyler Gunn    public boolean isMultiparty() {
91116b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen        synchronized(mLockObj) {
91216b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen            if (mSession == null) {
91316b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen                return false;
91416b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen            }
91516b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen
91671382693cbc81b1d131085f52d97879976706f55Anthony Lee            return mSession.isMultiparty();
91716b3b36eb554d27f23b05577c6a76a9b989bdbcdEtan Cohen        }
918725ad373383798c1516348475b1f6304484e031eTyler Gunn    }
919725ad373383798c1516348475b1f6304484e031eTyler Gunn
920725ad373383798c1516348475b1f6304484e031eTyler Gunn    /**
92125394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn     * Where {@link #isMultiparty()} is {@code true}, determines if this {@link ImsCall} is the
92225394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn     * origin of the conference call (i.e. {@code #isConferenceHost()} is {@code true}), or if this
92325394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn     * {@link ImsCall} is a member of a conference hosted on another device.
92425394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn     *
92525394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn     * @return {@code true} if this call is the origin of the conference call it is a member of,
92625394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn     *      {@code false} otherwise.
92725394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn     */
92825394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn    public boolean isConferenceHost() {
92925394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn        synchronized(mLockObj) {
93025394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn            return isMultiparty() && mIsConferenceHost;
93125394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn        }
93225394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn    }
93325394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn
93425394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn    /**
9359bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * Marks whether an IMS call is merged. This should be set {@code true} when the call merges
9369bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * into a conference.
9378ae59492156d9cef275f559c5ee09a44315989beAndrew Lee     *
9388ae59492156d9cef275f559c5ee09a44315989beAndrew Lee     * @param isMerged Whether the call is merged.
9398ae59492156d9cef275f559c5ee09a44315989beAndrew Lee     */
9408ae59492156d9cef275f559c5ee09a44315989beAndrew Lee    public void setIsMerged(boolean isMerged) {
9418ae59492156d9cef275f559c5ee09a44315989beAndrew Lee        mIsMerged = isMerged;
9428ae59492156d9cef275f559c5ee09a44315989beAndrew Lee    }
9438ae59492156d9cef275f559c5ee09a44315989beAndrew Lee
9448ae59492156d9cef275f559c5ee09a44315989beAndrew Lee    /**
9459bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * @return {@code true} if the call recently merged into a conference call.
9468ae59492156d9cef275f559c5ee09a44315989beAndrew Lee     */
9478ae59492156d9cef275f559c5ee09a44315989beAndrew Lee    public boolean isMerged() {
9488ae59492156d9cef275f559c5ee09a44315989beAndrew Lee        return mIsMerged;
9498ae59492156d9cef275f559c5ee09a44315989beAndrew Lee    }
9508ae59492156d9cef275f559c5ee09a44315989beAndrew Lee
9518ae59492156d9cef275f559c5ee09a44315989beAndrew Lee    /**
952ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Sets the listener to listen to the IMS call events.
953ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * The method calls {@link #setListener setListener(listener, false)}.
954ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
955ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param listener to listen to the IMS call events of this object; null to remove listener
956ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see #setListener(Listener, boolean)
957ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
958ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void setListener(ImsCall.Listener listener) {
959ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        setListener(listener, false);
960ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
961ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
962ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
963ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Sets the listener to listen to the IMS call events.
964ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * A {@link ImsCall} can only hold one listener at a time. Subsequent calls
965ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * to this method override the previous listener.
966ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
967ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param listener to listen to the IMS call events of this object; null to remove listener
968ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param callbackImmediately set to true if the caller wants to be called
969ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *        back immediately on the current state
970ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
971ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void setListener(ImsCall.Listener listener, boolean callbackImmediately) {
972ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        boolean inCall;
973ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        boolean onHold;
974ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        int state;
975ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        ImsReasonInfo lastReasonInfo;
976ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
977ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
978ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mListener = listener;
979ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
980ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if ((listener == null) || !callbackImmediately) {
981ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return;
982ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
983ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
984ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            inCall = mInCall;
985ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            onHold = mHold;
986ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            state = getState();
987ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            lastReasonInfo = mLastReasonInfo;
988ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
989ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
990ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        try {
991ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (lastReasonInfo != null) {
992ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener.onCallError(this, lastReasonInfo);
993ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } else if (inCall) {
994ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (onHold) {
995ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallHeld(this);
996ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } else {
997ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallStarted(this);
998ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
999ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } else {
1000ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                switch (state) {
1001ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    case ImsCallSession.State.ESTABLISHING:
1002ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        listener.onCallProgressing(this);
1003ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        break;
1004ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    case ImsCallSession.State.TERMINATED:
1005ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        listener.onCallTerminated(this, lastReasonInfo);
1006ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        break;
1007ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    default:
1008ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        // Ignore it. There is no action in the other state.
1009ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        break;
1010ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1011ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1012ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        } catch (Throwable t) {
10136804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            loge("setListener() :: ", t);
1014ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1015ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1016ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1017ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1018ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Mutes or unmutes the mic for the active call.
1019ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1020ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param muted true if the call is muted, false otherwise
1021ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1022ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void setMute(boolean muted) throws ImsException {
1023ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1024ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mMute != muted) {
10256804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("setMute :: turning mute " + (muted ? "on" : "off"));
1026ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mMute = muted;
1027ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1028ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
1029ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    mSession.setMute(muted);
1030ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
1031ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("setMute :: ", t);
1032ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    throwImsException(t, 0);
1033ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1034ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1035ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1036ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1037ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1038ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     /**
1039ef36ef67e009449300b0150c60c9f637e205d79eWink Saville      * Attaches an incoming call to this call object.
1040ef36ef67e009449300b0150c60c9f637e205d79eWink Saville      *
1041ef36ef67e009449300b0150c60c9f637e205d79eWink Saville      * @param session the session that receives the incoming call
1042ef36ef67e009449300b0150c60c9f637e205d79eWink Saville      * @throws ImsException if the IMS service fails to attach this object to the session
1043ef36ef67e009449300b0150c60c9f637e205d79eWink Saville      */
1044ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     public void attachSession(ImsCallSession session) throws ImsException {
10456804851b58264d7e82b09a845118d24d36c8d831Anthony Lee         logi("attachSession :: session=" + session);
1046ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1047ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         synchronized(mLockObj) {
1048ef36ef67e009449300b0150c60c9f637e205d79eWink Saville             mSession = session;
1049ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1050ef36ef67e009449300b0150c60c9f637e205d79eWink Saville             try {
1051ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                 mSession.setListener(createCallSessionListener());
1052ef36ef67e009449300b0150c60c9f637e205d79eWink Saville             } catch (Throwable t) {
1053ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                 loge("attachSession :: ", t);
1054ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                 throwImsException(t, 0);
1055ef36ef67e009449300b0150c60c9f637e205d79eWink Saville             }
1056ef36ef67e009449300b0150c60c9f637e205d79eWink Saville         }
1057ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     }
1058ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1059ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1060ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Initiates an IMS call with the call profile which is provided
1061ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * when creating a {@link ImsCall}.
1062ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1063ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param session the {@link ImsCallSession} for carrying out the call
1064ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param callee callee information to initiate an IMS call
1065ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to initiate the call
1066ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1067ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void start(ImsCallSession session, String callee)
1068ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            throws ImsException {
10697b3107c484337a728fe12c6968570c43bc1188ecfionaxu        logi("start(1) :: session=" + session);
1070ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1071ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1072ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession = session;
1073ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1074ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            try {
1075ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                session.setListener(createCallSessionListener());
1076ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                session.start(callee, mCallProfile);
1077ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } catch (Throwable t) {
1078ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("start(1) :: ", t);
1079ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("start(1)", t, 0);
1080ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1081ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1082ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1083ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1084ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1085ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Initiates an IMS conferenca call with the call profile which is provided
1086ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * when creating a {@link ImsCall}.
1087ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1088ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param session the {@link ImsCallSession} for carrying out the call
1089ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param participants participant list to initiate an IMS conference call
1090ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to initiate the call
1091ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1092ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void start(ImsCallSession session, String[] participants)
1093ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            throws ImsException {
10947b3107c484337a728fe12c6968570c43bc1188ecfionaxu        logi("start(n) :: session=" + session);
1095ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1096ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1097ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession = session;
1098ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1099ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            try {
1100ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                session.setListener(createCallSessionListener());
1101ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                session.start(participants, mCallProfile);
1102ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } catch (Throwable t) {
1103ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("start(n) :: ", t);
1104ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("start(n)", t, 0);
1105ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1106ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1107ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1108ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1109ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1110ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Accepts a call.
1111ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1112ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallStarted
1113d1edfd8cf9ffeb191a84e08522bb570cd8cd4381Tyler Gunn     *
1114d1edfd8cf9ffeb191a84e08522bb570cd8cd4381Tyler Gunn     * @param callType The call type the user agreed to for accepting the call.
1115ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to accept the call
1116ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1117d1edfd8cf9ffeb191a84e08522bb570cd8cd4381Tyler Gunn    public void accept(int callType) throws ImsException {
1118d1edfd8cf9ffeb191a84e08522bb570cd8cd4381Tyler Gunn        accept(callType, new ImsStreamMediaProfile());
1119ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1120ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1121ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1122ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Accepts a call.
1123ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1124ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param callType call type to be answered in {@link ImsCallProfile}
1125ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param profile a media profile to be answered (audio/audio & video, direction, ...)
1126ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallStarted
1127ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to accept the call
1128ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1129ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void accept(int callType, ImsStreamMediaProfile profile) throws ImsException {
11306804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        logi("accept :: callType=" + callType + ", profile=" + profile);
1131ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1132ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1133ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1134ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call to answer",
1135ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1136ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1137ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1138ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            try {
1139ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mSession.accept(callType, profile);
1140ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } catch (Throwable t) {
1141ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("accept :: ", t);
1142ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("accept()", t, 0);
1143ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1144ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1145ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mInCall && (mProposedCallProfile != null)) {
1146ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (DBG) {
11476804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    logi("accept :: call profile will be updated");
1148ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1149ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1150ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallProfile = mProposedCallProfile;
11511ac24854dba02556692dbbd779434e5596f6daedTyler Gunn                trackVideoStateHistory(mCallProfile);
1152ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mProposedCallProfile = null;
1153ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1154ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1155ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // Other call update received
1156ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mInCall && (mUpdateRequest == UPDATE_UNSPECIFIED)) {
1157ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
1158ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1159ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1160ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1161ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1162ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1163ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Rejects a call.
1164ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1165ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param reason reason code to reject an incoming call
1166ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallStartFailed
11676804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     * @throws ImsException if the IMS service fails to reject the call
1168ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1169ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void reject(int reason) throws ImsException {
11706804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        logi("reject :: reason=" + reason);
1171ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1172ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1173ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession != null) {
1174ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mSession.reject(reason);
1175ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1176ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1177ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mInCall && (mProposedCallProfile != null)) {
1178ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (DBG) {
11796804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    logi("reject :: call profile is not updated; destroy it...");
1180ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1181ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1182ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mProposedCallProfile = null;
1183ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1184ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1185ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            // Other call update received
1186ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mInCall && (mUpdateRequest == UPDATE_UNSPECIFIED)) {
1187ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
1188ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1189ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1190ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1191ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
119225a72fccf3313ab46a1dd03096f8944a96499406Tyler Gunn    public void terminate(int reason, int overrideReason) throws ImsException {
119325a72fccf3313ab46a1dd03096f8944a96499406Tyler Gunn        logi("terminate :: reason=" + reason + " ; overrideReadon=" + overrideReason);
119425a72fccf3313ab46a1dd03096f8944a96499406Tyler Gunn        mOverrideReason = overrideReason;
119525a72fccf3313ab46a1dd03096f8944a96499406Tyler Gunn        terminate(reason);
119625a72fccf3313ab46a1dd03096f8944a96499406Tyler Gunn    }
119725a72fccf3313ab46a1dd03096f8944a96499406Tyler Gunn
1198ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
119995d563ed2a215d67a4f789c3ebb5a526fb95cc7fTyler Gunn     * Terminates an IMS call (e.g. user initiated).
1200ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1201ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param reason reason code to terminate a call
1202ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to terminate the call
1203ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1204ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void terminate(int reason) throws ImsException {
12056804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        logi("terminate :: reason=" + reason);
1206ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1207ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1208ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mHold = false;
1209ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mInCall = false;
121095d563ed2a215d67a4f789c3ebb5a526fb95cc7fTyler Gunn            mTerminationRequestPending = true;
1211ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1212ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession != null) {
1213c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // TODO: Fix the fact that user invoked call terminations during
1214c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // the process of establishing a conference call needs to be handled
1215c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // as a special case.
1216c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // Currently, any terminations (both invoked by the user or
1217c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // by the network results in a callSessionTerminated() callback
1218c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // from the network.  When establishing a conference call we bury
1219c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // these callbacks until we get closure on all participants of the
1220c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // conference. In some situations, we will throw away the callback
1221c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // (when the underlying session of the host of the new conference
1222c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // is terminated) or will will unbury it when the conference has been
1223c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // established, like when the peer of the new conference goes away
1224c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // after the conference has been created.  The UI relies on the callback
1225c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // to reflect the fact that the call is gone.
1226c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // So if a user decides to terminated a call while it is merging, it
1227c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // could take a long time to reflect in the UI due to the conference
1228c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // processing but we should probably cancel that and just terminate
1229c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // the call immediately and clean up.  This is not a huge issue right
1230c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // now because we have not seen instances where establishing a
1231c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // conference takes a long time (more than a second or two).
1232ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mSession.terminate(reason);
1233ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1234ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1235ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1236ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1237d43b5302d8edf4df90a28055f043786f542df219Uma Maheswari Ramalingam
1238ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1239ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Puts a call on hold. When succeeds, {@link Listener#onCallHeld} is called.
1240ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1241ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallHeld, Listener#onCallHoldFailed
1242ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to hold the call
1243ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1244ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void hold() throws ImsException {
12456804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        logi("hold :: ");
1246111eecc9845826e985c48133b754e453fb3aca84Etan Cohen
1247ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (isOnHold()) {
1248ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
12496804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("hold :: call is already on hold");
1250ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1251ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return;
1252ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1253ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1254ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1255ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mUpdateRequest != UPDATE_NONE) {
12569bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                loge("hold :: update is in progress; request=" +
12579bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                        updateRequestToString(mUpdateRequest));
1258ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("Call update is in progress",
1259ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
1260ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1261ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1262ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1263ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1264ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1265ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1266ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1267ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession.hold(createHoldMediaProfile());
12686804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            // FIXME: We should update the state on the callback because that is where
12696804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            // we can confirm that the hold request was successful or not.
1270ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mHold = true;
1271ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mUpdateRequest = UPDATE_HOLD;
1272ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1273ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1274ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1275ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1276ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Continues a call that's on hold. When succeeds, {@link Listener#onCallResumed} is called.
1277ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1278ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallResumed, Listener#onCallResumeFailed
1279ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to resume the call
1280ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1281ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void resume() throws ImsException {
12826804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        logi("resume :: ");
1283111eecc9845826e985c48133b754e453fb3aca84Etan Cohen
1284ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (!isOnHold()) {
1285ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
12866804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("resume :: call is not being held");
1287ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1288ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return;
1289ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1290ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1291ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1292ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mUpdateRequest != UPDATE_NONE) {
12939bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                loge("resume :: update is in progress; request=" +
12949bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                        updateRequestToString(mUpdateRequest));
1295ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("Call update is in progress",
1296ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
1297ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1298ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1299ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1300ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("resume :: ");
1301ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1302ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1303ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1304ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1305c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // mHold is set to false in confirmation callback that the
1306c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // ImsCall was resumed.
1307ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mUpdateRequest = UPDATE_RESUME;
1308c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            mSession.resume(createResumeMediaProfile());
1309ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1310ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1311ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1312ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1313ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Merges the active & hold call.
1314ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1315ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallMerged, Listener#onCallMergeFailed
1316ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to merge the call
1317ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1318047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    private void merge() throws ImsException {
13196804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        logi("merge :: ");
1320ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1321ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
13229b1723376c2f04b30b677d94f9105220a014501eTyler Gunn            // If the host of the merge is in the midst of some other operation, we cannot merge.
1323ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mUpdateRequest != UPDATE_NONE) {
13249b1723376c2f04b30b677d94f9105220a014501eTyler Gunn                setCallSessionMergePending(false);
13259b1723376c2f04b30b677d94f9105220a014501eTyler Gunn                if (mMergePeer != null) {
13269b1723376c2f04b30b677d94f9105220a014501eTyler Gunn                    mMergePeer.setCallSessionMergePending(false);
13279b1723376c2f04b30b677d94f9105220a014501eTyler Gunn                }
13289bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                loge("merge :: update is in progress; request=" +
13299bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                        updateRequestToString(mUpdateRequest));
1330ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("Call update is in progress",
1331ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
1332ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
13339b1723376c2f04b30b677d94f9105220a014501eTyler Gunn
13349b1723376c2f04b30b677d94f9105220a014501eTyler Gunn            // The peer of the merge is in the midst of some other operation, we cannot merge.
13359b1723376c2f04b30b677d94f9105220a014501eTyler Gunn            if (mMergePeer != null && mMergePeer.mUpdateRequest != UPDATE_NONE) {
13369b1723376c2f04b30b677d94f9105220a014501eTyler Gunn                setCallSessionMergePending(false);
13379b1723376c2f04b30b677d94f9105220a014501eTyler Gunn                mMergePeer.setCallSessionMergePending(false);
13389b1723376c2f04b30b677d94f9105220a014501eTyler Gunn                loge("merge :: peer call update is in progress; request=" +
13399b1723376c2f04b30b677d94f9105220a014501eTyler Gunn                        updateRequestToString(mMergePeer.mUpdateRequest));
13409b1723376c2f04b30b677d94f9105220a014501eTyler Gunn                throw new ImsException("Peer call update is in progress",
13419b1723376c2f04b30b677d94f9105220a014501eTyler Gunn                        ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
13429b1723376c2f04b30b677d94f9105220a014501eTyler Gunn            }
1343ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1344ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1345c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                loge("merge :: no call session");
1346ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1347ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1348ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1349ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1350ca45f58a57eb782153c034ae067f59c0018799caUma Maheswari Ramalingam            // if skipHoldBeforeMerge = true, IMS service implementation will
1351ca45f58a57eb782153c034ae067f59c0018799caUma Maheswari Ramalingam            // merge without explicitly holding the call.
1352ca45f58a57eb782153c034ae067f59c0018799caUma Maheswari Ramalingam            if (mHold || (mContext.getResources().getBoolean(
1353ca45f58a57eb782153c034ae067f59c0018799caUma Maheswari Ramalingam                    com.android.internal.R.bool.skipHoldBeforeMerge))) {
1354b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee
13559bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                if (mMergePeer != null && !mMergePeer.isMultiparty() && !isMultiparty()) {
13569bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                    // We only set UPDATE_MERGE when we are adding the first
13579bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                    // calls to the Conference.  If there is already a conference
1358047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                    // no special handling is needed. The existing conference
13599bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                    // session will just go active and any other sessions will be terminated
13609bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                    // if needed.  There will be no merge failed callback.
1361047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                    // Mark both the host and peer UPDATE_MERGE to ensure both are aware that a
1362047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                    // merge is pending.
13639bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                    mUpdateRequest = UPDATE_MERGE;
1364047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                    mMergePeer.mUpdateRequest = UPDATE_MERGE;
1365b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                }
13669bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
13679bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                mSession.merge();
1368ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } else {
136971382693cbc81b1d131085f52d97879976706f55Anthony Lee                // This code basically says, we need to explicitly hold before requesting a merge
137071382693cbc81b1d131085f52d97879976706f55Anthony Lee                // when we get the callback that the hold was successful (or failed), we should
137171382693cbc81b1d131085f52d97879976706f55Anthony Lee                // automatically request a merge.
1372ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mSession.hold(createHoldMediaProfile());
1373ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mHold = true;
1374ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_HOLD_MERGE;
1375ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1376ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1377ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1378ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1379ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1380ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Merges the active & hold call.
1381ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1382ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param bgCall the background (holding) call
1383ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @see Listener#onCallMerged, Listener#onCallMergeFailed
1384ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @throws ImsException if the IMS service fails to merge the call
1385ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1386ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void merge(ImsCall bgCall) throws ImsException {
13876804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        logi("merge(1) :: bgImsCall=" + bgCall);
1388ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1389ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (bgCall == null) {
1390ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            throw new ImsException("No background call",
1391ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
1392ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1393ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1394ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1395047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            // Mark both sessions as pending merge.
1396047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            this.setCallSessionMergePending(true);
1397047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            bgCall.setCallSessionMergePending(true);
1398047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
139987466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn            if ((!isMultiparty() && !bgCall.isMultiparty()) || isMultiparty()) {
140087466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                // If neither call is multiparty, the current call is the merge host and the bg call
140187466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                // is the merge peer (ie we're starting a new conference).
140287466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                // OR
140387466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                // If this call is multiparty, it is the merge host and the other call is the merge
140487466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                // peer.
140587466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                setMergePeer(bgCall);
140687466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn            } else {
140787466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                // If the bg call is multiparty, it is the merge host.
140887466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                setMergeHost(bgCall);
140987466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn            }
1410ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1411a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam
141295be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam        if (isMultiparty()) {
141395be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam            mMergeRequestedByConference = true;
141495be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam        } else {
141595be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam            logi("merge : mMergeRequestedByConference not set");
141695be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam        }
1417ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        merge();
1418ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1419ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1420ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1421ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Updates the current call's properties (ex. call mode change: video upgrade / downgrade).
1422ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1423ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void update(int callType, ImsStreamMediaProfile mediaProfile) throws ImsException {
14246804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        logi("update :: callType=" + callType + ", mediaProfile=" + mediaProfile);
1425ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1426ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (isOnHold()) {
1427ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
14286804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("update :: call is on hold");
1429ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1430ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            throw new ImsException("Not in a call to update call",
1431ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
1432ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1433ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1434ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1435ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mUpdateRequest != UPDATE_NONE) {
1436ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (DBG) {
14376804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    logi("update :: update is in progress; request=" +
14389bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                            updateRequestToString(mUpdateRequest));
1439ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1440ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("Call update is in progress",
1441ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
1442ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1443ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1444ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1445ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("update :: ");
1446ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1447ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1448ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1449ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1450ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession.update(callType, mediaProfile);
1451ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mUpdateRequest = UPDATE_UNSPECIFIED;
1452ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1453ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1454ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1455ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1456ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Extends this call (1-to-1 call) to the conference call
1457ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * inviting the specified participants to.
1458ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1459ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1460ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void extendToConference(String[] participants) throws ImsException {
14616804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        logi("extendToConference ::");
1462ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1463ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (isOnHold()) {
1464ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (DBG) {
14656804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("extendToConference :: call is on hold");
1466ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1467ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            throw new ImsException("Not in a call to extend a call to conference",
1468ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
1469ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1470ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1471ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1472ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mUpdateRequest != UPDATE_NONE) {
14736804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                if (CONF_DBG) {
14746804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    logi("extendToConference :: update is in progress; request=" +
14759bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                            updateRequestToString(mUpdateRequest));
1476ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
1477ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("Call update is in progress",
1478ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
1479ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1480ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1481ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1482ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("extendToConference :: ");
1483ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1484ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1485ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1486ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1487ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession.extendToConference(participants);
1488ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mUpdateRequest = UPDATE_EXTEND_TO_CONFERENCE;
1489ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1490ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1491ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1492ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1493ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Requests the conference server to invite an additional participants to the conference.
1494ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1495ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1496ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void inviteParticipants(String[] participants) throws ImsException {
14976804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        logi("inviteParticipants ::");
1498ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1499ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1500ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1501ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("inviteParticipants :: ");
1502ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1503ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1504ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1505ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1506ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession.inviteParticipants(participants);
1507ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1508ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1509ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1510ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1511ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Requests the conference server to remove the specified participants from the conference.
1512ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1513ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1514ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void removeParticipants(String[] participants) throws ImsException {
1515a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam        logi("removeParticipants :: session=" + mSession);
1516ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1517ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1518ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("removeParticipants :: ");
1519ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1520ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1521ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1522ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1523ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession.removeParticipants(participants);
1524a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam
1525ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1526ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1527ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1528ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1529ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Sends a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2833</a>,
1530ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * event 0 ~ 9 maps to decimal value 0 ~ 9, '*' to 10, '#' to 11, event 'A' ~ 'D' to 12 ~ 15,
1531ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * and event flash to 16. Currently, event flash is not supported.
1532ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
15332f92daf76a66d7d2fe6fb7b1a28fc1b5888a7b7cLibin.Tang@motorola.com     * @param c that represents the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs.
15342f92daf76a66d7d2fe6fb7b1a28fc1b5888a7b7cLibin.Tang@motorola.com     * @param result the result message to send when done.
1535ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
15362f92daf76a66d7d2fe6fb7b1a28fc1b5888a7b7cLibin.Tang@motorola.com    public void sendDtmf(char c, Message result) {
15376804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        logi("sendDtmf :: code=" + c);
1538ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1539ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1540ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession != null) {
1541a4710d5d926d8112179acece620f49cb79257e98Andrew Lee                mSession.sendDtmf(c, result);
1542ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1543ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1544ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1545ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1546ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1547a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam     * Start a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2833</a>,
1548a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam     * event 0 ~ 9 maps to decimal value 0 ~ 9, '*' to 10, '#' to 11, event 'A' ~ 'D' to 12 ~ 15,
1549a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam     * and event flash to 16. Currently, event flash is not supported.
1550a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam     *
1551a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam     * @param c that represents the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs.
1552a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam     */
1553a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam    public void startDtmf(char c) {
15546804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        logi("startDtmf :: code=" + c);
1555a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam
1556a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam        synchronized(mLockObj) {
1557a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam            if (mSession != null) {
1558a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam                mSession.startDtmf(c);
1559a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam            }
1560a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam        }
1561a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam    }
1562a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam
1563a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam    /**
1564a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam     * Stop a DTMF code.
1565a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam     */
1566a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam    public void stopDtmf() {
15676804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        logi("stopDtmf :: ");
1568a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam
1569a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam        synchronized(mLockObj) {
1570a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam            if (mSession != null) {
1571a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam                mSession.stopDtmf();
1572a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam            }
1573a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam        }
1574a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam    }
1575a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam
1576a6fbae9f8c793118e008a98d3576df316bf0364aUma Maheswari Ramalingam    /**
1577ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Sends an USSD message.
1578ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     *
1579ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * @param ussdMessage USSD message to send
1580ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1581ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    public void sendUssd(String ussdMessage) throws ImsException {
15826804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        logi("sendUssd :: ussdMessage=" + ussdMessage);
1583ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1584ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        synchronized(mLockObj) {
1585ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (mSession == null) {
1586ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("sendUssd :: ");
1587ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                throw new ImsException("No call session",
1588ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
1589ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1590ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1591ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mSession.sendUssd(ussdMessage);
1592ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1593ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1594ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1595bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu    public void sendRttMessage(String rttMessage) {
1596bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu        synchronized(mLockObj) {
1597bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            if (mSession == null) {
1598bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu                loge("sendRttMessage::no session");
1599bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            }
1600bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            if (!mCallProfile.mMediaProfile.isRttCall()) {
1601bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu                logi("sendRttMessage::Not an rtt call, ignoring");
1602bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu                return;
1603bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            }
1604bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            mSession.sendRttMessage(rttMessage);
1605bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu        }
1606bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu    }
1607bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu
1608bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu    /**
1609bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu     * Sends a user-requested RTT upgrade request.
1610bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu     */
1611bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu    public void sendRttModifyRequest() {
1612bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu        logi("sendRttModifyRequest");
1613bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu
1614bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu        synchronized(mLockObj) {
1615bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            if (mSession == null) {
1616bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu                loge("sendRttModifyRequest::no session");
1617bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            }
1618bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            if (mCallProfile.mMediaProfile.isRttCall()) {
1619bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu                logi("sendRttModifyRequest::Already RTT call, ignoring.");
1620bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu                return;
1621bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            }
1622bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            // Make a copy of the current ImsCallProfile and modify it to enable RTT
1623bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            Parcel p = Parcel.obtain();
1624bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            mCallProfile.writeToParcel(p, 0);
1625bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            ImsCallProfile requestedProfile = new ImsCallProfile(p);
1626bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            requestedProfile.mMediaProfile.setRttMode(ImsStreamMediaProfile.RTT_MODE_FULL);
1627bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu
1628bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            mSession.sendRttModifyRequest(requestedProfile);
1629bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu        }
1630bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu    }
1631bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu
1632bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu    /**
1633bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu     * Sends the user's response to a remotely-issued RTT upgrade request
1634bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu     *
1635bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu     * @param textStream A valid {@link Connection.RttTextStream} if the user
1636bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu     *                   accepts, {@code null} if not.
1637bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu     */
1638bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu    public void sendRttModifyResponse(boolean status) {
1639bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu        logi("sendRttModifyResponse");
1640bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu
1641bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu        synchronized(mLockObj) {
1642bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            if (mSession == null) {
1643bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu                loge("sendRttModifyResponse::no session");
1644bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            }
1645bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            if (mCallProfile.mMediaProfile.isRttCall()) {
1646bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu                logi("sendRttModifyResponse::Already RTT call, ignoring.");
1647bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu                return;
1648bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            }
1649bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            mSession.sendRttModifyResponse(status);
1650bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu        }
1651bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu    }
1652bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu
1653ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void clear(ImsReasonInfo lastReasonInfo) {
1654ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mInCall = false;
1655ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mHold = false;
1656ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mUpdateRequest = UPDATE_NONE;
1657ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mLastReasonInfo = lastReasonInfo;
1658ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1659ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1660ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    /**
1661ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     * Creates an IMS call session listener.
1662ef36ef67e009449300b0150c60c9f637e205d79eWink Saville     */
1663ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsCallSession.Listener createCallSessionListener() {
1664afb53c826d0f4614311a93d24a9bf8fe2b0a51a5Tyler Gunn        mImsCallSessionListenerProxy = new ImsCallSessionListenerProxy();
1665afb53c826d0f4614311a93d24a9bf8fe2b0a51a5Tyler Gunn        return mImsCallSessionListenerProxy;
1666afb53c826d0f4614311a93d24a9bf8fe2b0a51a5Tyler Gunn    }
1667afb53c826d0f4614311a93d24a9bf8fe2b0a51a5Tyler Gunn
1668afb53c826d0f4614311a93d24a9bf8fe2b0a51a5Tyler Gunn    /**
1669afb53c826d0f4614311a93d24a9bf8fe2b0a51a5Tyler Gunn     * @return the current ImsCallSessionListenerProxy.  NOTE: ONLY FOR USE WITH TESTING.
1670afb53c826d0f4614311a93d24a9bf8fe2b0a51a5Tyler Gunn     */
1671afb53c826d0f4614311a93d24a9bf8fe2b0a51a5Tyler Gunn    @VisibleForTesting
1672afb53c826d0f4614311a93d24a9bf8fe2b0a51a5Tyler Gunn    public ImsCallSessionListenerProxy getImsCallSessionListenerProxy() {
1673afb53c826d0f4614311a93d24a9bf8fe2b0a51a5Tyler Gunn        return mImsCallSessionListenerProxy;
1674ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1675ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1676ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsCall createNewCall(ImsCallSession session, ImsCallProfile profile) {
1677ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        ImsCall call = new ImsCall(mContext, profile);
1678ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1679ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        try {
1680ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            call.attachSession(session);
1681ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        } catch (ImsException e) {
1682ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (call != null) {
1683ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                call.close();
1684ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                call = null;
1685ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1686ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1687ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1688ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        // Do additional operations...
1689ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1690ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        return call;
1691ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1692ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1693ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsStreamMediaProfile createHoldMediaProfile() {
1694ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        ImsStreamMediaProfile mediaProfile = new ImsStreamMediaProfile();
1695ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1696ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (mCallProfile == null) {
1697ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mediaProfile;
1698ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1699ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1700ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mediaProfile.mAudioQuality = mCallProfile.mMediaProfile.mAudioQuality;
1701ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mediaProfile.mVideoQuality = mCallProfile.mMediaProfile.mVideoQuality;
1702ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mediaProfile.mAudioDirection = ImsStreamMediaProfile.DIRECTION_SEND;
1703ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1704ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (mediaProfile.mVideoQuality != ImsStreamMediaProfile.VIDEO_QUALITY_NONE) {
1705ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mediaProfile.mVideoDirection = ImsStreamMediaProfile.DIRECTION_SEND;
1706ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1707ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1708ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        return mediaProfile;
1709ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1710ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1711ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private ImsStreamMediaProfile createResumeMediaProfile() {
1712ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        ImsStreamMediaProfile mediaProfile = new ImsStreamMediaProfile();
1713ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1714ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (mCallProfile == null) {
1715ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return mediaProfile;
1716ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1717ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1718ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mediaProfile.mAudioQuality = mCallProfile.mMediaProfile.mAudioQuality;
1719ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mediaProfile.mVideoQuality = mCallProfile.mMediaProfile.mVideoQuality;
1720ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mediaProfile.mAudioDirection = ImsStreamMediaProfile.DIRECTION_SEND_RECEIVE;
1721ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1722ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (mediaProfile.mVideoQuality != ImsStreamMediaProfile.VIDEO_QUALITY_NONE) {
1723ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mediaProfile.mVideoDirection = ImsStreamMediaProfile.DIRECTION_SEND_RECEIVE;
1724ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1725ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1726ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        return mediaProfile;
1727ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1728ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1729ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void enforceConversationMode() {
1730ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (mInCall) {
1731ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mHold = false;
1732ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            mUpdateRequest = UPDATE_NONE;
1733ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1734ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1735ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1736ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void mergeInternal() {
17376804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        if (CONF_DBG) {
17386804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("mergeInternal :: ");
1739ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1740ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1741ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mSession.merge();
1742ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        mUpdateRequest = UPDATE_MERGE;
1743ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1744ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1745ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void notifyConferenceSessionTerminated(ImsReasonInfo reasonInfo) {
17469bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        ImsCall.Listener listener = mListener;
1747ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        clear(reasonInfo);
1748ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1749ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        if (listener != null) {
1750ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            try {
1751ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener.onCallTerminated(this, reasonInfo);
1752ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            } catch (Throwable t) {
1753ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                loge("notifyConferenceSessionTerminated :: ", t);
1754ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1755ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1756ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1757ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1758ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    private void notifyConferenceStateUpdated(ImsConferenceState state) {
17599e3452a8efa430f9ca04379be3da6baf0bb0f51aTyler Gunn        if (state == null || state.mParticipants == null) {
17609e3452a8efa430f9ca04379be3da6baf0bb0f51aTyler Gunn            return;
17619e3452a8efa430f9ca04379be3da6baf0bb0f51aTyler Gunn        }
17629e3452a8efa430f9ca04379be3da6baf0bb0f51aTyler Gunn
17631c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn        Set<Entry<String, Bundle>> participants = state.mParticipants.entrySet();
1764ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
17651c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn        if (participants == null) {
1766ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            return;
1767ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
1768ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
17691c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn        Iterator<Entry<String, Bundle>> iterator = participants.iterator();
1770a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam        mConferenceParticipants = new ArrayList<>(participants.size());
1771ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        while (iterator.hasNext()) {
1772ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            Entry<String, Bundle> entry = iterator.next();
1773ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1774ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            String key = entry.getKey();
1775ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            Bundle confInfo = entry.getValue();
1776ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            String status = confInfo.getString(ImsConferenceState.STATUS);
1777ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            String user = confInfo.getString(ImsConferenceState.USER);
17785965614f5b813f2739722589f84cec69c572b0a2Tyler Gunn            String displayName = confInfo.getString(ImsConferenceState.DISPLAY_TEXT);
1779ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            String endpoint = confInfo.getString(ImsConferenceState.ENDPOINT);
1780ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
17816804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            if (CONF_DBG) {
1782fb688ca8113d6dae87e2d18ea29f09c630360c03Shunta Sakai                logi("notifyConferenceStateUpdated :: key=" + Rlog.pii(TAG, key) +
1783ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ", status=" + status +
1784fb688ca8113d6dae87e2d18ea29f09c630360c03Shunta Sakai                        ", user=" + Rlog.pii(TAG, user) +
1785fb688ca8113d6dae87e2d18ea29f09c630360c03Shunta Sakai                        ", displayName= " + Rlog.pii(TAG, displayName) +
1786ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                        ", endpoint=" + endpoint);
1787ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
1788ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
17899bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            Uri handle = Uri.parse(user);
1790a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam            if (endpoint == null) {
1791a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam                endpoint = "";
1792a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam            }
17939bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            Uri endpointUri = Uri.parse(endpoint);
17949bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            int connectionState = ImsConferenceState.getConnectionStateForStatus(status);
1795ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1796a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam            if (connectionState != Connection.STATE_DISCONNECTED) {
1797a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam                ConferenceParticipant conferenceParticipant = new ConferenceParticipant(handle,
1798a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam                        displayName, endpointUri, connectionState);
1799a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam                mConferenceParticipants.add(conferenceParticipant);
1800a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam            }
1801ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
18021c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn
18030f108033df343d446e42c403494cc2ab079895d5Anju Mathapati        if (mConferenceParticipants != null && mListener != null) {
18041c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn            try {
1805a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam                mListener.onConferenceParticipantsStateChanged(this, mConferenceParticipants);
18061c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn            } catch (Throwable t) {
18071c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn                loge("notifyConferenceStateUpdated :: ", t);
18081c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn            }
18091c46760f9e523312d92e027dfdb52d359d65efe1Tyler Gunn        }
1810ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
1811ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
1812b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    /**
1813b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee     * Perform all cleanup and notification around the termination of a session.
1814b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee     * Note that there are 2 distinct modes of operation.  The first is when
1815b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee     * we receive a session termination on the primary session when we are
1816b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee     * in the processing of merging.  The second is when we are not merging anything
1817b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee     * and the call is terminated.
1818b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee     *
1819b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee     * @param reasonInfo The reason for the session termination
1820b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee     */
1821b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    private void processCallTerminated(ImsReasonInfo reasonInfo) {
182295d563ed2a215d67a4f789c3ebb5a526fb95cc7fTyler Gunn        logi("processCallTerminated :: reason=" + reasonInfo + " userInitiated = " +
182395d563ed2a215d67a4f789c3ebb5a526fb95cc7fTyler Gunn                mTerminationRequestPending);
1824b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee
1825b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee        ImsCall.Listener listener = null;
1826b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee        synchronized(ImsCall.this) {
1827047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            // If we are in the midst of establishing a conference, we will bury the termination
182895d563ed2a215d67a4f789c3ebb5a526fb95cc7fTyler Gunn            // until the merge has completed.  If necessary we can surface the termination at
182995d563ed2a215d67a4f789c3ebb5a526fb95cc7fTyler Gunn            // this point.
183095d563ed2a215d67a4f789c3ebb5a526fb95cc7fTyler Gunn            // We will also NOT bury the termination if a termination was initiated locally.
183195d563ed2a215d67a4f789c3ebb5a526fb95cc7fTyler Gunn            if (isCallSessionMergePending() && !mTerminationRequestPending) {
1832b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                // Since we are in the process of a merge, this trigger means something
1833b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                // else because it is probably due to the merge happening vs. the
1834b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                // session is really terminated. Let's flag this and revisit if
1835b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                // the merge() ends up failing because we will need to take action on the
1836b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                // mSession in that case since the termination was not due to the merge
1837b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                // succeeding.
18386804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                if (CONF_DBG) {
18396804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    logi("processCallTerminated :: burying termination during ongoing merge.");
1840b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                }
1841b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                mSessionEndDuringMerge = true;
1842b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                mSessionEndDuringMergeReasonInfo = reasonInfo;
1843b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                return;
1844b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee            }
1845b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee
18469bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            // If we are terminating the conference call, notify using conference listeners.
18479bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            if (isMultiparty()) {
1848b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                notifyConferenceSessionTerminated(reasonInfo);
18499bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                return;
1850b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee            } else {
1851b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                listener = mListener;
1852b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                clear(reasonInfo);
1853b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee            }
1854b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee        }
1855b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee
1856b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee        if (listener != null) {
1857b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee            try {
1858b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                listener.onCallTerminated(ImsCall.this, reasonInfo);
1859b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee            } catch (Throwable t) {
1860c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                loge("processCallTerminated :: ", t);
1861b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee            }
1862b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee        }
1863b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    }
186471382693cbc81b1d131085f52d97879976706f55Anthony Lee
186571382693cbc81b1d131085f52d97879976706f55Anthony Lee    /**
186671382693cbc81b1d131085f52d97879976706f55Anthony Lee     * This function determines if the ImsCallSession is our actual ImsCallSession or if is
186771382693cbc81b1d131085f52d97879976706f55Anthony Lee     * the transient session used in the process of creating a conference. This function should only
186871382693cbc81b1d131085f52d97879976706f55Anthony Lee     * be called within  callbacks that are not directly related to conference merging but might
186971382693cbc81b1d131085f52d97879976706f55Anthony Lee     * potentially still be called on the transient ImsCallSession sent to us from
187071382693cbc81b1d131085f52d97879976706f55Anthony Lee     * callSessionMergeStarted() when we don't really care. In those situations, we probably don't
187171382693cbc81b1d131085f52d97879976706f55Anthony Lee     * want to take any action so we need to know that we can return early.
187271382693cbc81b1d131085f52d97879976706f55Anthony Lee     *
187371382693cbc81b1d131085f52d97879976706f55Anthony Lee     * @param session - The {@link ImsCallSession} that the function needs to analyze
187471382693cbc81b1d131085f52d97879976706f55Anthony Lee     * @return true if this is the transient {@link ImsCallSession}, false otherwise.
187571382693cbc81b1d131085f52d97879976706f55Anthony Lee     */
187671382693cbc81b1d131085f52d97879976706f55Anthony Lee    private boolean isTransientConferenceSession(ImsCallSession session) {
187771382693cbc81b1d131085f52d97879976706f55Anthony Lee        if (session != null && session != mSession && session == mTransientConferenceSession) {
187871382693cbc81b1d131085f52d97879976706f55Anthony Lee            return true;
187971382693cbc81b1d131085f52d97879976706f55Anthony Lee        }
188071382693cbc81b1d131085f52d97879976706f55Anthony Lee        return false;
188171382693cbc81b1d131085f52d97879976706f55Anthony Lee    }
188271382693cbc81b1d131085f52d97879976706f55Anthony Lee
1883c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    private void setTransientSessionAsPrimary(ImsCallSession transientSession) {
1884c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        synchronized (ImsCall.this) {
1885c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            mSession.setListener(null);
1886c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            mSession = transientSession;
1887c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            mSession.setListener(createCallSessionListener());
1888c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        }
1889c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    }
1890c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
1891818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati    private void markCallAsMerged(boolean playDisconnectTone) {
1892818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati        if (!isSessionAlive(mSession)) {
189395be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam            // If the peer is dead, let's not play a disconnect sound for it when we
189495be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam            // unbury the termination callback.
1895818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati            logi("markCallAsMerged");
1896818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati            setIsMerged(playDisconnectTone);
1897818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati            mSessionEndDuringMerge = true;
1898818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati            String reasonInfo;
189996e2d85ef5300fdac5acf89daabfa2584f969d0dJayachandran C            int reasonCode = ImsReasonInfo.CODE_UNSPECIFIED;
1900818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati            if (playDisconnectTone) {
190196e2d85ef5300fdac5acf89daabfa2584f969d0dJayachandran C                reasonCode = ImsReasonInfo.CODE_USER_TERMINATED_BY_REMOTE;
1902818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati                reasonInfo = "Call ended by network";
1903818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati            } else {
190496e2d85ef5300fdac5acf89daabfa2584f969d0dJayachandran C                reasonCode = ImsReasonInfo.CODE_LOCAL_ENDED_BY_CONFERENCE_MERGE;
1905818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati                reasonInfo = "Call ended during conference merge process.";
1906818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati            }
1907818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati            mSessionEndDuringMergeReasonInfo = new ImsReasonInfo(
190896e2d85ef5300fdac5acf89daabfa2584f969d0dJayachandran C                    reasonCode, 0, reasonInfo);
190995be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam        }
191095be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam    }
191195be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam
191271382693cbc81b1d131085f52d97879976706f55Anthony Lee    /**
191395be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam     * Checks if the merge was requested by foreground conference call
191495be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam     *
191595be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam     * @return true if the merge was requested by foreground conference call
1916047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     */
191795be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam    public boolean isMergeRequestedByConf() {
191895be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam        synchronized(mLockObj) {
191995be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam            return mMergeRequestedByConference;
192095be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam        }
192195be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam    }
192295be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam
192395be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam    /**
192495be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam     * Resets the flag which indicates merge request was sent by
192595be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam     * foreground conference call
192695be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam     */
192795be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam    public void resetIsMergeRequestedByConf(boolean value) {
192895be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam        synchronized(mLockObj) {
192995be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam            mMergeRequestedByConference = value;
193095be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam        }
193195be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam    }
193295be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam
193395be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam    /**
193495be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam     * Returns current ImsCallSession
193595be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam     *
193695be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam     * @return current session
193795be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam     */
193895be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam    public ImsCallSession getSession() {
193995be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam        synchronized(mLockObj) {
194095be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam            return mSession;
1941c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        }
1942047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    }
1943047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
1944047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    /**
1945c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * We have detected that a initial conference call has been fully configured. The internal
1946c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * state of both {@code ImsCall} objects need to be cleaned up to reflect the new state.
1947c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * This function should only be called in the context of the merge host to simplify logic
194871382693cbc81b1d131085f52d97879976706f55Anthony Lee     *
194971382693cbc81b1d131085f52d97879976706f55Anthony Lee     */
1950b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    private void processMergeComplete() {
19516804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        logi("processMergeComplete :: ");
1952c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
1953c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        // The logic simplifies if we can assume that this function is only called on
1954c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        // the merge host.
1955c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        if (!isMergeHost()) {
1956c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            loge("processMergeComplete :: We are not the merge host!");
1957c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            return;
1958b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee        }
1959b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee
196071382693cbc81b1d131085f52d97879976706f55Anthony Lee        ImsCall.Listener listener;
1961047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        boolean swapRequired = false;
19629bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
196395be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam        ImsCall finalHostCall;
196495be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam        ImsCall finalPeerCall;
196595be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam
196695be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam        synchronized(ImsCall.this) {
1967c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            if (isMultiparty()) {
1968c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                setIsMerged(false);
196995be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                // if case handles Case 4 explained in callSessionMergeComplete
197095be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                // otherwise it is case 5
197195be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                if (!mMergeRequestedByConference) {
197295be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                    // single call in fg, conference call in bg.
197395be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                    // Finally conf call becomes active after conference
197495be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                    this.mHold = false;
197595be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                    swapRequired = true;
1976047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                }
1977818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati                mMergePeer.markCallAsMerged(false);
197895be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                finalHostCall = this;
197995be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                finalPeerCall = mMergePeer;
1980047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            } else {
1981c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // If we are here, we are not trying to merge a new call into an existing
1982c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // conference.  That means that there is a transient session on the merge
1983c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // host that represents the future conference once all the parties
1984c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // have been added to it.  So make sure that it exists or else something
1985c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // very wrong is going on.
1986c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                if (mTransientConferenceSession == null) {
1987c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    loge("processMergeComplete :: No transient session!");
1988c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    return;
1989047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                }
1990c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                if (mMergePeer == null) {
1991c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    loge("processMergeComplete :: No merge peer!");
1992c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    return;
1993047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                }
1994047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
1995c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // Since we are the host, we have the transient session attached to us. Let's detach
1996c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // it and figure out where we need to set it for the final conference configuration.
1997c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                ImsCallSession transientConferenceSession = mTransientConferenceSession;
1998c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                mTransientConferenceSession = null;
1999c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
2000c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // Clear the listener for this transient session, we'll create a new listener
2001c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // when it is attached to the final ImsCall that it should live on.
2002c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                transientConferenceSession.setListener(null);
2003c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
2004c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // Determine which call the transient session should be moved to.  If the current
2005c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // call session is still alive and the merge peer's session is not, we have a
2006c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // situation where the current call failed to merge into the conference but the
2007c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // merge peer did merge in to the conference.  In this type of scenario the current
2008c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // call will continue as a single party call, yet the background call will become
2009c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // the conference.
2010c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
201195be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                // handles Case 3 explained in callSessionMergeComplete
2012c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                if (isSessionAlive(mSession) && !isSessionAlive(mMergePeer.getCallSession())) {
2013c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // I'm the host but we are moving the transient session to the peer since its
2014c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // session was disconnected and my session is still alive.  This signifies that
2015c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // their session was properly added to the conference but mine was not because
2016c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // it is probably in the held state as opposed to part of the final conference.
2017c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // In this case, we need to set isMerged to false on both calls so the
2018c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // disconnect sound is called when either call disconnects.
2019c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // Note that this case is only valid if this is an initial conference being
2020c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // brought up.
202195be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                    mMergePeer.mHold = false;
202295be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                    this.mHold = true;
2023d0fb66402074528deccd6a85f3d1eca8d2d0714fAnju Mathapati                    if (mConferenceParticipants != null && !mConferenceParticipants.isEmpty()) {
2024d0fb66402074528deccd6a85f3d1eca8d2d0714fAnju Mathapati                        mMergePeer.mConferenceParticipants = mConferenceParticipants;
2025d0fb66402074528deccd6a85f3d1eca8d2d0714fAnju Mathapati                    }
2026d0fb66402074528deccd6a85f3d1eca8d2d0714fAnju Mathapati                    // At this point both host & peer will have participant information.
2027d0fb66402074528deccd6a85f3d1eca8d2d0714fAnju Mathapati                    // Peer will transition to host & the participant information
2028d0fb66402074528deccd6a85f3d1eca8d2d0714fAnju Mathapati                    // from that will be used
2029d0fb66402074528deccd6a85f3d1eca8d2d0714fAnju Mathapati                    // HostCall that failed to merge will remain as a single call with
2030d0fb66402074528deccd6a85f3d1eca8d2d0714fAnju Mathapati                    // mConferenceParticipants, which should not be used.
2031d0fb66402074528deccd6a85f3d1eca8d2d0714fAnju Mathapati                    // Expectation is that if this call becomes part of a conference call in future,
2032d0fb66402074528deccd6a85f3d1eca8d2d0714fAnju Mathapati                    // mConferenceParticipants will be overriten with new CEP that is received.
2033c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    finalHostCall = mMergePeer;
2034c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    finalPeerCall = this;
2035c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    swapRequired = true;
2036c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    setIsMerged(false);
2037c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    mMergePeer.setIsMerged(false);
20386804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    if (CONF_DBG) {
20396804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                        logi("processMergeComplete :: transient will transfer to merge peer");
2040047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                    }
20416804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                } else if (!isSessionAlive(mSession) &&
20426804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                                isSessionAlive(mMergePeer.getCallSession())) {
204395be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                    // Handles case 2 explained in callSessionMergeComplete
2044c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // The transient session stays with us and the disconnect sound should be played
2045c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // when the merge peer eventually disconnects since it was not actually added to
2046c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // the conference and is probably sitting in the held state.
2047c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    finalHostCall = this;
2048c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    finalPeerCall = mMergePeer;
2049c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    swapRequired = false;
2050c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    setIsMerged(false);
2051c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    mMergePeer.setIsMerged(false); // Play the disconnect sound
20526804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    if (CONF_DBG) {
20536804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                        logi("processMergeComplete :: transient will stay with the merge host");
2054c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    }
2055c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                } else {
205695be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                    // Handles case 1 explained in callSessionMergeComplete
2057c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // The transient session stays with us and the disconnect sound should not be
2058c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // played when we ripple up the disconnect for the merge peer because it was
2059c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // only disconnected to be added to the conference.
2060c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    finalHostCall = this;
2061c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    finalPeerCall = mMergePeer;
2062818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati                    mMergePeer.markCallAsMerged(false);
2063c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    swapRequired = false;
2064c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    setIsMerged(false);
2065c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    mMergePeer.setIsMerged(true);
20666804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    if (CONF_DBG) {
20676804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                        logi("processMergeComplete :: transient will stay with us (I'm the host).");
2068047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                    }
2069047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                }
2070047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
20716804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                if (CONF_DBG) {
20726804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    logi("processMergeComplete :: call=" + finalHostCall + " is the final host");
2073c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                }
2074c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
2075c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // Add the transient session to the ImsCall that ended up being the host for the
2076c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // conference.
2077c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                finalHostCall.setTransientSessionAsPrimary(transientConferenceSession);
2078047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            }
2079047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
2080c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            listener = finalHostCall.mListener;
2081c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
20821c1088887347d682b7b186027d98ad3617dcfb68Anju Mathapati            updateCallProfile(finalPeerCall);
20831c1088887347d682b7b186027d98ad3617dcfb68Anju Mathapati            updateCallProfile(finalHostCall);
20841c1088887347d682b7b186027d98ad3617dcfb68Anju Mathapati
2085c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // Clear all the merge related flags.
2086c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            clearMergeInfo();
2087c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
2088c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // For the final peer...let's bubble up any possible disconnects that we had
2089c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // during the merge process
2090c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            finalPeerCall.notifySessionTerminatedDuringMerge();
2091c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // For the final host, let's just bury the disconnects that we my have received
2092c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // during the merge process since we are now the host of the conference call.
2093c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            finalHostCall.clearSessionTerminationFlags();
209425394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn
209525394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn            // Keep track of the fact that merge host is the origin of a conference call in
209625394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn            // progress.  This is important so that we can later determine if a multiparty ImsCall
209725394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn            // is multiparty because it was the origin of a conference call, or because it is a
209825394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn            // member of a conference on another device.
209925394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn            finalHostCall.mIsConferenceHost = true;
210071382693cbc81b1d131085f52d97879976706f55Anthony Lee        }
210171382693cbc81b1d131085f52d97879976706f55Anthony Lee        if (listener != null) {
210271382693cbc81b1d131085f52d97879976706f55Anthony Lee            try {
210395be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                // finalPeerCall will have the participant that was not merged and
210495be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                // it will be held state
210595be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                // if peer was merged successfully, finalPeerCall will be null
210695be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                listener.onCallMerged(finalHostCall, finalPeerCall, swapRequired);
210771382693cbc81b1d131085f52d97879976706f55Anthony Lee            } catch (Throwable t) {
2108b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                loge("processMergeComplete :: ", t);
210971382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
21106c0b0d0e83b8d06f40ec814573adc69f362704a9Tyler Gunn            if (mConferenceParticipants != null && !mConferenceParticipants.isEmpty()) {
2111a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam                try {
2112d0fb66402074528deccd6a85f3d1eca8d2d0714fAnju Mathapati                    listener.onConferenceParticipantsStateChanged(finalHostCall,
2113d0fb66402074528deccd6a85f3d1eca8d2d0714fAnju Mathapati                            mConferenceParticipants);
2114a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam                } catch (Throwable t) {
2115a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam                    loge("processMergeComplete :: ", t);
2116a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam                }
2117a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam            }
211871382693cbc81b1d131085f52d97879976706f55Anthony Lee        }
211971382693cbc81b1d131085f52d97879976706f55Anthony Lee        return;
212071382693cbc81b1d131085f52d97879976706f55Anthony Lee    }
212171382693cbc81b1d131085f52d97879976706f55Anthony Lee
21221c1088887347d682b7b186027d98ad3617dcfb68Anju Mathapati    private static void updateCallProfile(ImsCall call) {
21231c1088887347d682b7b186027d98ad3617dcfb68Anju Mathapati        if (call != null) {
21241c1088887347d682b7b186027d98ad3617dcfb68Anju Mathapati            call.updateCallProfile();
21251c1088887347d682b7b186027d98ad3617dcfb68Anju Mathapati        }
21261c1088887347d682b7b186027d98ad3617dcfb68Anju Mathapati    }
21271c1088887347d682b7b186027d98ad3617dcfb68Anju Mathapati
21281c1088887347d682b7b186027d98ad3617dcfb68Anju Mathapati    private void updateCallProfile() {
21291c1088887347d682b7b186027d98ad3617dcfb68Anju Mathapati        synchronized (mLockObj) {
21301c1088887347d682b7b186027d98ad3617dcfb68Anju Mathapati            if (mSession != null) {
21311ac24854dba02556692dbbd779434e5596f6daedTyler Gunn                setCallProfile(mSession.getCallProfile());
21321c1088887347d682b7b186027d98ad3617dcfb68Anju Mathapati            }
21331c1088887347d682b7b186027d98ad3617dcfb68Anju Mathapati        }
21341c1088887347d682b7b186027d98ad3617dcfb68Anju Mathapati    }
21351c1088887347d682b7b186027d98ad3617dcfb68Anju Mathapati
213671382693cbc81b1d131085f52d97879976706f55Anthony Lee    /**
2137047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * Handles the case where the session has ended during a merge by reporting the termination
2138047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * reason to listeners.
2139047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     */
2140047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    private void notifySessionTerminatedDuringMerge() {
2141047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        ImsCall.Listener listener;
2142047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        boolean notifyFailure = false;
2143047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        ImsReasonInfo notifyFailureReasonInfo = null;
2144047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
2145047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        synchronized(ImsCall.this) {
2146047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            listener = mListener;
2147047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            if (mSessionEndDuringMerge) {
2148047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                // Set some local variables that will send out a notification about a
2149047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                // previously buried termination callback for our primary session now that
2150047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                // we know that this is not due to the conference call merging successfully.
21516804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                if (CONF_DBG) {
21526804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    logi("notifySessionTerminatedDuringMerge ::reporting terminate during merge");
2153047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                }
2154047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                notifyFailure = true;
2155047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                notifyFailureReasonInfo = mSessionEndDuringMergeReasonInfo;
2156047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            }
2157c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            clearSessionTerminationFlags();
2158047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        }
2159047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
2160047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        if (listener != null && notifyFailure) {
2161047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            try {
2162047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                processCallTerminated(notifyFailureReasonInfo);
2163047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            } catch (Throwable t) {
2164047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                loge("notifySessionTerminatedDuringMerge :: ", t);
2165047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            }
2166047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        }
2167047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    }
2168047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
2169c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    private void clearSessionTerminationFlags() {
2170c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        mSessionEndDuringMerge = false;
2171c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        mSessionEndDuringMergeReasonInfo = null;
2172c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    }
2173c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
2174a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam   /**
217571382693cbc81b1d131085f52d97879976706f55Anthony Lee     * We received a callback from ImsCallSession that a merge failed. Clean up all
2176c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * internal state to represent this state change.  The calling function is a callback
2177c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * and should have been called on the session that was in the foreground
2178c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * when merge() was originally called.  It is assumed that this function will be called
2179c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * on the merge host.
218071382693cbc81b1d131085f52d97879976706f55Anthony Lee     *
218171382693cbc81b1d131085f52d97879976706f55Anthony Lee     * @param reasonInfo The {@link ImsReasonInfo} why the merge failed.
218271382693cbc81b1d131085f52d97879976706f55Anthony Lee     */
2183b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee    private void processMergeFailed(ImsReasonInfo reasonInfo) {
21846804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        logi("processMergeFailed :: reason=" + reasonInfo);
2185047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
2186047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        ImsCall.Listener listener;
218771382693cbc81b1d131085f52d97879976706f55Anthony Lee        synchronized(ImsCall.this) {
2188c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // The logic simplifies if we can assume that this function is only called on
2189c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // the merge host.
2190c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            if (!isMergeHost()) {
2191c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                loge("processMergeFailed :: We are not the merge host!");
2192c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                return;
2193c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            }
2194c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
219561d41c1f9ba249bd0df575cc1b551a9e70f54645Anthony Lee            // Try to clean up the transient session if it exists.
219661d41c1f9ba249bd0df575cc1b551a9e70f54645Anthony Lee            if (mTransientConferenceSession != null) {
219771382693cbc81b1d131085f52d97879976706f55Anthony Lee                mTransientConferenceSession.setListener(null);
219871382693cbc81b1d131085f52d97879976706f55Anthony Lee                mTransientConferenceSession = null;
2199b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee            }
2200047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
2201c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            listener = mListener;
2202c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
220361d41c1f9ba249bd0df575cc1b551a9e70f54645Anthony Lee            // Ensure the calls being conferenced into the conference has isMerged = false.
2204c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // Ensure any terminations are surfaced from this session.
2205818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati            markCallAsMerged(true);
2206818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati            setCallSessionMergePending(false);
2207c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            notifySessionTerminatedDuringMerge();
220861d41c1f9ba249bd0df575cc1b551a9e70f54645Anthony Lee
2209818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati            // Perform the same cleanup on the merge peer if it exists.
221061d41c1f9ba249bd0df575cc1b551a9e70f54645Anthony Lee            if (mMergePeer != null) {
2211818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati                mMergePeer.markCallAsMerged(true);
2212818c09d7b55d3257e91e528749587349f7197e3fAnju Mathapati                mMergePeer.setCallSessionMergePending(false);
221361d41c1f9ba249bd0df575cc1b551a9e70f54645Anthony Lee                mMergePeer.notifySessionTerminatedDuringMerge();
221461d41c1f9ba249bd0df575cc1b551a9e70f54645Anthony Lee            } else {
221561d41c1f9ba249bd0df575cc1b551a9e70f54645Anthony Lee                loge("processMergeFailed :: No merge peer!");
221661d41c1f9ba249bd0df575cc1b551a9e70f54645Anthony Lee            }
2217c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
2218c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // Clear all the various flags around coordinating this merge.
2219c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            clearMergeInfo();
222071382693cbc81b1d131085f52d97879976706f55Anthony Lee        }
222171382693cbc81b1d131085f52d97879976706f55Anthony Lee        if (listener != null) {
222271382693cbc81b1d131085f52d97879976706f55Anthony Lee            try {
222371382693cbc81b1d131085f52d97879976706f55Anthony Lee                listener.onCallMergeFailed(ImsCall.this, reasonInfo);
222471382693cbc81b1d131085f52d97879976706f55Anthony Lee            } catch (Throwable t) {
2225b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                loge("processMergeFailed :: ", t);
222671382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
222771382693cbc81b1d131085f52d97879976706f55Anthony Lee        }
2228c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
222971382693cbc81b1d131085f52d97879976706f55Anthony Lee        return;
223071382693cbc81b1d131085f52d97879976706f55Anthony Lee    }
223171382693cbc81b1d131085f52d97879976706f55Anthony Lee
2232afb53c826d0f4614311a93d24a9bf8fe2b0a51a5Tyler Gunn    @VisibleForTesting
2233afb53c826d0f4614311a93d24a9bf8fe2b0a51a5Tyler Gunn    public class ImsCallSessionListenerProxy extends ImsCallSession.Listener {
2234ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
223571382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionProgressing(ImsCallSession session, ImsStreamMediaProfile profile) {
22366804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionProgressing :: session=" + session + " profile=" + profile);
22376804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
223871382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2239c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // If it is a transient (conference) session, there is no action for this signal.
22406804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionProgressing :: not supported for transient conference session=" +
2241b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
224271382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
224371382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
224471382693cbc81b1d131085f52d97879976706f55Anthony Lee
2245ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2246ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2247ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2248ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2249ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mCallProfile.mMediaProfile.copyFrom(profile);
2250ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2251ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2252ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2253ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2254ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallProgressing(ImsCall.this);
2255ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2256ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionProgressing :: ", t);
2257ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2258ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2259ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2260ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2261ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
226271382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionStarted(ImsCallSession session, ImsCallProfile profile) {
22636804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionStarted :: session=" + session + " profile=" + profile);
2264c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
2265c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            if (!isTransientConferenceSession(session)) {
2266c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // In the case that we are in the middle of a merge (either host or peer), we have
2267c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // closure as far as this call's primary session is concerned.  If we are not
2268c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // merging...its a NOOP.
2269c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                setCallSessionMergePending(false);
2270c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            } else {
22716804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionStarted :: on transient session=" + session);
2272c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                return;
2273ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2274ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2275c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            if (isTransientConferenceSession(session)) {
2276c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // No further processing is needed if this is the transient session.
2277b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                return;
2278b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee            }
2279b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee
2280ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2281ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2282ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2283ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
22841ac24854dba02556692dbbd779434e5596f6daedTyler Gunn                setCallProfile(profile);
2285ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2286ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2287ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2288ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2289ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallStarted(ImsCall.this);
2290ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2291ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionStarted :: ", t);
2292ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2293ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2294ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2295ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2296ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
229771382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionStartFailed(ImsCallSession session, ImsReasonInfo reasonInfo) {
22986804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            loge("callSessionStartFailed :: session=" + session + " reasonInfo=" + reasonInfo);
22996804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
230071382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2301c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // We should not get this callback for a transient session.
23026804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionStartFailed :: not supported for transient conference session=" +
2303b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
230471382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
230571382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
230671382693cbc81b1d131085f52d97879976706f55Anthony Lee
2307ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2308ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2309ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2310ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2311ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mLastReasonInfo = reasonInfo;
2312ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2313ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2314ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2315ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2316ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallStartFailed(ImsCall.this, reasonInfo);
2317ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2318ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionStarted :: ", t);
2319ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2320ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2321ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2322ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2323ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
232471382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionTerminated(ImsCallSession session, ImsReasonInfo reasonInfo) {
23256804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionTerminated :: session=" + session + " reasonInfo=" + reasonInfo);
23266804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
2327c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            if (isTransientConferenceSession(session)) {
23286804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionTerminated :: on transient session=" + session);
2329c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // This is bad, it should be treated much a callSessionMergeFailed since the
2330c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // transient session only exists when in the process of a merge and the
2331c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // termination of this session is effectively the end of the merge.
2332c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                processMergeFailed(reasonInfo);
233371382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
233471382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
233571382693cbc81b1d131085f52d97879976706f55Anthony Lee
233625a72fccf3313ab46a1dd03096f8944a96499406Tyler Gunn            if (mOverrideReason != ImsReasonInfo.CODE_UNSPECIFIED) {
233725a72fccf3313ab46a1dd03096f8944a96499406Tyler Gunn                logi("callSessionTerminated :: overrideReasonInfo=" + mOverrideReason);
233825a72fccf3313ab46a1dd03096f8944a96499406Tyler Gunn                reasonInfo = new ImsReasonInfo(mOverrideReason, reasonInfo.getExtraCode(),
233925a72fccf3313ab46a1dd03096f8944a96499406Tyler Gunn                        reasonInfo.getExtraMessage());
234025a72fccf3313ab46a1dd03096f8944a96499406Tyler Gunn            }
234125a72fccf3313ab46a1dd03096f8944a96499406Tyler Gunn
2342c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // Process the termination first.  If we are in the midst of establishing a conference
2343c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // call, we may bury this callback until we are done.  If there so no conference
2344c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // call, the code after this function will be a NOOP.
2345c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            processCallTerminated(reasonInfo);
2346c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
2347047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            // If session has terminated, it is no longer pending merge.
2348047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn            setCallSessionMergePending(false);
2349047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
2350ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2351ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2352ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
235371382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionHeld(ImsCallSession session, ImsCallProfile profile) {
23546804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionHeld :: session=" + session + "profile=" + profile);
2355ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2356ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2357ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2358047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                // If the session was held, it is no longer pending a merge -- this means it could
2359047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                // not be merged into the conference and was held instead.
2360047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn                setCallSessionMergePending(false);
2361047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
23621ac24854dba02556692dbbd779434e5596f6daedTyler Gunn                setCallProfile(profile);
2363ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2364ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (mUpdateRequest == UPDATE_HOLD_MERGE) {
2365c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // This hold request was made to set the stage for a merge.
2366ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    mergeInternal();
2367ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    return;
2368ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2369ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2370ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2371ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2372ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2373ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2374ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2375ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2376ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallHeld(ImsCall.this);
2377ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2378ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionHeld :: ", t);
2379ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2380ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2381ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2382ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2383ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
238471382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionHoldFailed(ImsCallSession session, ImsReasonInfo reasonInfo) {
23856804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            loge("callSessionHoldFailed :: session" + session + "reasonInfo=" + reasonInfo);
23866804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
238771382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2388c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // We should not get this callback for a transient session.
23896804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionHoldFailed :: not supported for transient conference session=" +
2390b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
239171382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
239271382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
239371382693cbc81b1d131085f52d97879976706f55Anthony Lee
2394d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh            logi("callSessionHoldFailed :: session=" + session +
2395d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh                    ", reasonInfo=" + reasonInfo);
2396d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh
2397d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh            synchronized (mLockObj) {
2398a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam                mHold = false;
2399a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam            }
2400a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam
2401ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            boolean isHoldForMerge = false;
2402ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2403ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2404ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2405ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                if (mUpdateRequest == UPDATE_HOLD_MERGE) {
2406ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    isHoldForMerge = true;
2407ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2408ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2409ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2410ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2411ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2412ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2413ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2414ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2415ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallHoldFailed(ImsCall.this, reasonInfo);
2416ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2417ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionHoldFailed :: ", t);
2418ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2419ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2420ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2421ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2422ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
242371382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionHoldReceived(ImsCallSession session, ImsCallProfile profile) {
24246804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionHoldReceived :: session=" + session + "profile=" + profile);
24256804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
242671382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
2427c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // We should not get this callback for a transient session.
24286804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionHoldReceived :: not supported for transient conference session=" +
2429b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
243071382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
243171382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
243271382693cbc81b1d131085f52d97879976706f55Anthony Lee
2433ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2434ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2435ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2436ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
24371ac24854dba02556692dbbd779434e5596f6daedTyler Gunn                setCallProfile(profile);
2438ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2439ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2440ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2441ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2442ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallHoldReceived(ImsCall.this);
2443ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2444ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionHoldReceived :: ", t);
2445ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2446ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2447ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2448ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2449ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
245071382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionResumed(ImsCallSession session, ImsCallProfile profile) {
24516804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionResumed :: session=" + session + "profile=" + profile);
24526804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
245371382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
24546804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionResumed :: not supported for transient conference session=" +
2455b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
245671382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
245771382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
245871382693cbc81b1d131085f52d97879976706f55Anthony Lee
2459c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // If this call was pending a merge, it is not anymore. This is the case when we
2460c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // are merging in a new call into an existing conference.
2461c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            setCallSessionMergePending(false);
2462c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
2463c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // TOOD: When we are merging a new call into an existing conference we are waiting
2464c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // for 2 triggers to let us know that the conference has been established, the first
2465c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // is a termination for the new calls (since it is added to the conference) the second
2466c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // would be a resume on the existing conference.  If the resume comes first, then
2467c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // we will make the onCallResumed() callback and its unclear how this will behave if
2468c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // the termination has not come yet.
2469ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2470c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            ImsCall.Listener listener;
2471ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2472ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
24731ac24854dba02556692dbbd779434e5596f6daedTyler Gunn                setCallProfile(profile);
2474ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2475095839a66699a128c76cd5002459fcba7c3a9a0dUma Maheswari Ramalingam                mHold = false;
2476ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2477ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2478ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2479ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2480ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallResumed(ImsCall.this);
2481ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2482ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionResumed :: ", t);
2483ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2484ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2485ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2486ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2487ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
248871382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionResumeFailed(ImsCallSession session, ImsReasonInfo reasonInfo) {
24896804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            loge("callSessionResumeFailed :: session=" + session + "reasonInfo=" + reasonInfo);
24906804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
249171382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
24926804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionResumeFailed :: not supported for transient conference session=" +
2493b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
249471382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
249571382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
249671382693cbc81b1d131085f52d97879976706f55Anthony Lee
2497a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam            synchronized(mLockObj) {
2498a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam                mHold = true;
2499a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam            }
2500a1ed7b0957567367d0e782ee6ce1db265d028eceUma Maheswari Ramalingam
2501ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2502ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2503ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2504ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2505ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2506ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2507ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2508ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2509ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2510ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallResumeFailed(ImsCall.this, reasonInfo);
2511ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2512ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionResumeFailed :: ", t);
2513ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2514ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2515ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2516ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2517ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
251871382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionResumeReceived(ImsCallSession session, ImsCallProfile profile) {
25196804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionResumeReceived :: session=" + session + "profile=" + profile);
25206804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
252171382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
25226804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionResumeReceived :: not supported for transient conference session=" +
2523b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
252471382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
252571382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
252671382693cbc81b1d131085f52d97879976706f55Anthony Lee
2527ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2528ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2529ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2530ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
25311ac24854dba02556692dbbd779434e5596f6daedTyler Gunn                setCallProfile(profile);
2532ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2533ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2534ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2535ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2536ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallResumeReceived(ImsCall.this);
2537ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2538ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionResumeReceived :: ", t);
2539ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2540ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2541ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2542ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2543ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
25443f2b0aaa277545886571cbf90fc90fd5d304e714Tyler Gunn        public void callSessionMergeStarted(ImsCallSession session,
2545ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsCallSession newSession, ImsCallProfile profile) {
25466804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionMergeStarted :: session=" + session + " newSession=" + newSession +
25476804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    ", profile=" + profile);
2548ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
254971382693cbc81b1d131085f52d97879976706f55Anthony Lee            return;
2550ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2551ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
255295be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam        /*
255395be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam         * This method check if session exists as a session on the current
255495be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam         * ImsCall or its counterpart if it is in the process of a conference
255595be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam         */
255695be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam        private boolean doesCallSessionExistsInMerge(ImsCallSession cs) {
255795be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam            String callId = cs.getCallId();
255895be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam            return ((isMergeHost() && Objects.equals(mMergePeer.mSession.getCallId(), callId)) ||
255995be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                    (isMergePeer() && Objects.equals(mMergeHost.mSession.getCallId(), callId)) ||
256095be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                    Objects.equals(mSession.getCallId(), callId));
256195be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam        }
256295be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam
256395be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam        /**
256495be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam         * We received a callback from ImsCallSession that merge completed.
2565d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati         * @param newSession - this session can have 2 values based on the below scenarios
256695be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam         *
256795be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam	 * Conference Scenarios :
256895be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam         * Case 1 - 3 way success case
256995be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam         * Case 2 - 3 way success case but held call fails to merge
257095be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam         * Case 3 - 3 way success case but active call fails to merge
257195be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam         * case 4 - 4 way success case, where merge is initiated on the foreground single-party
257295be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam         *          call and the conference (mergeHost) is the background call.
257395be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam         * case 5 - 4 way success case, where merge is initiated on the foreground conference
257495be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam         *          call (mergeHost) and the single party call is in the background.
257595be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam         *
257695be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam         * Conference Result:
2577d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati         * session : new session after conference
2578d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati         * newSession = new session for case 1, 2, 3.
2579d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati         *              Should be considered as mTransientConferencession
2580d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati         * newSession = Active conference session for case 5 will be null
2581d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati         *              mergehost was foreground call
2582d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati         *              mTransientConferencession will be null
2583d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati         * newSession = Active conference session for case 4 will be null
2584d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati         *              mergeHost was background call
2585d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati         *              mTransientConferencession will be null
258695be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam         */
2587ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2588d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati        public void callSessionMergeComplete(ImsCallSession newSession) {
2589d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati            logi("callSessionMergeComplete :: newSession =" + newSession);
259095be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam            if (!isMergeHost()) {
259195be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                // Handles case 4
259295be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                mMergeHost.processMergeComplete();
259395be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam            } else {
2594d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati                // Handles case 1, 2, 3
2595d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati                if (newSession != null) {
2596d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati                    mTransientConferenceSession = doesCallSessionExistsInMerge(newSession) ?
2597d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati                            null: newSession;
2598d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati                }
2599d9ed874439293ed6c34ce27a3689711c986f977bAnju Mathapati                // Handles case 5
260095be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam                processMergeComplete();
260195be7c68495a3a22c45b8d7867bf5c0246513adbUma Maheswari Ramalingam            }
26023f2b0aaa277545886571cbf90fc90fd5d304e714Tyler Gunn        }
26033f2b0aaa277545886571cbf90fc90fd5d304e714Tyler Gunn
26043f2b0aaa277545886571cbf90fc90fd5d304e714Tyler Gunn        @Override
260571382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionMergeFailed(ImsCallSession session, ImsReasonInfo reasonInfo) {
26066804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            loge("callSessionMergeFailed :: session=" + session + "reasonInfo=" + reasonInfo);
2607c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
2608c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // Its possible that there could be threading issues with the other thread handling
2609c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // the other call. This could affect our state.
2610c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            synchronized (ImsCall.this) {
2611c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // Let's tell our parent ImsCall that the merge has failed and we need to clean
2612c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // up any temporary, transient state.  Note this only gets called for an initial
2613c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // conference.  If a merge into an existing conference fails, the two sessions will
2614c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // just go back to their original state (ACTIVE or HELD).
2615c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                if (isMergeHost()) {
2616c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    processMergeFailed(reasonInfo);
2617c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                } else if (mMergeHost != null) {
2618c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    mMergeHost.processMergeFailed(reasonInfo);
2619c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                } else {
2620c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    loge("callSessionMergeFailed :: No merge host for this conference!");
2621c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                }
2622ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2623ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2624ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2625ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
262671382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionUpdated(ImsCallSession session, ImsCallProfile profile) {
26276804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionUpdated :: session=" + session + " profile=" + profile);
26286804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
262971382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
26306804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionUpdated :: not supported for transient conference session=" +
2631b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
263271382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
263371382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
263471382693cbc81b1d131085f52d97879976706f55Anthony Lee
2635ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2636ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2637ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2638ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
26391ac24854dba02556692dbbd779434e5596f6daedTyler Gunn                setCallProfile(profile);
2640ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2641ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2642ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2643ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2644ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallUpdated(ImsCall.this);
2645ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2646ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionUpdated :: ", t);
2647ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2648ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2649ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2650ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2651ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
265271382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionUpdateFailed(ImsCallSession session, ImsReasonInfo reasonInfo) {
26536804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            loge("callSessionUpdateFailed :: session=" + session + " reasonInfo=" + reasonInfo);
26546804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
265571382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
26566804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionUpdateFailed :: not supported for transient conference session=" +
2657b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        session);
265871382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
265971382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
266071382693cbc81b1d131085f52d97879976706f55Anthony Lee
2661ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2662ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2663ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2664ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2665ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2666ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2667ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2668ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2669ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2670ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallUpdateFailed(ImsCall.this, reasonInfo);
2671ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2672ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionUpdateFailed :: ", t);
2673ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2674ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2675ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2676ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2677ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
267871382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionUpdateReceived(ImsCallSession session, ImsCallProfile profile) {
26796804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionUpdateReceived :: session=" + session + " profile=" + profile);
26806804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
268171382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
26826804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionUpdateReceived :: not supported for transient conference " +
2683b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        "session=" + session);
268471382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
268571382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
268671382693cbc81b1d131085f52d97879976706f55Anthony Lee
2687ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2688ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2689ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2690ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2691ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mProposedCallProfile = profile;
2692ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_UNSPECIFIED;
2693ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2694ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2695ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2696ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2697ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallUpdateReceived(ImsCall.this);
2698ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2699ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionUpdateReceived :: ", t);
2700ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2701ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2702ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2703ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2704ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
270571382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionConferenceExtended(ImsCallSession session, ImsCallSession newSession,
270671382693cbc81b1d131085f52d97879976706f55Anthony Lee                ImsCallProfile profile) {
27076804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionConferenceExtended :: session=" + session  + " newSession=" +
27086804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    newSession + ", profile=" + profile);
27096804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
271071382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
27116804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionConferenceExtended :: not supported for transient conference " +
2712b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        "session=" + session);
271371382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
271471382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
271571382693cbc81b1d131085f52d97879976706f55Anthony Lee
2716ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall newCall = createNewCall(newSession, profile);
2717ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2718ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (newCall == null) {
2719ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                callSessionConferenceExtendFailed(session, new ImsReasonInfo());
2720ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return;
2721ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2722ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2723ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2724ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2725ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2726ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2727ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2728ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2729ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2730ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2731ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2732ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallConferenceExtended(ImsCall.this, newCall);
2733ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2734ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionConferenceExtended :: ", t);
2735ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2736ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2737ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2738ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2739ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2740ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionConferenceExtendFailed(ImsCallSession session,
2741ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsReasonInfo reasonInfo) {
27426804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            loge("callSessionConferenceExtendFailed :: reasonInfo=" + reasonInfo);
27436804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
274471382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
27456804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionConferenceExtendFailed :: not supported for transient " +
2746b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        "conference session=" + session);
274771382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
274871382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
274971382693cbc81b1d131085f52d97879976706f55Anthony Lee
2750ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2751ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2752ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2753ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2754ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                mUpdateRequest = UPDATE_NONE;
2755ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2756ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2757ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2758ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2759ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallConferenceExtendFailed(ImsCall.this, reasonInfo);
2760ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2761ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionConferenceExtendFailed :: ", t);
2762ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2763ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2764ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2765ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2766ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2767ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionConferenceExtendReceived(ImsCallSession session,
2768ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsCallSession newSession, ImsCallProfile profile) {
27696804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionConferenceExtendReceived :: newSession=" + newSession +
27706804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    ", profile=" + profile);
27716804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
277271382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
27736804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionConferenceExtendReceived :: not supported for transient " +
27749bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                        "conference session" + session);
277571382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
277671382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
277771382693cbc81b1d131085f52d97879976706f55Anthony Lee
2778ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall newCall = createNewCall(newSession, profile);
2779ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2780ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (newCall == null) {
2781ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                // Should all the calls be terminated...???
2782ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                return;
2783ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2784ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2785ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2786ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2787ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2788ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2789ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2790ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2791ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2792ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2793ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallConferenceExtendReceived(ImsCall.this, newCall);
2794ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2795ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionConferenceExtendReceived :: ", t);
2796ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2797ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2798ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2799ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2800ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2801ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionInviteParticipantsRequestDelivered(ImsCallSession session) {
28026804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionInviteParticipantsRequestDelivered ::");
28036804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
280471382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
28056804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionInviteParticipantsRequestDelivered :: not supported for " +
280671382693cbc81b1d131085f52d97879976706f55Anthony Lee                        "conference session=" + session);
280771382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
280871382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
280971382693cbc81b1d131085f52d97879976706f55Anthony Lee
2810ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2811ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2812ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2813ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2814ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2815ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2816ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2817ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2818ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallInviteParticipantsRequestDelivered(ImsCall.this);
2819ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2820ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionInviteParticipantsRequestDelivered :: ", t);
2821ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2822ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2823ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2824ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2825ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2826ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionInviteParticipantsRequestFailed(ImsCallSession session,
2827ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsReasonInfo reasonInfo) {
28286804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            loge("callSessionInviteParticipantsRequestFailed :: reasonInfo=" + reasonInfo);
28296804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
283071382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
28316804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionInviteParticipantsRequestFailed :: not supported for " +
283271382693cbc81b1d131085f52d97879976706f55Anthony Lee                        "conference session=" + session);
283371382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
283471382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
283571382693cbc81b1d131085f52d97879976706f55Anthony Lee
2836ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2837ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2838ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2839ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2840ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2841ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2842ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2843ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2844ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallInviteParticipantsRequestFailed(ImsCall.this, reasonInfo);
2845ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2846ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionInviteParticipantsRequestFailed :: ", t);
2847ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2848ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2849ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2850ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2851ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2852ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionRemoveParticipantsRequestDelivered(ImsCallSession session) {
28536804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionRemoveParticipantsRequestDelivered ::");
28546804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
285571382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
28566804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionRemoveParticipantsRequestDelivered :: not supported for " +
285771382693cbc81b1d131085f52d97879976706f55Anthony Lee                        "conference session=" + session);
285871382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
285971382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
286071382693cbc81b1d131085f52d97879976706f55Anthony Lee
2861ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2862ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2863ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2864ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2865ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2866ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2867ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2868ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2869ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallRemoveParticipantsRequestDelivered(ImsCall.this);
2870ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2871ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionRemoveParticipantsRequestDelivered :: ", t);
2872ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2873ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2874ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2875ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2876ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2877ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionRemoveParticipantsRequestFailed(ImsCallSession session,
2878ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsReasonInfo reasonInfo) {
28796804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            loge("callSessionRemoveParticipantsRequestFailed :: reasonInfo=" + reasonInfo);
28806804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
288171382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
28826804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionRemoveParticipantsRequestFailed :: not supported for " +
28839bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn                        "conference session=" + session);
288471382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
288571382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
288671382693cbc81b1d131085f52d97879976706f55Anthony Lee
2887ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2888ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2889ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2890ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2891ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2892ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2893ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2894ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2895ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallRemoveParticipantsRequestFailed(ImsCall.this, reasonInfo);
2896ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2897ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionRemoveParticipantsRequestFailed :: ", t);
2898ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2899ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2900ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2901ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2902ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
2903ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        public void callSessionConferenceStateUpdated(ImsCallSession session,
2904ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                ImsConferenceState state) {
29056804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionConferenceStateUpdated :: state=" + state);
29066804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
2907938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn            conferenceStateUpdated(state);
2908ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2909ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2910ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        @Override
291171382693cbc81b1d131085f52d97879976706f55Anthony Lee        public void callSessionUssdMessageReceived(ImsCallSession session, int mode,
291271382693cbc81b1d131085f52d97879976706f55Anthony Lee                String ussdMessage) {
29136804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionUssdMessageReceived :: mode=" + mode + ", ussdMessage=" +
29146804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    ussdMessage);
29156804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
291671382693cbc81b1d131085f52d97879976706f55Anthony Lee            if (isTransientConferenceSession(session)) {
29176804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("callSessionUssdMessageReceived :: not supported for transient " +
2918b8799fe85b9387999f03ce7def6ace59903984a4Anthony Lee                        "conference session=" + session);
291971382693cbc81b1d131085f52d97879976706f55Anthony Lee                return;
292071382693cbc81b1d131085f52d97879976706f55Anthony Lee            }
292171382693cbc81b1d131085f52d97879976706f55Anthony Lee
2922ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            ImsCall.Listener listener;
2923ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2924ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            synchronized(ImsCall.this) {
2925ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                listener = mListener;
2926ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2927ef36ef67e009449300b0150c60c9f637e205d79eWink Saville
2928ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            if (listener != null) {
2929ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                try {
2930ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    listener.onCallUssdMessageReceived(ImsCall.this, mode, ussdMessage);
2931ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                } catch (Throwable t) {
2932ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                    loge("callSessionUssdMessageReceived :: ", t);
2933ef36ef67e009449300b0150c60c9f637e205d79eWink Saville                }
2934ef36ef67e009449300b0150c60c9f637e205d79eWink Saville            }
2935ef36ef67e009449300b0150c60c9f637e205d79eWink Saville        }
2936987bab859324396c0d1fc00c375f98f3f74c9067Pavel Zhamaitsiak
2937987bab859324396c0d1fc00c375f98f3f74c9067Pavel Zhamaitsiak        @Override
2938987bab859324396c0d1fc00c375f98f3f74c9067Pavel Zhamaitsiak        public void callSessionTtyModeReceived(ImsCallSession session, int mode) {
29396804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionTtyModeReceived :: mode=" + mode);
2940987bab859324396c0d1fc00c375f98f3f74c9067Pavel Zhamaitsiak
2941a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak            ImsCall.Listener listener;
2942a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak
2943a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak            synchronized(ImsCall.this) {
2944a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak                listener = mListener;
2945a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak            }
2946a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak
2947a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak            if (listener != null) {
2948a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak                try {
2949a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak                    listener.onCallSessionTtyModeReceived(ImsCall.this, mode);
2950a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak                } catch (Throwable t) {
2951a6cae36b881e26fa288a83c94b8c357fd436140ePavel Zhamaitsiak                    loge("callSessionTtyModeReceived :: ", t);
2952987bab859324396c0d1fc00c375f98f3f74c9067Pavel Zhamaitsiak                }
2953987bab859324396c0d1fc00c375f98f3f74c9067Pavel Zhamaitsiak            }
2954987bab859324396c0d1fc00c375f98f3f74c9067Pavel Zhamaitsiak        }
29551463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar
295625394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn        /**
295725394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn         * Notifies of a change to the multiparty state for this {@code ImsCallSession}.
295825394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn         *
295925394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn         * @param session The call session.
296025394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn         * @param isMultiParty {@code true} if the session became multiparty, {@code false}
296125394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn         *      otherwise.
296225394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn         */
296325394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn        @Override
296425394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn        public void callSessionMultipartyStateChanged(ImsCallSession session,
296525394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn                boolean isMultiParty) {
296625394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn            if (VDBG) {
2967691a1cc831e1bade18cb39f917f9aebbb5939ab8Pavel Zhamaitsiak                logi("callSessionMultipartyStateChanged isMultiParty: " + (isMultiParty ? "Y"
296825394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn                        : "N"));
296925394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn            }
297025394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn
297125394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn            ImsCall.Listener listener;
297225394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn
297325394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn            synchronized(ImsCall.this) {
297425394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn                listener = mListener;
297525394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn            }
297625394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn
297725394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn            if (listener != null) {
297825394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn                try {
297925394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn                    listener.onMultipartyStateChanged(ImsCall.this, isMultiParty);
298025394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn                } catch (Throwable t) {
298125394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn                    loge("callSessionMultipartyStateChanged :: ", t);
298225394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn                }
298325394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn            }
298425394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn        }
298525394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn
29861463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar        public void callSessionHandover(ImsCallSession session, int srcAccessTech,
29871463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            int targetAccessTech, ImsReasonInfo reasonInfo) {
29886804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("callSessionHandover :: session=" + session + ", srcAccessTech=" +
29896804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                srcAccessTech + ", targetAccessTech=" + targetAccessTech + ", reasonInfo=" +
29906804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                reasonInfo);
29911463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar
29921463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            ImsCall.Listener listener;
29931463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar
29941463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            synchronized(ImsCall.this) {
29951463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                listener = mListener;
29961463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            }
29971463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar
29981463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            if (listener != null) {
29991463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                try {
30001463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                    listener.onCallHandover(ImsCall.this, srcAccessTech, targetAccessTech,
30011463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                        reasonInfo);
30021463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                } catch (Throwable t) {
30031463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                    loge("callSessionHandover :: ", t);
30041463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                }
30051463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            }
30061463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar        }
30071463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar
30081463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar        @Override
30091463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar        public void callSessionHandoverFailed(ImsCallSession session, int srcAccessTech,
30101463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            int targetAccessTech, ImsReasonInfo reasonInfo) {
30116804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            loge("callSessionHandoverFailed :: session=" + session + ", srcAccessTech=" +
30126804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                srcAccessTech + ", targetAccessTech=" + targetAccessTech + ", reasonInfo=" +
30136804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                reasonInfo);
30141463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar
30151463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            ImsCall.Listener listener;
30161463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar
30171463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            synchronized(ImsCall.this) {
30181463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                listener = mListener;
30191463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            }
30201463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar
30211463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            if (listener != null) {
30221463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                try {
30231463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                    listener.onCallHandoverFailed(ImsCall.this, srcAccessTech, targetAccessTech,
30241463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                        reasonInfo);
30251463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                } catch (Throwable t) {
30261463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                    loge("callSessionHandoverFailed :: ", t);
30271463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar                }
30281463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar            }
30291463174fa4bab35f04dfa71196c277dfeb603717Rekha Kumar        }
3030d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh
3031d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh        @Override
3032d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh        public void callSessionSuppServiceReceived(ImsCallSession session,
3033d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh                ImsSuppServiceNotification suppServiceInfo ) {
3034d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh            if (isTransientConferenceSession(session)) {
3035d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh                logi("callSessionSuppServiceReceived :: not supported for transient conference"
3036d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh                        + " session=" + session);
3037d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh                return;
3038d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh            }
3039d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh
3040d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh            logi("callSessionSuppServiceReceived :: session=" + session +
3041d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh                     ", suppServiceInfo" + suppServiceInfo);
3042d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh
3043d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh            ImsCall.Listener listener;
3044d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh
3045d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh            synchronized(ImsCall.this) {
3046d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh                listener = mListener;
3047d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh            }
3048d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh
3049d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh            if (listener != null) {
3050d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh                try {
3051d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh                    listener.onCallSuppServiceReceived(ImsCall.this, suppServiceInfo);
3052d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh                } catch (Throwable t) {
3053d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh                    loge("callSessionSuppServiceReceived :: ", t);
3054d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh                }
3055d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh            }
3056d3adfadd868b19e2423674bfefa5ba778f743bf2Shriram Ganesh        }
3057bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu
3058bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu        @Override
3059bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu        public void callSessionRttModifyRequestReceived(ImsCallSession session,
3060bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu                ImsCallProfile callProfile) {
3061bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            ImsCall.Listener listener;
3062bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu
3063bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            synchronized(ImsCall.this) {
3064bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu                listener = mListener;
3065bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            }
3066bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu
3067bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            if (!callProfile.mMediaProfile.isRttCall()) {
3068bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu                logi("callSessionRttModifyRequestReceived:: ignoring request, requested profile " +
3069bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu                        "is not RTT.");
3070bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu                return;
3071bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            }
3072bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu
3073bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            if (listener != null) {
3074bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu                try {
3075bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu                    listener.onRttModifyRequestReceived(ImsCall.this);
3076bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu                } catch (Throwable t) {
3077bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu                    loge("callSessionRttModifyRequestReceived:: ", t);
3078bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu                }
3079bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            }
3080bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu        }
3081bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu
3082bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu        @Override
3083bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu        public void callSessionRttModifyResponseReceived(int status) {
3084bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            ImsCall.Listener listener;
3085bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu
3086bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            synchronized(ImsCall.this) {
3087bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu                listener = mListener;
3088bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            }
3089bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu
3090bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            if (listener != null) {
3091bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu                try {
3092bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu                    listener.onRttModifyResponseReceived(ImsCall.this, status);
3093bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu                } catch (Throwable t) {
3094bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu                    loge("callSessionRttModifyResponseReceived:: ", t);
3095bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu                }
3096bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            }
3097bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu        }
3098bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu
3099bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu        @Override
3100bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu        public void callSessionRttMessageReceived(String rttMessage) {
3101bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            ImsCall.Listener listener;
3102bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu
3103bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            synchronized(ImsCall.this) {
3104bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu                listener = mListener;
3105bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            }
3106bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu
3107bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            if (listener != null) {
3108bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu                try {
3109bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu                    listener.onRttMessageReceived(ImsCall.this, rttMessage);
3110bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu                } catch (Throwable t) {
3111bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu                    loge("callSessionRttModifyResponseReceived:: ", t);
3112bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu                }
3113bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu            }
3114bd3f377399138291ffcd072f4572be84c87dfa44Hall Liu        }
3115ef36ef67e009449300b0150c60c9f637e205d79eWink Saville    }
3116938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn
3117938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn    /**
3118938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     * Report a new conference state to the current {@link ImsCall} and inform listeners of the
3119938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     * change.  Marked as {@code VisibleForTesting} so that the
3120938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     * {@code com.android.internal.telephony.TelephonyTester} class can inject a test conference
3121938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     * event package into a regular ongoing IMS call.
3122938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     *
3123938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     * @param state The {@link ImsConferenceState}.
3124938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn     */
3125938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn    @VisibleForTesting
3126938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn    public void conferenceStateUpdated(ImsConferenceState state) {
3127938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn        Listener listener;
3128938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn
3129938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn        synchronized(this) {
3130938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn            notifyConferenceStateUpdated(state);
3131938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn            listener = mListener;
3132938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn        }
3133938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn
3134938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn        if (listener != null) {
3135938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn            try {
3136938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn                listener.onCallConferenceStateUpdated(this, state);
3137938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn            } catch (Throwable t) {
3138938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn                loge("callSessionConferenceStateUpdated :: ", t);
3139938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn            }
3140938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn        }
3141938116f08e88772f6736ddd7aa7541c204538b66Tyler Gunn    }
3142168c634eef29f21c73129164207d04b8cce23738Tyler Gunn
3143168c634eef29f21c73129164207d04b8cce23738Tyler Gunn    /**
3144168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     * Provides a human-readable string representation of an update request.
3145168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     *
3146168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     * @param updateRequest The update request.
3147168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     * @return The string representation.
3148168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     */
3149168c634eef29f21c73129164207d04b8cce23738Tyler Gunn    private String updateRequestToString(int updateRequest) {
3150168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        switch (updateRequest) {
3151168c634eef29f21c73129164207d04b8cce23738Tyler Gunn            case UPDATE_NONE:
3152168c634eef29f21c73129164207d04b8cce23738Tyler Gunn                return "NONE";
3153168c634eef29f21c73129164207d04b8cce23738Tyler Gunn            case UPDATE_HOLD:
3154168c634eef29f21c73129164207d04b8cce23738Tyler Gunn                return "HOLD";
3155168c634eef29f21c73129164207d04b8cce23738Tyler Gunn            case UPDATE_HOLD_MERGE:
3156168c634eef29f21c73129164207d04b8cce23738Tyler Gunn                return "HOLD_MERGE";
3157168c634eef29f21c73129164207d04b8cce23738Tyler Gunn            case UPDATE_RESUME:
3158168c634eef29f21c73129164207d04b8cce23738Tyler Gunn                return "RESUME";
3159168c634eef29f21c73129164207d04b8cce23738Tyler Gunn            case UPDATE_MERGE:
3160168c634eef29f21c73129164207d04b8cce23738Tyler Gunn                return "MERGE";
3161168c634eef29f21c73129164207d04b8cce23738Tyler Gunn            case UPDATE_EXTEND_TO_CONFERENCE:
3162168c634eef29f21c73129164207d04b8cce23738Tyler Gunn                return "EXTEND_TO_CONFERENCE";
3163168c634eef29f21c73129164207d04b8cce23738Tyler Gunn            case UPDATE_UNSPECIFIED:
3164168c634eef29f21c73129164207d04b8cce23738Tyler Gunn                return "UNSPECIFIED";
3165168c634eef29f21c73129164207d04b8cce23738Tyler Gunn            default:
3166168c634eef29f21c73129164207d04b8cce23738Tyler Gunn                return "UNKNOWN";
3167168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        }
3168168c634eef29f21c73129164207d04b8cce23738Tyler Gunn    }
3169168c634eef29f21c73129164207d04b8cce23738Tyler Gunn
3170168c634eef29f21c73129164207d04b8cce23738Tyler Gunn    /**
31719bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * Clears the merge peer for this call, ensuring that the peer's connection to this call is also
31729bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * severed at the same time.
31739bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     */
3174c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    private void clearMergeInfo() {
31756804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        if (CONF_DBG) {
31766804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            logi("clearMergeInfo :: clearing all merge info");
3177c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        }
3178047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
3179c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        // First clear out the merge partner then clear ourselves out.
31809bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (mMergeHost != null) {
31819bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            mMergeHost.mMergePeer = null;
3182165aed55d289ae2a5cdf34de4164c2395f46b8c1Libin.Tang@motorola.com            mMergeHost.mUpdateRequest = UPDATE_NONE;
3183c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            mMergeHost.mCallSessionMergePending = false;
31849bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        }
31859bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        if (mMergePeer != null) {
31869bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn            mMergePeer.mMergeHost = null;
3187165aed55d289ae2a5cdf34de4164c2395f46b8c1Libin.Tang@motorola.com            mMergePeer.mUpdateRequest = UPDATE_NONE;
3188c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            mMergePeer.mCallSessionMergePending = false;
31899bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        }
3190c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        mMergeHost = null;
3191c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        mMergePeer = null;
3192c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        mUpdateRequest = UPDATE_NONE;
3193c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        mCallSessionMergePending = false;
31949bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    }
31959bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
31969bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    /**
31979bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * Sets the merge peer for the current call.  The merge peer is the background call that will be
31989bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * merged into this call.  On the merge peer, sets the merge host to be this call.
31999bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     *
32009bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * @param mergePeer The peer call to be merged into this one.
32019bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     */
32029bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    private void setMergePeer(ImsCall mergePeer) {
32039bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        mMergePeer = mergePeer;
32049bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        mMergeHost = null;
32059bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
32069bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        mergePeer.mMergeHost = ImsCall.this;
32079bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        mergePeer.mMergePeer = null;
32089bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    }
32099bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
32109bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    /**
32119bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * Sets the merge hody for the current call.  The merge host is the foreground call this call
32129bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * will be merged into.  On the merge host, sets the merge peer to be this call.
32139bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     *
32149bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * @param mergeHost The merge host this call will be merged into.
32159bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     */
32169bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    public void setMergeHost(ImsCall mergeHost) {
32179bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        mMergeHost = mergeHost;
32189bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        mMergePeer = null;
32199bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
32209bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        mergeHost.mMergeHost = null;
32219bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        mergeHost.mMergePeer = ImsCall.this;
32229bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    }
32239bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
32249bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    /**
32259bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * Determines if the current call is in the process of merging with another call or conference.
32269bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     *
32279bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * @return {@code true} if in the process of merging.
32289bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     */
32299bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    private boolean isMerging() {
32309bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        return mMergePeer != null || mMergeHost != null;
32319bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    }
32329bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
32339bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    /**
32349bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * Determines if the current call is the host of the merge.
32359bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     *
32369bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * @return {@code true} if the call is the merge host.
32379bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     */
32389bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    private boolean isMergeHost() {
32399bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        return mMergePeer != null && mMergeHost == null;
32409bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    }
32419bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
32429bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    /**
32439bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * Determines if the current call is the peer of the merge.
32449bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     *
32459bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     * @return {@code true} if the call is the merge peer.
32469bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn     */
32479bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    private boolean isMergePeer() {
32489bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        return mMergePeer == null && mMergeHost != null;
32499bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    }
32509bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn
32519bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn    /**
3252047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * Determines if the call session is pending merge into a conference or not.
3253047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     *
3254047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * @return {@code true} if a merge into a conference is pending, {@code false} otherwise.
3255047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     */
3256083efaa4ca0c365b3429e862afd162638ba2d4ceTyler Gunn    public boolean isCallSessionMergePending() {
3257047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        return mCallSessionMergePending;
3258047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    }
3259047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
3260047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    /**
3261047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * Sets flag indicating whether the call session is pending merge into a conference or not.
3262047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     *
3263047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * @param callSessionMergePending {@code true} if a merge into the conference is pending,
3264047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     *      {@code false} otherwise.
3265047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     */
3266047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    private void setCallSessionMergePending(boolean callSessionMergePending) {
3267047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        mCallSessionMergePending = callSessionMergePending;
3268047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    }
3269047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
3270047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    /**
3271047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * Determines if there is a conference merge in process.  If there is a merge in process,
3272047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * determines if both the merge host and peer sessions have completed the merge process.  This
3273047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * means that we have received terminate or hold signals for the sessions, indicating that they
3274047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * are no longer in the process of being merged into the conference.
3275047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * <p>
3276c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * The sessions are considered to have merged if: both calls still have merge peer/host
3277c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * relationships configured,  both sessions are not waiting to be merged into the conference,
3278c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee     * and the transient conference session is alive in the case of an initial conference.
3279047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     *
3280047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     * @return {@code true} where the host and peer sessions have finished merging into the
3281047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     *      conference, {@code false} if the merge has not yet completed, and {@code false} if there
3282047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     *      is no conference merge in progress.
3283047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn     */
3284c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee    private boolean shouldProcessConferenceResult() {
3285c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        boolean areMergeTriggersDone = false;
3286c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee
3287c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        synchronized (ImsCall.this) {
3288c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // if there is a merge going on, then the merge host/peer relationships should have been
3289c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // set up.  This works for both the initial conference or merging a call into an
3290c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // existing conference.
3291c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            if (!isMergeHost() && !isMergePeer()) {
32926804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                if (CONF_DBG) {
32936804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    loge("shouldProcessConferenceResult :: no merge in progress");
3294c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                }
3295c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                return false;
3296c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            }
3297047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
3298c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // There is a merge in progress, so check the sessions to ensure:
3299c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // 1. Both calls have completed being merged (or failing to merge) into the conference.
3300c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            // 2. The transient conference session is alive.
3301c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            if (isMergeHost()) {
33026804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                if (CONF_DBG) {
33036804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    logi("shouldProcessConferenceResult :: We are a merge host");
33046804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    logi("shouldProcessConferenceResult :: Here is the merge peer=" + mMergePeer);
3305c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                }
3306c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                areMergeTriggersDone = !isCallSessionMergePending() &&
3307c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                        !mMergePeer.isCallSessionMergePending();
3308c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                if (!isMultiparty()) {
3309c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // Only check the transient session when there is no existing conference
3310c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    areMergeTriggersDone &= isSessionAlive(mTransientConferenceSession);
3311c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                }
3312c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            } else if (isMergePeer()) {
33136804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                if (CONF_DBG) {
33146804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    logi("shouldProcessConferenceResult :: We are a merge peer");
33156804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                    logi("shouldProcessConferenceResult :: Here is the merge host=" + mMergeHost);
3316c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                }
3317c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                areMergeTriggersDone = !isCallSessionMergePending() &&
3318c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                        !mMergeHost.isCallSessionMergePending();
3319c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                if (!mMergeHost.isMultiparty()) {
3320c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // Only check the transient session when there is no existing conference
3321c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    areMergeTriggersDone &= isSessionAlive(mMergeHost.mTransientConferenceSession);
3322c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                } else {
3323c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // This else block is a special case for Verizon to handle these steps
3324c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // 1. Establish a conference call.
3325c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // 2. Add a new call (conference in in BG)
3326c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // 3. Swap (conference active on FG)
3327c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // 4. Merge
3328c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // What happens here is that the BG call gets a terminated callback
3329c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // because it was added to the conference. I've seen where
3330c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // the FG gets no callback at all because its already active.
3331c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // So if we continue to wait for it to set its isCallSessionMerging
3332c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    // flag to false...we'll be waiting forever.
3333c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                    areMergeTriggersDone = !isCallSessionMergePending();
3334c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                }
3335c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            } else {
3336c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                // Realistically this shouldn't happen, but best to be safe.
3337c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                loge("shouldProcessConferenceResult : merge in progress but call is neither" +
33386804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                        " host nor peer.");
3339c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            }
33406804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            if (CONF_DBG) {
33416804851b58264d7e82b09a845118d24d36c8d831Anthony Lee                logi("shouldProcessConferenceResult :: returning:" +
3342c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee                        (areMergeTriggersDone ? "true" : "false"));
3343c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee            }
3344047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn        }
3345c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        return areMergeTriggersDone;
3346047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    }
3347047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn
3348047d8101113030f34f89f7c9ba015d6c5c3abba6Tyler Gunn    /**
3349168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     * Provides a string representation of the {@link ImsCall}.  Primarily intended for use in log
3350168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     * statements.
3351168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     *
3352168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     * @return String representation of call.
3353168c634eef29f21c73129164207d04b8cce23738Tyler Gunn     */
3354168c634eef29f21c73129164207d04b8cce23738Tyler Gunn    @Override
3355168c634eef29f21c73129164207d04b8cce23738Tyler Gunn    public String toString() {
3356168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        StringBuilder sb = new StringBuilder();
3357168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        sb.append("[ImsCall objId:");
3358168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        sb.append(System.identityHashCode(this));
33599bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        sb.append(" onHold:");
33609bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        sb.append(isOnHold() ? "Y" : "N");
33619bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        sb.append(" mute:");
33629bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        sb.append(isMuted() ? "Y" : "N");
336350b03e9261c7717817ebfb8e4086f949d0ad9c18Pavel Zhamaitsiak        if (mCallProfile != null) {
33649f71a24be06da7b4a0d51fd13fcb33efabcfea13Jack Yu            sb.append(" mCallProfile:" + mCallProfile);
336550b03e9261c7717817ebfb8e4086f949d0ad9c18Pavel Zhamaitsiak            sb.append(" tech:");
336650b03e9261c7717817ebfb8e4086f949d0ad9c18Pavel Zhamaitsiak            sb.append(mCallProfile.getCallExtra(ImsCallProfile.EXTRA_CALL_RAT_TYPE));
336750b03e9261c7717817ebfb8e4086f949d0ad9c18Pavel Zhamaitsiak        }
33689bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        sb.append(" updateRequest:");
33699bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        sb.append(updateRequestToString(mUpdateRequest));
337087466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn        sb.append(" merging:");
337187466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn        sb.append(isMerging() ? "Y" : "N");
337287466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn        if (isMerging()) {
337387466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn            if (isMergePeer()) {
337487466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                sb.append("P");
337587466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn            } else {
337687466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn                sb.append("H");
337787466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn            }
337887466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn        }
3379c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        sb.append(" merge action pending:");
3380c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        sb.append(isCallSessionMergePending() ? "Y" : "N");
338187466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn        sb.append(" merged:");
338287466c59b1980ec4e56bb17fae8b855efcc17fd8Tyler Gunn        sb.append(isMerged() ? "Y" : "N");
3383168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        sb.append(" multiParty:");
33849bd5ca59239ac4acdccf97c0ab7a2a4ab957bf28Tyler Gunn        sb.append(isMultiparty() ? "Y" : "N");
338525394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn        sb.append(" confHost:");
338625394099999f724f7806cbc7119ecca3708cf3b3Tyler Gunn        sb.append(isConferenceHost() ? "Y" : "N");
3387c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        sb.append(" buried term:");
3388c479f66e3d1f3cfdd3e88a050881f7cd663a5a90Anthony Lee        sb.append(mSessionEndDuringMerge ? "Y" : "N");
33899f71a24be06da7b4a0d51fd13fcb33efabcfea13Jack Yu        sb.append(" isVideo: ");
33909f71a24be06da7b4a0d51fd13fcb33efabcfea13Jack Yu        sb.append(isVideoCall() ? "Y" : "N");
33911ac24854dba02556692dbbd779434e5596f6daedTyler Gunn        sb.append(" wasVideo: ");
33921ac24854dba02556692dbbd779434e5596f6daedTyler Gunn        sb.append(mWasVideoCall ? "Y" : "N");
33939f71a24be06da7b4a0d51fd13fcb33efabcfea13Jack Yu        sb.append(" isWifi: ");
33949f71a24be06da7b4a0d51fd13fcb33efabcfea13Jack Yu        sb.append(isWifiCall() ? "Y" : "N");
3395168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        sb.append(" session:");
3396168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        sb.append(mSession);
3397168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        sb.append(" transientSession:");
3398168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        sb.append(mTransientConferenceSession);
3399168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        sb.append("]");
3400168c634eef29f21c73129164207d04b8cce23738Tyler Gunn        return sb.toString();
3401168c634eef29f21c73129164207d04b8cce23738Tyler Gunn    }
34026804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
34036804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    private void throwImsException(Throwable t, int code) throws ImsException {
34046804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        if (t instanceof ImsException) {
34056804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            throw (ImsException) t;
34066804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        } else {
34076804851b58264d7e82b09a845118d24d36c8d831Anthony Lee            throw new ImsException(String.valueOf(code), t, code);
34086804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        }
34096804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    }
34106804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
34116804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    /**
34126804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     * Append the ImsCall information to the provided string. Usefull for as a logging helper.
34136804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     * @param s The original string
34146804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     * @return The original string with {@code ImsCall} information appended to it.
34156804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     */
34166804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    private String appendImsCallInfoToString(String s) {
34176804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        StringBuilder sb = new StringBuilder();
34186804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        sb.append(s);
34196804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        sb.append(" ImsCall=");
34206804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        sb.append(ImsCall.this);
34216804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        return sb.toString();
34226804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    }
34236804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
34246804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    /**
34251ac24854dba02556692dbbd779434e5596f6daedTyler Gunn     * Updates {@link #mWasVideoCall} based on the current {@link ImsCallProfile} for the call.
34261ac24854dba02556692dbbd779434e5596f6daedTyler Gunn     *
34271ac24854dba02556692dbbd779434e5596f6daedTyler Gunn     * @param profile The current {@link ImsCallProfile} for the call.
34281ac24854dba02556692dbbd779434e5596f6daedTyler Gunn     */
34291ac24854dba02556692dbbd779434e5596f6daedTyler Gunn    private void trackVideoStateHistory(ImsCallProfile profile) {
34301ac24854dba02556692dbbd779434e5596f6daedTyler Gunn        mWasVideoCall = mWasVideoCall || profile.isVideoCall();
34311ac24854dba02556692dbbd779434e5596f6daedTyler Gunn    }
34321ac24854dba02556692dbbd779434e5596f6daedTyler Gunn
34331ac24854dba02556692dbbd779434e5596f6daedTyler Gunn    /**
34341ac24854dba02556692dbbd779434e5596f6daedTyler Gunn     * @return {@code true} if this call was a video call at some point in its life span,
34351ac24854dba02556692dbbd779434e5596f6daedTyler Gunn     *      {@code false} otherwise.
34361ac24854dba02556692dbbd779434e5596f6daedTyler Gunn     */
34371ac24854dba02556692dbbd779434e5596f6daedTyler Gunn    public boolean wasVideoCall() {
34381ac24854dba02556692dbbd779434e5596f6daedTyler Gunn        return mWasVideoCall;
34391ac24854dba02556692dbbd779434e5596f6daedTyler Gunn    }
34401ac24854dba02556692dbbd779434e5596f6daedTyler Gunn
34411ac24854dba02556692dbbd779434e5596f6daedTyler Gunn    /**
34421ac24854dba02556692dbbd779434e5596f6daedTyler Gunn     * @return {@code true} if this call is a video call, {@code false} otherwise.
34431ac24854dba02556692dbbd779434e5596f6daedTyler Gunn     */
34441ac24854dba02556692dbbd779434e5596f6daedTyler Gunn    public boolean isVideoCall() {
34451ac24854dba02556692dbbd779434e5596f6daedTyler Gunn        synchronized(mLockObj) {
34461ac24854dba02556692dbbd779434e5596f6daedTyler Gunn            return mCallProfile != null && mCallProfile.isVideoCall();
34471ac24854dba02556692dbbd779434e5596f6daedTyler Gunn        }
34481ac24854dba02556692dbbd779434e5596f6daedTyler Gunn    }
34491ac24854dba02556692dbbd779434e5596f6daedTyler Gunn
34501ac24854dba02556692dbbd779434e5596f6daedTyler Gunn    /**
34511ac24854dba02556692dbbd779434e5596f6daedTyler Gunn     * Determines if the current call radio access technology is over WIFI.
34521ac24854dba02556692dbbd779434e5596f6daedTyler Gunn     * Note: This depends on the RIL exposing the {@link ImsCallProfile#EXTRA_CALL_RAT_TYPE} extra.
34531ac24854dba02556692dbbd779434e5596f6daedTyler Gunn     * This method is primarily intended to be used when checking if answering an incoming audio
34541ac24854dba02556692dbbd779434e5596f6daedTyler Gunn     * call should cause a wifi video call to drop (e.g.
34551ac24854dba02556692dbbd779434e5596f6daedTyler Gunn     * {@link android.telephony.CarrierConfigManager#
34561ac24854dba02556692dbbd779434e5596f6daedTyler Gunn     * KEY_DROP_VIDEO_CALL_WHEN_ANSWERING_AUDIO_CALL_BOOL} is set).
34571ac24854dba02556692dbbd779434e5596f6daedTyler Gunn     *
34581ac24854dba02556692dbbd779434e5596f6daedTyler Gunn     * @return {@code true} if the call is over WIFI, {@code false} otherwise.
34591ac24854dba02556692dbbd779434e5596f6daedTyler Gunn     */
34601ac24854dba02556692dbbd779434e5596f6daedTyler Gunn    public boolean isWifiCall() {
34611ac24854dba02556692dbbd779434e5596f6daedTyler Gunn        synchronized(mLockObj) {
34621ac24854dba02556692dbbd779434e5596f6daedTyler Gunn            if (mCallProfile == null) {
34631ac24854dba02556692dbbd779434e5596f6daedTyler Gunn                return false;
34641ac24854dba02556692dbbd779434e5596f6daedTyler Gunn            }
34659d6410a77eefdb35f72a17d62e3c4dc21a71ea18Tyler Gunn            int radioTechnology = getRadioTechnology();
34669d6410a77eefdb35f72a17d62e3c4dc21a71ea18Tyler Gunn            return radioTechnology == ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN;
34679d6410a77eefdb35f72a17d62e3c4dc21a71ea18Tyler Gunn        }
34689d6410a77eefdb35f72a17d62e3c4dc21a71ea18Tyler Gunn    }
34699d6410a77eefdb35f72a17d62e3c4dc21a71ea18Tyler Gunn
34709d6410a77eefdb35f72a17d62e3c4dc21a71ea18Tyler Gunn    /**
34719d6410a77eefdb35f72a17d62e3c4dc21a71ea18Tyler Gunn     * Determines the radio access technology for the {@link ImsCall}.
34729d6410a77eefdb35f72a17d62e3c4dc21a71ea18Tyler Gunn     * @return The {@link ServiceState} {@code RIL_RADIO_TECHNOLOGY_*} code in use.
34739d6410a77eefdb35f72a17d62e3c4dc21a71ea18Tyler Gunn     */
34749d6410a77eefdb35f72a17d62e3c4dc21a71ea18Tyler Gunn    public int getRadioTechnology() {
34759d6410a77eefdb35f72a17d62e3c4dc21a71ea18Tyler Gunn        synchronized(mLockObj) {
34769d6410a77eefdb35f72a17d62e3c4dc21a71ea18Tyler Gunn            if (mCallProfile == null) {
34779d6410a77eefdb35f72a17d62e3c4dc21a71ea18Tyler Gunn                return ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN;
34789d6410a77eefdb35f72a17d62e3c4dc21a71ea18Tyler Gunn            }
34791ac24854dba02556692dbbd779434e5596f6daedTyler Gunn            String callType = mCallProfile.getCallExtra(ImsCallProfile.EXTRA_CALL_RAT_TYPE);
34808ae5fbb8c970ec7546762f89ed33eec37c4912c4Tyler Gunn            if (callType == null || callType.isEmpty()) {
34818ae5fbb8c970ec7546762f89ed33eec37c4912c4Tyler Gunn                callType = mCallProfile.getCallExtra(ImsCallProfile.EXTRA_CALL_RAT_TYPE_ALT);
34828ae5fbb8c970ec7546762f89ed33eec37c4912c4Tyler Gunn            }
34831ac24854dba02556692dbbd779434e5596f6daedTyler Gunn
34841ac24854dba02556692dbbd779434e5596f6daedTyler Gunn            // The RIL (sadly) sends us the EXTRA_CALL_RAT_TYPE as a string extra, rather than an
34851ac24854dba02556692dbbd779434e5596f6daedTyler Gunn            // integer extra, so we need to parse it.
34861ac24854dba02556692dbbd779434e5596f6daedTyler Gunn            int radioTechnology = ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN;
34871ac24854dba02556692dbbd779434e5596f6daedTyler Gunn            try {
34881ac24854dba02556692dbbd779434e5596f6daedTyler Gunn                radioTechnology = Integer.parseInt(callType);
34891ac24854dba02556692dbbd779434e5596f6daedTyler Gunn            } catch (NumberFormatException nfe) {
34901ac24854dba02556692dbbd779434e5596f6daedTyler Gunn                radioTechnology = ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN;
34911ac24854dba02556692dbbd779434e5596f6daedTyler Gunn            }
34921ac24854dba02556692dbbd779434e5596f6daedTyler Gunn
34939d6410a77eefdb35f72a17d62e3c4dc21a71ea18Tyler Gunn            return radioTechnology;
34941ac24854dba02556692dbbd779434e5596f6daedTyler Gunn        }
34951ac24854dba02556692dbbd779434e5596f6daedTyler Gunn    }
34961ac24854dba02556692dbbd779434e5596f6daedTyler Gunn
34971ac24854dba02556692dbbd779434e5596f6daedTyler Gunn    /**
34986804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     * Log a string to the radio buffer at the info level.
34996804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     * @param s The message to log
35006804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     */
35016804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    private void logi(String s) {
35026804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        Log.i(TAG, appendImsCallInfoToString(s));
35036804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    }
35046804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
35056804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    /**
35066804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     * Log a string to the radio buffer at the debug level.
35076804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     * @param s The message to log
35086804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     */
35096804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    private void logd(String s) {
35106804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        Log.d(TAG, appendImsCallInfoToString(s));
35116804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    }
35126804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
35136804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    /**
35146804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     * Log a string to the radio buffer at the verbose level.
35156804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     * @param s The message to log
35166804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     */
35176804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    private void logv(String s) {
35186804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        Log.v(TAG, appendImsCallInfoToString(s));
35196804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    }
35206804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
35216804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    /**
35226804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     * Log a string to the radio buffer at the error level.
35236804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     * @param s The message to log
35246804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     */
35256804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    private void loge(String s) {
35266804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        Log.e(TAG, appendImsCallInfoToString(s));
35276804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    }
35286804851b58264d7e82b09a845118d24d36c8d831Anthony Lee
35296804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    /**
35306804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     * Log a string to the radio buffer at the error level with a throwable
35316804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     * @param s The message to log
35326804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     * @param t The associated throwable
35336804851b58264d7e82b09a845118d24d36c8d831Anthony Lee     */
35346804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    private void loge(String s, Throwable t) {
35356804851b58264d7e82b09a845118d24d36c8d831Anthony Lee        Log.e(TAG, appendImsCallInfoToString(s), t);
35366804851b58264d7e82b09a845118d24d36c8d831Anthony Lee    }
3537ef36ef67e009449300b0150c60c9f637e205d79eWink Saville}
3538