163aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordon/*
263aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordon * Copyright 2014, The Android Open Source Project
363aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordon *
463aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordon * Licensed under the Apache License, Version 2.0 (the "License");
563aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordon * you may not use this file except in compliance with the License.
663aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordon * You may obtain a copy of the License at
763aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordon *
863aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordon *     http://www.apache.org/licenses/LICENSE-2.0
963aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordon *
1063aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordon * Unless required by applicable law or agreed to in writing, software
1163aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordon * distributed under the License is distributed on an "AS IS" BASIS,
1263aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordon * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1363aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordon * See the License for the specific language governing permissions and
1463aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordon * limitations under the License.
1563aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordon */
1663aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordon
177cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnpackage com.android.server.telecom;
1863aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordon
195924beafe09bf3fb710ec1bafd59113a12b45adaSantos Cordonimport android.content.ComponentName;
2091d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunnimport android.content.Context;
21e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepalimport android.net.Uri;
22512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awadimport android.os.Binder;
23a05805b839edea9b9fe3bd4a0fbaf310c2a32838Evan Charltonimport android.os.Bundle;
2463aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordonimport android.os.IBinder;
2563aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordonimport android.os.RemoteException;
26105d977687d1d0de7cd9420fc140b01404261df1Evan Charltonimport android.os.UserHandle;
272a66f7b906b225413ae33f72e70a75e4f9c883c0Yorke Leeimport android.telecom.CallAudioState;
287cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.Connection;
297cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.ConnectionRequest;
307cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.ConnectionService;
31701dc006ac11625b55d872f1639107b028933895Andrew Leeimport android.telecom.DisconnectCause;
327cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.GatewayInfo;
337cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.ParcelableConference;
347cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.ParcelableConnection;
357cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.PhoneAccountHandle;
367cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.StatusHints;
377cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.TelecomManager;
387cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport android.telecom.VideoProfile;
39a439e1b6d6201dedecfc40b67c9347a8c563b9c1Sailesh Nepal
407cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport com.android.internal.telecom.IConnectionService;
417cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport com.android.internal.telecom.IConnectionServiceAdapter;
427cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport com.android.internal.telecom.IVideoProvider;
437cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunnimport com.android.internal.telecom.RemoteServiceCallback;
4491d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunnimport com.android.internal.util.Preconditions;
453d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon
465924beafe09bf3fb710ec1bafd59113a12b45adaSantos Cordonimport java.util.ArrayList;
47b78b27693afbe9736f0a54ec473328955251f885Ihab Awadimport java.util.Collections;
48682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordonimport java.util.HashMap;
498f3282c49bd4e8e6de59be4bdaefc726d99a3273Santos Cordonimport java.util.List;
50682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordonimport java.util.Map;
513d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordonimport java.util.Set;
52a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shraunerimport java.util.concurrent.ConcurrentHashMap;
5363aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordon
5463aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordon/**
55c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal * Wrapper for {@link IConnectionService}s, handles binding to {@link IConnectionService} and keeps
56c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal * track of when the object can safely be unbound. Other classes should not use
57c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal * {@link IConnectionService} directly and instead should use this class to invoke methods of
58c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal * {@link IConnectionService}.
5963aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordon */
6078a5e6b9c1595c81f72d7a822617cb78db224e48Ihab Awadfinal class ConnectionServiceWrapper extends ServiceBinder {
61c195e3613af47a49e76821d3f24c05adb71cf920Santos Cordon
62c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal    private final class Adapter extends IConnectionServiceAdapter.Stub {
636fb37c87836b5245046bd3b14320823ab839a10cIhab Awad
643d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon        @Override
65fb5560d634aef745466e8869f8acf496447da17bIhab Awad        public void handleCreateConnectionComplete(
666fb37c87836b5245046bd3b14320823ab839a10cIhab Awad                String callId,
676fb37c87836b5245046bd3b14320823ab839a10cIhab Awad                ConnectionRequest request,
686fb37c87836b5245046bd3b14320823ab839a10cIhab Awad                ParcelableConnection connection) {
69512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            long token = Binder.clearCallingIdentity();
70512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            try {
71512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                synchronized (mLock) {
72512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    logIncoming("handleCreateConnectionComplete %s", callId);
73512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    if (mCallIdMapper.isValidCallId(callId)) {
74512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        ConnectionServiceWrapper.this
75512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                                .handleCreateConnectionComplete(callId, request, connection);
76512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    }
778d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                }
78512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            } finally {
79512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                Binder.restoreCallingIdentity(token);
80969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner            }
813d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon        }
823d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon
833d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon        @Override
843d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon        public void setActive(String callId) {
85512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            long token = Binder.clearCallingIdentity();
86512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            try {
87512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                synchronized (mLock) {
88512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    logIncoming("setActive %s", callId);
89512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    if (mCallIdMapper.isValidCallId(callId) || mCallIdMapper
90512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            .isValidConferenceId(callId)) {
91512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        Call call = mCallIdMapper.getCall(callId);
92512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        if (call != null) {
93512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            mCallsManager.markCallAsActive(call);
94512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        } else {
95512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            // Log.w(this, "setActive, unknown call id: %s", msg.obj);
96512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        }
978d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                    }
988d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                }
99512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            } finally {
100512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                Binder.restoreCallingIdentity(token);
101969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner            }
1023d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon        }
1033d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon
1043d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon        @Override
1053d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon        public void setRinging(String callId) {
106512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            long token = Binder.clearCallingIdentity();
107512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            try {
108512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                synchronized (mLock) {
109512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    logIncoming("setRinging %s", callId);
110512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    if (mCallIdMapper.isValidCallId(callId)) {
111512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        Call call = mCallIdMapper.getCall(callId);
112512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        if (call != null) {
113512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            mCallsManager.markCallAsRinging(call);
114512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        } else {
115512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            // Log.w(this, "setRinging, unknown call id: %s", msg.obj);
116512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        }
1178d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                    }
1188d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                }
119512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            } finally {
120512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                Binder.restoreCallingIdentity(token);
121969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner            }
1223d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon        }
1233d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon
1243d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon        @Override
1256fb37c87836b5245046bd3b14320823ab839a10cIhab Awad        public void setVideoProvider(String callId, IVideoProvider videoProvider) {
126512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            long token = Binder.clearCallingIdentity();
127512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            try {
128512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                synchronized (mLock) {
129512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    logIncoming("setVideoProvider %s", callId);
130032f8e415661339bd1e9a2da5e295062a996a7f5Rekha Kumar                    if (mCallIdMapper.isValidCallId(callId)
131032f8e415661339bd1e9a2da5e295062a996a7f5Rekha Kumar                            || mCallIdMapper.isValidConferenceId(callId)) {
132512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        Call call = mCallIdMapper.getCall(callId);
133512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        if (call != null) {
134512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            call.setVideoProvider(videoProvider);
135512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        }
1368d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                    }
1378d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                }
138512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            } finally {
139512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                Binder.restoreCallingIdentity(token);
140969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner            }
141e9a776560dfe6f000cfc0dc1ea36c0f37d937f53Andrew Lee        }
142e9a776560dfe6f000cfc0dc1ea36c0f37d937f53Andrew Lee
143e9a776560dfe6f000cfc0dc1ea36c0f37d937f53Andrew Lee        @Override
1443d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon        public void setDialing(String callId) {
145512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            long token = Binder.clearCallingIdentity();
146512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            try {
147512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                synchronized (mLock) {
148512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    logIncoming("setDialing %s", callId);
149512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    if (mCallIdMapper.isValidCallId(callId)) {
150512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        Call call = mCallIdMapper.getCall(callId);
151512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        if (call != null) {
152512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            mCallsManager.markCallAsDialing(call);
153512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        } else {
154512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            // Log.w(this, "setDialing, unknown call id: %s", msg.obj);
155512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        }
1568d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                    }
1578d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                }
158512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            } finally {
159512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                Binder.restoreCallingIdentity(token);
160969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner            }
1613d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon        }
1623d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon
1633d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon        @Override
164701dc006ac11625b55d872f1639107b028933895Andrew Lee        public void setDisconnected(String callId, DisconnectCause disconnectCause) {
165512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            long token = Binder.clearCallingIdentity();
166512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            try {
167512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                synchronized (mLock) {
168512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    logIncoming("setDisconnected %s %s", callId, disconnectCause);
169512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    if (mCallIdMapper.isValidCallId(callId) || mCallIdMapper
170512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            .isValidConferenceId(callId)) {
171512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        Call call = mCallIdMapper.getCall(callId);
172512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        Log.d(this, "disconnect call %s %s", disconnectCause, call);
173512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        if (call != null) {
174512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            mCallsManager.markCallAsDisconnected(call, disconnectCause);
175512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        } else {
176512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            // Log.w(this, "setDisconnected, unknown call id: %s", args.arg1);
177512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        }
1788d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                    }
1798d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                }
180512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            } finally {
181512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                Binder.restoreCallingIdentity(token);
182969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner            }
1833d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon        }
1843d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon
1853d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon        @Override
1863d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon        public void setOnHold(String callId) {
187512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            long token = Binder.clearCallingIdentity();
188512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            try {
189512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                synchronized (mLock) {
190512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    logIncoming("setOnHold %s", callId);
191512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    if (mCallIdMapper.isValidCallId(callId) || mCallIdMapper
192512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            .isValidConferenceId(callId)) {
193512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        Call call = mCallIdMapper.getCall(callId);
194512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        if (call != null) {
195512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            mCallsManager.markCallAsOnHold(call);
196512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        } else {
197512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            // Log.w(this, "setOnHold, unknown call id: %s", msg.obj);
198512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        }
1998d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                    }
2008d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                }
201512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            } finally {
202512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                Binder.restoreCallingIdentity(token);
203969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner            }
2043d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon        }
20550a57136b3aa876c8311b58e1e11720a337fe1ccIhab Awad
20650a57136b3aa876c8311b58e1e11720a337fe1ccIhab Awad        @Override
2075be64bc46c23b614d5452ca398a6bb7a512f1887Andrew Lee        public void setRingbackRequested(String callId, boolean ringback) {
208512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            long token = Binder.clearCallingIdentity();
209512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            try {
210512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                synchronized (mLock) {
211512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    logIncoming("setRingbackRequested %s %b", callId, ringback);
212512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    if (mCallIdMapper.isValidCallId(callId)) {
213512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        Call call = mCallIdMapper.getCall(callId);
214512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        if (call != null) {
215512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            call.setRingbackRequested(ringback);
216512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        } else {
217512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            // Log.w(this, "setRingback, unknown call id: %s", args.arg1);
218512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        }
2198d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                    }
2208d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                }
221512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            } finally {
222512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                Binder.restoreCallingIdentity(token);
223969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner            }
22450a57136b3aa876c8311b58e1e11720a337fe1ccIhab Awad        }
2258f3282c49bd4e8e6de59be4bdaefc726d99a3273Santos Cordon
2268f3282c49bd4e8e6de59be4bdaefc726d99a3273Santos Cordon        @Override
2278f3282c49bd4e8e6de59be4bdaefc726d99a3273Santos Cordon        public void removeCall(String callId) {
228512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            long token = Binder.clearCallingIdentity();
229512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            try {
230512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                synchronized (mLock) {
231512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    logIncoming("removeCall %s", callId);
232512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    if (mCallIdMapper.isValidCallId(callId) || mCallIdMapper
233512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            .isValidConferenceId(callId)) {
234512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        Call call = mCallIdMapper.getCall(callId);
235512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        if (call != null) {
236512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            if (call.isAlive()) {
237512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                                mCallsManager.markCallAsDisconnected(
238512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                                        call, new DisconnectCause(DisconnectCause.REMOTE));
239512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            } else {
240512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                                mCallsManager.markCallAsRemoved(call);
241512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            }
2428d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                        }
2438d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                    }
2448d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                }
245512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            } finally {
246512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                Binder.restoreCallingIdentity(token);
247a02bef5d67f261d7457d0dab9e51595f1960128bIhab Awad            }
2488f3282c49bd4e8e6de59be4bdaefc726d99a3273Santos Cordon        }
2498f3282c49bd4e8e6de59be4bdaefc726d99a3273Santos Cordon
2508f3282c49bd4e8e6de59be4bdaefc726d99a3273Santos Cordon        @Override
25107bc5ee853bc9a0b4cd46e0c702888b2c7989392Ihab Awad        public void setConnectionCapabilities(String callId, int connectionCapabilities) {
252512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            long token = Binder.clearCallingIdentity();
253512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            try {
254512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                synchronized (mLock) {
255512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    logIncoming("setConnectionCapabilities %s %d", callId, connectionCapabilities);
256512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    if (mCallIdMapper.isValidCallId(callId) || mCallIdMapper
257512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            .isValidConferenceId(callId)) {
258512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        Call call = mCallIdMapper.getCall(callId);
259512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        if (call != null) {
260512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            call.setConnectionCapabilities(connectionCapabilities);
261512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        } else {
262512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            // Log.w(ConnectionServiceWrapper.this,
263512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            // "setConnectionCapabilities, unknown call id: %s", msg.obj);
264512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        }
2658d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                    }
2668d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                }
267512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            } finally {
268512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                Binder.restoreCallingIdentity(token);
269969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner            }
2708f3282c49bd4e8e6de59be4bdaefc726d99a3273Santos Cordon        }
2718f3282c49bd4e8e6de59be4bdaefc726d99a3273Santos Cordon
2728f3282c49bd4e8e6de59be4bdaefc726d99a3273Santos Cordon        @Override
273a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        public void setIsConferenced(String callId, String conferenceCallId) {
274512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            long token = Binder.clearCallingIdentity();
275512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            try {
276512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                synchronized (mLock) {
277512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    logIncoming("setIsConferenced %s %s", callId, conferenceCallId);
278512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    Call childCall = mCallIdMapper.getCall(callId);
279512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    if (childCall != null) {
280512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        if (conferenceCallId == null) {
281512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            Log.d(this, "unsetting parent: %s", conferenceCallId);
282512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            childCall.setParentCall(null);
283512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        } else {
284512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            Call conferenceCall = mCallIdMapper.getCall(conferenceCallId);
285512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            childCall.setParentCall(conferenceCall);
286512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        }
2878d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                    } else {
288512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        // Log.w(this, "setIsConferenced, unknown call id: %s", args.arg1);
2898d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                    }
2908d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                }
291512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            } finally {
292512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                Binder.restoreCallingIdentity(token);
2938d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad            }
294a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        }
295a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
296a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        @Override
297ce75aa1cfa3572f208d02a058b7aaf025ad6856cAnthony Lee        public void setConferenceMergeFailed(String callId) {
298ce75aa1cfa3572f208d02a058b7aaf025ad6856cAnthony Lee            long token = Binder.clearCallingIdentity();
299ce75aa1cfa3572f208d02a058b7aaf025ad6856cAnthony Lee            try {
300ce75aa1cfa3572f208d02a058b7aaf025ad6856cAnthony Lee                synchronized (mLock) {
301ce75aa1cfa3572f208d02a058b7aaf025ad6856cAnthony Lee                    logIncoming("setConferenceMergeFailed %s", callId);
302ce75aa1cfa3572f208d02a058b7aaf025ad6856cAnthony Lee                    if (mCallIdMapper.isValidCallId(callId)) {
303ce75aa1cfa3572f208d02a058b7aaf025ad6856cAnthony Lee                        // TODO: we should move the UI for indication a merge failure here
304ce75aa1cfa3572f208d02a058b7aaf025ad6856cAnthony Lee                        // from CallNotifier.onSuppServiceFailed(). This way the InCallUI can
305ce75aa1cfa3572f208d02a058b7aaf025ad6856cAnthony Lee                        // deliver the message anyway that they want. b/20530631.
306ce75aa1cfa3572f208d02a058b7aaf025ad6856cAnthony Lee                        Call call = mCallIdMapper.getCall(callId);
307ce75aa1cfa3572f208d02a058b7aaf025ad6856cAnthony Lee                        if (call != null) {
308ce75aa1cfa3572f208d02a058b7aaf025ad6856cAnthony Lee                            // Just refresh the connection capabilities so that the UI
309ce75aa1cfa3572f208d02a058b7aaf025ad6856cAnthony Lee                            // is forced to reenable the merge button as the capability
310ce75aa1cfa3572f208d02a058b7aaf025ad6856cAnthony Lee                            // is still on the connection. Note when b/20530631 is fixed, we need
311ce75aa1cfa3572f208d02a058b7aaf025ad6856cAnthony Lee                            // to revisit this fix to remove this hacky way of unhiding the merge
312ce75aa1cfa3572f208d02a058b7aaf025ad6856cAnthony Lee                            // button (side effect of reprocessing the capabilities) and plumb
313ce75aa1cfa3572f208d02a058b7aaf025ad6856cAnthony Lee                            // the failure event all the way to InCallUI instead of stopping
314ce75aa1cfa3572f208d02a058b7aaf025ad6856cAnthony Lee                            // it here. That way we can also handle the UI of notifying that
315ce75aa1cfa3572f208d02a058b7aaf025ad6856cAnthony Lee                            // the merged has failed.
316ce75aa1cfa3572f208d02a058b7aaf025ad6856cAnthony Lee                            call.setConnectionCapabilities(call.getConnectionCapabilities(), true);
317ce75aa1cfa3572f208d02a058b7aaf025ad6856cAnthony Lee                        } else {
318ce75aa1cfa3572f208d02a058b7aaf025ad6856cAnthony Lee                            Log.w(this, "setConferenceMergeFailed, unknown call id: %s", callId);
319ce75aa1cfa3572f208d02a058b7aaf025ad6856cAnthony Lee                        }
320ce75aa1cfa3572f208d02a058b7aaf025ad6856cAnthony Lee                    }
321ce75aa1cfa3572f208d02a058b7aaf025ad6856cAnthony Lee
322ce75aa1cfa3572f208d02a058b7aaf025ad6856cAnthony Lee                }
323ce75aa1cfa3572f208d02a058b7aaf025ad6856cAnthony Lee            } finally {
324ce75aa1cfa3572f208d02a058b7aaf025ad6856cAnthony Lee                Binder.restoreCallingIdentity(token);
325ce75aa1cfa3572f208d02a058b7aaf025ad6856cAnthony Lee            }
326ce75aa1cfa3572f208d02a058b7aaf025ad6856cAnthony Lee        }
327ce75aa1cfa3572f208d02a058b7aaf025ad6856cAnthony Lee
328ce75aa1cfa3572f208d02a058b7aaf025ad6856cAnthony Lee        @Override
3290fbe6321e341ddce186634266dba2db3fa426b88Santos Cordon        public void addConferenceCall(String callId, ParcelableConference parcelableConference) {
330512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            long token = Binder.clearCallingIdentity();
331512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            try {
332512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                synchronized (mLock) {
333512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    if (mCallIdMapper.getCall(callId) != null) {
334512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        Log.w(this, "Attempting to add a conference call using an existing " +
335512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                                "call id %s", callId);
336512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        return;
337512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    }
3388d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad
339512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    // Make sure that there's at least one valid call. For remote connections
340512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    // we'll get a add conference msg from both the remote connection service
341512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    // and from the real connection service.
342512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    boolean hasValidCalls = false;
343512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    for (String connId : parcelableConference.getConnectionIds()) {
344512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        if (mCallIdMapper.getCall(connId) != null) {
345512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            hasValidCalls = true;
346512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        }
347512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    }
348512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    // But don't bail out if the connection count is 0, because that is a valid
349512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    // IMS conference state.
350512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    if (!hasValidCalls && parcelableConference.getConnectionIds().size() > 0) {
351512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        Log.d(this, "Attempting to add a conference with no valid calls");
352512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        return;
3538d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                    }
3548d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad
355512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    // need to create a new Call
356512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    PhoneAccountHandle phAcc = null;
357512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    if (parcelableConference != null &&
358512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            parcelableConference.getPhoneAccount() != null) {
359512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        phAcc = parcelableConference.getPhoneAccount();
360512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    }
361512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    Call conferenceCall = mCallsManager.createConferenceCall(
362512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            phAcc, parcelableConference);
363512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    mCallIdMapper.addCall(conferenceCall, callId);
364512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    conferenceCall.setConnectionService(ConnectionServiceWrapper.this);
365512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad
366512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    Log.d(this, "adding children to conference %s phAcc %s",
367512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            parcelableConference.getConnectionIds(), phAcc);
368512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    for (String connId : parcelableConference.getConnectionIds()) {
369512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        Call childCall = mCallIdMapper.getCall(connId);
370512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        Log.d(this, "found child: %s", connId);
371512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        if (childCall != null) {
372512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            childCall.setParentCall(conferenceCall);
373512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        }
3748d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                    }
3758d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                }
376512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            } finally {
377512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                Binder.restoreCallingIdentity(token);
3788d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad            }
3798f3282c49bd4e8e6de59be4bdaefc726d99a3273Santos Cordon        }
380352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton
381352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton        @Override
382352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton        public void onPostDialWait(String callId, String remaining) throws RemoteException {
383512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            long token = Binder.clearCallingIdentity();
384512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            try {
385512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                synchronized (mLock) {
386512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    logIncoming("onPostDialWait %s %s", callId, remaining);
387512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    if (mCallIdMapper.isValidCallId(callId)) {
388512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        Call call = mCallIdMapper.getCall(callId);
389512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        if (call != null) {
390512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            call.onPostDialWait(remaining);
391512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        } else {
392512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            // Log.w(this, "onPostDialWait, unknown call id: %s", args.arg1);
393512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        }
3948d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                    }
3958d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                }
396512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            } finally {
397512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                Binder.restoreCallingIdentity(token);
398969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner            }
399352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton        }
4006098d2c392f8698f8f4885da6edf6c5b8d7e4cb9Sailesh Nepal
4015924beafe09bf3fb710ec1bafd59113a12b45adaSantos Cordon        @Override
402a469f76c1710a945933910840f11f9fda0445d82Nancy Chen        public void onPostDialChar(String callId, char nextChar) throws RemoteException {
403512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            long token = Binder.clearCallingIdentity();
404512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            try {
405512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                synchronized (mLock) {
406512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    logIncoming("onPostDialChar %s %s", callId, nextChar);
407512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    if (mCallIdMapper.isValidCallId(callId)) {
408512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        Call call = mCallIdMapper.getCall(callId);
409512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        if (call != null) {
410512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            call.onPostDialChar(nextChar);
411512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        } else {
412512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            // Log.w(this, "onPostDialChar, unknown call id: %s", args.arg1);
413512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        }
4148d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                    }
4158d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                }
416512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            } finally {
417512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                Binder.restoreCallingIdentity(token);
418a469f76c1710a945933910840f11f9fda0445d82Nancy Chen            }
419a469f76c1710a945933910840f11f9fda0445d82Nancy Chen        }
420a469f76c1710a945933910840f11f9fda0445d82Nancy Chen
421a469f76c1710a945933910840f11f9fda0445d82Nancy Chen        @Override
4225924beafe09bf3fb710ec1bafd59113a12b45adaSantos Cordon        public void queryRemoteConnectionServices(RemoteServiceCallback callback) {
423512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            long token = Binder.clearCallingIdentity();
424512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            try {
425512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                synchronized (mLock) {
426512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    logIncoming("queryRemoteConnectionServices %s", callback);
427512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    ConnectionServiceWrapper.this.queryRemoteConnectionServices(callback);
428512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                }
429512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            } finally {
430512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                Binder.restoreCallingIdentity(token);
4318d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad            }
4325924beafe09bf3fb710ec1bafd59113a12b45adaSantos Cordon        }
433e19cc005ddbff5313d6f7288587630b2410d005cTyler Gunn
434e19cc005ddbff5313d6f7288587630b2410d005cTyler Gunn        @Override
4350a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn        public void setVideoState(String callId, int videoState) {
436512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            long token = Binder.clearCallingIdentity();
437512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            try {
438512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                synchronized (mLock) {
439512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    logIncoming("setVideoState %s %d", callId, videoState);
440032f8e415661339bd1e9a2da5e295062a996a7f5Rekha Kumar                    if (mCallIdMapper.isValidCallId(callId)
441032f8e415661339bd1e9a2da5e295062a996a7f5Rekha Kumar                            || mCallIdMapper.isValidConferenceId(callId)) {
442512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        Call call = mCallIdMapper.getCall(callId);
443512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        if (call != null) {
444512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            call.setVideoState(videoState);
445512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        }
4468d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                    }
4478d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                }
448512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            } finally {
449512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                Binder.restoreCallingIdentity(token);
450969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner            }
4510a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn        }
4520a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn
4530a388fc566576513f54610c4427fb30feb88ab02Tyler Gunn        @Override
4545be64bc46c23b614d5452ca398a6bb7a512f1887Andrew Lee        public void setIsVoipAudioMode(String callId, boolean isVoip) {
455512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            long token = Binder.clearCallingIdentity();
456512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            try {
457512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                synchronized (mLock) {
458512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    logIncoming("setIsVoipAudioMode %s %b", callId, isVoip);
459512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    if (mCallIdMapper.isValidCallId(callId)) {
460512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        Call call = mCallIdMapper.getCall(callId);
461512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        if (call != null) {
462512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            call.setIsVoipAudioMode(isVoip);
463512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        }
4648d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                    }
4658d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                }
466512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            } finally {
467512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                Binder.restoreCallingIdentity(token);
468969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner            }
4697e66957928c5c23a1028c8e2a2d7cf359cbfa44eSailesh Nepal        }
47035faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal
47135faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal        @Override
47235faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal        public void setStatusHints(String callId, StatusHints statusHints) {
473512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            long token = Binder.clearCallingIdentity();
474512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            try {
475512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                synchronized (mLock) {
476512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    logIncoming("setStatusHints %s %s", callId, statusHints);
4770751e61ed2fd4fd828a4ca170a696fce369b31eaAndrew Lee                    if (mCallIdMapper.isValidCallId(callId)
4780751e61ed2fd4fd828a4ca170a696fce369b31eaAndrew Lee                            || mCallIdMapper.isValidConferenceId(callId)) {
479512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        Call call = mCallIdMapper.getCall(callId);
480512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        if (call != null) {
481512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            call.setStatusHints(statusHints);
482512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        }
4838d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                    }
4848d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                }
485512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            } finally {
486512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                Binder.restoreCallingIdentity(token);
487969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner            }
48835faf8cf29dc0f4a73935478e0fba957df9619d6Sailesh Nepal        }
489e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal
490e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        @Override
491b3907b3e79864a3a42d5e7105e5051f7e364fdbaSantos Cordon        public void setExtras(String callId, Bundle extras) {
492b3907b3e79864a3a42d5e7105e5051f7e364fdbaSantos Cordon            long token = Binder.clearCallingIdentity();
493b3907b3e79864a3a42d5e7105e5051f7e364fdbaSantos Cordon            try {
494b3907b3e79864a3a42d5e7105e5051f7e364fdbaSantos Cordon                synchronized(mLock) {
495b3907b3e79864a3a42d5e7105e5051f7e364fdbaSantos Cordon                    logIncoming("setExtras %s %s", callId, extras);
496b3907b3e79864a3a42d5e7105e5051f7e364fdbaSantos Cordon                    if (mCallIdMapper.isValidCallId(callId)
497b3907b3e79864a3a42d5e7105e5051f7e364fdbaSantos Cordon                            || mCallIdMapper.isValidConferenceId(callId)) {
498b3907b3e79864a3a42d5e7105e5051f7e364fdbaSantos Cordon                        Call call = mCallIdMapper.getCall(callId);
499b3907b3e79864a3a42d5e7105e5051f7e364fdbaSantos Cordon                        if (call != null) {
500b3907b3e79864a3a42d5e7105e5051f7e364fdbaSantos Cordon                            call.setExtras(extras);
501b3907b3e79864a3a42d5e7105e5051f7e364fdbaSantos Cordon                        }
502b3907b3e79864a3a42d5e7105e5051f7e364fdbaSantos Cordon                    }
503b3907b3e79864a3a42d5e7105e5051f7e364fdbaSantos Cordon                }
504b3907b3e79864a3a42d5e7105e5051f7e364fdbaSantos Cordon            } finally {
505b3907b3e79864a3a42d5e7105e5051f7e364fdbaSantos Cordon                Binder.restoreCallingIdentity(token);
506b3907b3e79864a3a42d5e7105e5051f7e364fdbaSantos Cordon            }
507b3907b3e79864a3a42d5e7105e5051f7e364fdbaSantos Cordon        }
508b3907b3e79864a3a42d5e7105e5051f7e364fdbaSantos Cordon
509b3907b3e79864a3a42d5e7105e5051f7e364fdbaSantos Cordon        @Override
5105be64bc46c23b614d5452ca398a6bb7a512f1887Andrew Lee        public void setAddress(String callId, Uri address, int presentation) {
511512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            long token = Binder.clearCallingIdentity();
512512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            try {
513512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                synchronized (mLock) {
514512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    logIncoming("setAddress %s %s %d", callId, address, presentation);
515512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    if (mCallIdMapper.isValidCallId(callId)) {
516512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        Call call = mCallIdMapper.getCall(callId);
517512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        if (call != null) {
518512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            call.setHandle(address, presentation);
519512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        }
5208d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                    }
5218d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                }
522512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            } finally {
523512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                Binder.restoreCallingIdentity(token);
524969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner            }
525e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        }
526e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal
527e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        @Override
528e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        public void setCallerDisplayName(
529e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal                String callId, String callerDisplayName, int presentation) {
530512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            long token = Binder.clearCallingIdentity();
531512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            try {
532512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                synchronized (mLock) {
533512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    logIncoming("setCallerDisplayName %s %s %d", callId, callerDisplayName,
534512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            presentation);
535512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    if (mCallIdMapper.isValidCallId(callId)) {
536512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        Call call = mCallIdMapper.getCall(callId);
537512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        if (call != null) {
538512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            call.setCallerDisplayName(callerDisplayName, presentation);
539512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        }
5408d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                    }
5418d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                }
542512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            } finally {
543512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                Binder.restoreCallingIdentity(token);
544969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner            }
545e8ecb98d5341395e073d02c065143ae3ac76ef71Sailesh Nepal        }
5469d58de5df05d0358fc8ae57ab7e9a0c45337c602Sailesh Nepal
5479d58de5df05d0358fc8ae57ab7e9a0c45337c602Sailesh Nepal        @Override
54812d61825cd0d6aa06272db3f77b5e30dce379951Santos Cordon        public void setConferenceableConnections(
54912d61825cd0d6aa06272db3f77b5e30dce379951Santos Cordon                String callId, List<String> conferenceableCallIds) {
550512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            long token = Binder.clearCallingIdentity();
551512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            try {
552512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                synchronized (mLock) {
553512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    logIncoming("setConferenceableConnections %s %s", callId,
554512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            conferenceableCallIds);
555512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    if (mCallIdMapper.isValidCallId(callId) ||
556512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            mCallIdMapper.isValidConferenceId(callId)) {
557512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        Call call = mCallIdMapper.getCall(callId);
558512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                        if (call != null) {
559512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            List<Call> conferenceableCalls =
560512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                                    new ArrayList<>(conferenceableCallIds.size());
561512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            for (String otherId : conferenceableCallIds) {
562512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                                Call otherCall = mCallIdMapper.getCall(otherId);
563512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                                if (otherCall != null && otherCall != call) {
564512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                                    conferenceableCalls.add(otherCall);
565512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                                }
5668d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                            }
567512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            call.setConferenceableCalls(conferenceableCalls);
5688d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                        }
5698d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                    }
5708d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad                }
571512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            } finally {
572512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                Binder.restoreCallingIdentity(token);
573969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner            }
57412d61825cd0d6aa06272db3f77b5e30dce379951Santos Cordon        }
5756e2b94eae72c72b11358fdb99f87471b5ab11e4fTyler Gunn
5766e2b94eae72c72b11358fdb99f87471b5ab11e4fTyler Gunn        @Override
5776e2b94eae72c72b11358fdb99f87471b5ab11e4fTyler Gunn        public void addExistingConnection(String callId, ParcelableConnection connection) {
578512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            long token = Binder.clearCallingIdentity();
579512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            try {
580512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                synchronized (mLock) {
581512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    logIncoming("addExistingConnection  %s %s", callId, connection);
582512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    Call existingCall = mCallsManager
583512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                            .createCallForExistingConnection(callId, connection);
584512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    mCallIdMapper.addCall(existingCall, callId);
585512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                    existingCall.setConnectionService(ConnectionServiceWrapper.this);
586512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                }
587512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad            } finally {
588512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad                Binder.restoreCallingIdentity(token);
5898d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad            }
5906e2b94eae72c72b11358fdb99f87471b5ab11e4fTyler Gunn        }
5913d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon    }
5923d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon
5933d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon    private final Adapter mAdapter = new Adapter();
594c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal    private final CallIdMapper mCallIdMapper = new CallIdMapper("ConnectionService");
595664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    private final Map<String, CreateConnectionResponse> mPendingResponses = new HashMap<>();
596c195e3613af47a49e76821d3f24c05adb71cf920Santos Cordon
597512d6350a66b44f1065d6fd2e14ec328449e8119Ihab Awad    private Binder2 mBinder = new Binder2();
598c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal    private IConnectionService mServiceInterface;
599905dfba7883666f45a0c6958d8bc6c19d68972d9Sailesh Nepal    private final ConnectionServiceRepository mConnectionServiceRepository;
60091d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn    private final PhoneAccountRegistrar mPhoneAccountRegistrar;
6018de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad    private final CallsManager mCallsManager;
6026192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad
60363aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordon    /**
604905dfba7883666f45a0c6958d8bc6c19d68972d9Sailesh Nepal     * Creates a connection service.
605c195e3613af47a49e76821d3f24c05adb71cf920Santos Cordon     *
606905dfba7883666f45a0c6958d8bc6c19d68972d9Sailesh Nepal     * @param componentName The component name of the service with which to bind.
607905dfba7883666f45a0c6958d8bc6c19d68972d9Sailesh Nepal     * @param connectionServiceRepository Connection service repository.
608b78b27693afbe9736f0a54ec473328955251f885Ihab Awad     * @param phoneAccountRegistrar Phone account registrar
6098de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad     * @param callsManager Calls manager
61091d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn     * @param context The context.
611105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton     * @param userHandle The {@link UserHandle} to use when binding.
61263aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordon     */
613c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal    ConnectionServiceWrapper(
614b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            ComponentName componentName,
615b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            ConnectionServiceRepository connectionServiceRepository,
61691d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn            PhoneAccountRegistrar phoneAccountRegistrar,
6178de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad            CallsManager callsManager,
618105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton            Context context,
6198d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad            TelecomSystem.SyncRoot lock,
620105d977687d1d0de7cd9420fc140b01404261df1Evan Charlton            UserHandle userHandle) {
6218d5d9ddc66b55b6906364ab3c0e244dab4d58f13Ihab Awad        super(ConnectionService.SERVICE_INTERFACE, componentName, context, lock, userHandle);
622905dfba7883666f45a0c6958d8bc6c19d68972d9Sailesh Nepal        mConnectionServiceRepository = connectionServiceRepository;
623b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        phoneAccountRegistrar.addListener(new PhoneAccountRegistrar.Listener() {
624b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            // TODO -- Upon changes to PhoneAccountRegistrar, need to re-wire connections
625b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            // To do this, we must proxy remote ConnectionService objects
626b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        });
62791d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn        mPhoneAccountRegistrar = phoneAccountRegistrar;
6288de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad        mCallsManager = callsManager;
629c195e3613af47a49e76821d3f24c05adb71cf920Santos Cordon    }
630c195e3613af47a49e76821d3f24c05adb71cf920Santos Cordon
631c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal    /** See {@link IConnectionService#addConnectionServiceAdapter}. */
632c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal    private void addConnectionServiceAdapter(IConnectionServiceAdapter adapter) {
633c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        if (isServiceValid("addConnectionServiceAdapter")) {
63461d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon            try {
6353fe8b727b04cb677bc757f030c802cd4e6234db7Sailesh Nepal                logOutgoing("addConnectionServiceAdapter %s", adapter);
636c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal                mServiceInterface.addConnectionServiceAdapter(adapter);
63761d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon            } catch (RemoteException e) {
63863aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordon            }
63963aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordon        }
64063aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordon    }
64163aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordon
6426192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad    /**
643664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal     * Creates a new connection for a new outgoing call or to attach to an existing incoming call.
6446192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad     */
645664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal    void createConnection(final Call call, final CreateConnectionResponse response) {
646664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        Log.d(this, "createConnection(%s) via %s.", call, getComponentName());
6476192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad        BindCallback callback = new BindCallback() {
6483d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon            @Override
6493d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon            public void onSuccess() {
650682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon                String callId = mCallIdMapper.getCallId(call);
651664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal                mPendingResponses.put(callId, response);
652682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon
653c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal                GatewayInfo gatewayInfo = call.getGatewayInfo();
654b3907b3e79864a3a42d5e7105e5051f7e364fdbaSantos Cordon                Bundle extras = call.getIntentExtras();
655c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal                if (gatewayInfo != null && gatewayInfo.getGatewayProviderPackageName() != null &&
656201b437535ebd07a3d8bf771920a4cb72d145ff3Nancy Chen                        gatewayInfo.getOriginalAddress() != null) {
657c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal                    extras = (Bundle) extras.clone();
658c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal                    extras.putString(
6597cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunn                            TelecomManager.GATEWAY_PROVIDER_PACKAGE,
660c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal                            gatewayInfo.getGatewayProviderPackageName());
661c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal                    extras.putParcelable(
6627cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunn                            TelecomManager.GATEWAY_ORIGINAL_ADDRESS,
663201b437535ebd07a3d8bf771920a4cb72d145ff3Nancy Chen                            gatewayInfo.getOriginalAddress());
664c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal                }
665c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal
666165c1ced107a1c3b9b359757d41438f9ca585e78Santos Cordon                Log.event(call, Log.Events.START_CONNECTION, Log.piiHandle(call.getHandle()));
667682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon                try {
668b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                    mServiceInterface.createConnection(
669b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                            call.getConnectionManagerPhoneAccount(),
6706fb37c87836b5245046bd3b14320823ab839a10cIhab Awad                            callId,
671b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                            new ConnectionRequest(
672b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                                    call.getTargetPhoneAccount(),
673b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                                    call.getHandle(),
674b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                                    extras,
675b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                                    call.getVideoState()),
6769250e5fa9987c3ab80e11e1955657055f5866539Yorke Lee                            call.isIncoming(),
6779250e5fa9987c3ab80e11e1955657055f5866539Yorke Lee                            call.isUnknown());
678682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon                } catch (RemoteException e) {
679664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal                    Log.e(this, e, "Failure to createConnection -- %s", getComponentName());
680fb5560d634aef745466e8869f8acf496447da17bIhab Awad                    mPendingResponses.remove(callId).handleCreateConnectionFailure(
681701dc006ac11625b55d872f1639107b028933895Andrew Lee                            new DisconnectCause(DisconnectCause.ERROR, e.toString()));
6826192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad                }
68363aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordon            }
6843d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon
6853d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon            @Override
6863d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon            public void onFailure() {
687905dfba7883666f45a0c6958d8bc6c19d68972d9Sailesh Nepal                Log.e(this, new Exception(), "Failure to call %s", getComponentName());
688701dc006ac11625b55d872f1639107b028933895Andrew Lee                response.handleCreateConnectionFailure(new DisconnectCause(DisconnectCause.ERROR));
6896192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad            }
6906192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad        };
6916192561b1f56d7c4e6c650e178e07ba61ad02667Ben Gilad
692165c1ced107a1c3b9b359757d41438f9ca585e78Santos Cordon        mBinder.bind(callback, call);
69363aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordon    }
69463aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordon
6958de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad    /** @see IConnectionService#abort(String) */
696e59bb195972d65a71618af4fe13f1ad982253e16Sailesh Nepal    void abort(Call call) {
697682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon        // Clear out any pending outgoing call data
698969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner        final String callId = mCallIdMapper.getCallId(call);
699682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon
700c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        // If still bound, tell the connection service to abort.
701969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner        if (callId != null && isServiceValid("abort")) {
70228e8ad601cbef0abab1cd6aec8c5a3bc881839c2Ben Gilad            try {
70355a3428c6b62e5a84d21f890418cfa9a8494780eIhab Awad                logOutgoing("abort %s", callId);
704682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon                mServiceInterface.abort(callId);
70528e8ad601cbef0abab1cd6aec8c5a3bc881839c2Ben Gilad            } catch (RemoteException e) {
70661d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon            }
70761d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon        }
708682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon
709701dc006ac11625b55d872f1639107b028933895Andrew Lee        removeCall(call, new DisconnectCause(DisconnectCause.LOCAL));
71061d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    }
71161d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
7128de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad    /** @see IConnectionService#hold(String) */
713e59bb195972d65a71618af4fe13f1ad982253e16Sailesh Nepal    void hold(Call call) {
714969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner        final String callId = mCallIdMapper.getCallId(call);
715969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner        if (callId != null && isServiceValid("hold")) {
716cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee            try {
717969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner                logOutgoing("hold %s", callId);
718969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner                mServiceInterface.hold(callId);
719cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee            } catch (RemoteException e) {
720cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee            }
721cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee        }
722cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee    }
723cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee
7248de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad    /** @see IConnectionService#unhold(String) */
725e59bb195972d65a71618af4fe13f1ad982253e16Sailesh Nepal    void unhold(Call call) {
726969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner        final String callId = mCallIdMapper.getCallId(call);
727969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner        if (callId != null && isServiceValid("unhold")) {
728cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee            try {
729969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner                logOutgoing("unhold %s", callId);
730969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner                mServiceInterface.unhold(callId);
731cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee            } catch (RemoteException e) {
732cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee            }
733cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee        }
734cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee    }
735cdf3ebd3ea6505668304b7e0a39df354ebbb52fbYorke Lee
7362a66f7b906b225413ae33f72e70a75e4f9c883c0Yorke Lee    /** @see IConnectionService#onCallAudioStateChanged(String,CallAudioState) */
7372a66f7b906b225413ae33f72e70a75e4f9c883c0Yorke Lee    void onCallAudioStateChanged(Call activeCall, CallAudioState audioState) {
738969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner        final String callId = mCallIdMapper.getCallId(activeCall);
7392a66f7b906b225413ae33f72e70a75e4f9c883c0Yorke Lee        if (callId != null && isServiceValid("onCallAudioStateChanged")) {
7406aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal            try {
7412a66f7b906b225413ae33f72e70a75e4f9c883c0Yorke Lee                logOutgoing("onCallAudioStateChanged %s %s", callId, audioState);
7422a66f7b906b225413ae33f72e70a75e4f9c883c0Yorke Lee                mServiceInterface.onCallAudioStateChanged(callId, audioState);
7436aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal            } catch (RemoteException e) {
7446aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal            }
7456aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal        }
7466aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal    }
7476aca10a0efa2771ccdef5920f4276f0db4a7ee1fSailesh Nepal
7488de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad    /** @see IConnectionService#disconnect(String) */
749e59bb195972d65a71618af4fe13f1ad982253e16Sailesh Nepal    void disconnect(Call call) {
750969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner        final String callId = mCallIdMapper.getCallId(call);
751969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner        if (callId != null && isServiceValid("disconnect")) {
75261d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon            try {
753969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner                logOutgoing("disconnect %s", callId);
754969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner                mServiceInterface.disconnect(callId);
75561d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon            } catch (RemoteException e) {
75661d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon            }
75761d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon        }
75861d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon    }
75961d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon
7608de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad    /** @see IConnectionService#answer(String) */
76138931d0ad60f00a9f50c90cef446166731f0b871Andrew Lee    void answer(Call call, int videoState) {
762969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner        final String callId = mCallIdMapper.getCallId(call);
763969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner        if (callId != null && isServiceValid("answer")) {
76461d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon            try {
765969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner                logOutgoing("answer %s %d", callId, videoState);
766467b64fb79f8720958bba6dff84d4827458d33e2Tyler Gunn                if (VideoProfile.isAudioOnly(videoState)) {
767041eff6b45ff885e77d2e1b8b9ca9099dd0885d2Tyler Gunn                    mServiceInterface.answer(callId);
768041eff6b45ff885e77d2e1b8b9ca9099dd0885d2Tyler Gunn                } else {
769041eff6b45ff885e77d2e1b8b9ca9099dd0885d2Tyler Gunn                    mServiceInterface.answerVideo(callId, videoState);
770041eff6b45ff885e77d2e1b8b9ca9099dd0885d2Tyler Gunn                }
77161d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon            } catch (RemoteException e) {
77263aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordon            }
77363aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordon        }
77463aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordon    }
7755c12c6e00101d16d2db776839a027c62c109dea8Santos Cordon
7768de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad    /** @see IConnectionService#reject(String) */
777e59bb195972d65a71618af4fe13f1ad982253e16Sailesh Nepal    void reject(Call call) {
778969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner        final String callId = mCallIdMapper.getCallId(call);
779969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner        if (callId != null && isServiceValid("reject")) {
78061d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon            try {
781969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner                logOutgoing("reject %s", callId);
782969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner                mServiceInterface.reject(callId);
78361d0f70cf45036f9cdeb41b96538f792b7c9764bSantos Cordon            } catch (RemoteException e) {
78474549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad            }
78574549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad        }
78674549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad    }
78774549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad
7888de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad    /** @see IConnectionService#playDtmfTone(String,char) */
789e59bb195972d65a71618af4fe13f1ad982253e16Sailesh Nepal    void playDtmfTone(Call call, char digit) {
790969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner        final String callId = mCallIdMapper.getCallId(call);
791969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner        if (callId != null && isServiceValid("playDtmfTone")) {
79274549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad            try {
793969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner                logOutgoing("playDtmfTone %s %c", callId, digit);
794969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner                mServiceInterface.playDtmfTone(callId, digit);
79574549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad            } catch (RemoteException e) {
79674549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad            }
79774549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad        }
79874549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad    }
79974549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad
8008de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad    /** @see IConnectionService#stopDtmfTone(String) */
801e59bb195972d65a71618af4fe13f1ad982253e16Sailesh Nepal    void stopDtmfTone(Call call) {
802969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner        final String callId = mCallIdMapper.getCallId(call);
803969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner        if (callId != null && isServiceValid("stopDtmfTone")) {
80474549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad            try {
805969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner                logOutgoing("stopDtmfTone %s",callId);
806969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner                mServiceInterface.stopDtmfTone(callId);
80774549ec95acf0d2ddbe4feca91c6febdf8008074Ihab Awad            } catch (RemoteException e) {
8087917d38176b6cc432314433d36d7bb46a09f5afcSantos Cordon            }
8097917d38176b6cc432314433d36d7bb46a09f5afcSantos Cordon        }
8107917d38176b6cc432314433d36d7bb46a09f5afcSantos Cordon    }
8117917d38176b6cc432314433d36d7bb46a09f5afcSantos Cordon
812e59bb195972d65a71618af4fe13f1ad982253e16Sailesh Nepal    void addCall(Call call) {
813a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        if (mCallIdMapper.getCallId(call) == null) {
814a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            mCallIdMapper.addCall(call);
815a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        }
8167917d38176b6cc432314433d36d7bb46a09f5afcSantos Cordon    }
8177917d38176b6cc432314433d36d7bb46a09f5afcSantos Cordon
8180e5410a58043ce059884fdc8811a280655e5a920Sailesh Nepal    /**
819c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal     * Associates newCall with this connection service by replacing callToReplace.
8200e5410a58043ce059884fdc8811a280655e5a920Sailesh Nepal     */
8210e5410a58043ce059884fdc8811a280655e5a920Sailesh Nepal    void replaceCall(Call newCall, Call callToReplace) {
822c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal        Preconditions.checkState(callToReplace.getConnectionService() == this);
8230e5410a58043ce059884fdc8811a280655e5a920Sailesh Nepal        mCallIdMapper.replaceCall(newCall, callToReplace);
8240e5410a58043ce059884fdc8811a280655e5a920Sailesh Nepal    }
8250e5410a58043ce059884fdc8811a280655e5a920Sailesh Nepal
826e59bb195972d65a71618af4fe13f1ad982253e16Sailesh Nepal    void removeCall(Call call) {
827701dc006ac11625b55d872f1639107b028933895Andrew Lee        removeCall(call, new DisconnectCause(DisconnectCause.ERROR));
828fd6ca447a45c47aeb3956964103770475c655a26Santos Cordon    }
829fd6ca447a45c47aeb3956964103770475c655a26Santos Cordon
830701dc006ac11625b55d872f1639107b028933895Andrew Lee    void removeCall(String callId, DisconnectCause disconnectCause) {
831fb5560d634aef745466e8869f8acf496447da17bIhab Awad        CreateConnectionResponse response = mPendingResponses.remove(callId);
832fb5560d634aef745466e8869f8acf496447da17bIhab Awad        if (response != null) {
833701dc006ac11625b55d872f1639107b028933895Andrew Lee            response.handleCreateConnectionFailure(disconnectCause);
834fb5560d634aef745466e8869f8acf496447da17bIhab Awad        }
835fb5560d634aef745466e8869f8acf496447da17bIhab Awad
836fb5560d634aef745466e8869f8acf496447da17bIhab Awad        mCallIdMapper.removeCall(callId);
837fb5560d634aef745466e8869f8acf496447da17bIhab Awad    }
838fb5560d634aef745466e8869f8acf496447da17bIhab Awad
839701dc006ac11625b55d872f1639107b028933895Andrew Lee    void removeCall(Call call, DisconnectCause disconnectCause) {
840664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        CreateConnectionResponse response = mPendingResponses.remove(mCallIdMapper.getCallId(call));
841664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        if (response != null) {
842701dc006ac11625b55d872f1639107b028933895Andrew Lee            response.handleCreateConnectionFailure(disconnectCause);
843682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon        }
844682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon
845e59bb195972d65a71618af4fe13f1ad982253e16Sailesh Nepal        mCallIdMapper.removeCall(call);
846adee12dd6b3e85ce3ae419329226c9aa72c184fcYorke Lee    }
847adee12dd6b3e85ce3ae419329226c9aa72c184fcYorke Lee
848352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton    void onPostDialContinue(Call call, boolean proceed) {
849969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner        final String callId = mCallIdMapper.getCallId(call);
850969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner        if (callId != null && isServiceValid("onPostDialContinue")) {
851352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton            try {
852969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner                logOutgoing("onPostDialContinue %s %b", callId, proceed);
853969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner                mServiceInterface.onPostDialContinue(callId, proceed);
854352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton            } catch (RemoteException ignored) {
855352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton            }
856352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton        }
857352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton    }
858352105c5d33ac94e5ad0cb5ac2e9268731423e65Evan Charlton
8590fbe6321e341ddce186634266dba2db3fa426b88Santos Cordon    void conference(final Call call, Call otherCall) {
860969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner        final String callId = mCallIdMapper.getCallId(call);
8610fbe6321e341ddce186634266dba2db3fa426b88Santos Cordon        final String otherCallId = mCallIdMapper.getCallId(otherCall);
8620fbe6321e341ddce186634266dba2db3fa426b88Santos Cordon        if (callId != null && otherCallId != null && isServiceValid("conference")) {
863a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            try {
8640fbe6321e341ddce186634266dba2db3fa426b88Santos Cordon                logOutgoing("conference %s %s", callId, otherCallId);
8650fbe6321e341ddce186634266dba2db3fa426b88Santos Cordon                mServiceInterface.conference(callId, otherCallId);
866a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            } catch (RemoteException ignored) {
867a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            }
868a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        }
869a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    }
870a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
871a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    void splitFromConference(Call call) {
872969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner        final String callId = mCallIdMapper.getCallId(call);
873969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner        if (callId != null && isServiceValid("splitFromConference")) {
874a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            try {
875969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner                logOutgoing("splitFromConference %s", callId);
876969755a2a7ff9416f677dd87d520fce27e629dffJay Shrauner                mServiceInterface.splitFromConference(callId);
877a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            } catch (RemoteException ignored) {
878a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon            }
879a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        }
880a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    }
881a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon
8826805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon    void mergeConference(Call call) {
8836805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon        final String callId = mCallIdMapper.getCallId(call);
8846805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon        if (callId != null && isServiceValid("mergeConference")) {
8856805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon            try {
8866805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon                logOutgoing("mergeConference %s", callId);
8876805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon                mServiceInterface.mergeConference(callId);
8886805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon            } catch (RemoteException ignored) {
8896805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon            }
8906805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon        }
8916805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon    }
8926805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon
8936805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon    void swapConference(Call call) {
8946805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon        final String callId = mCallIdMapper.getCallId(call);
8956805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon        if (callId != null && isServiceValid("swapConference")) {
8966805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon            try {
8976805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon                logOutgoing("swapConference %s", callId);
8986805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon                mServiceInterface.swapConference(callId);
8996805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon            } catch (RemoteException ignored) {
9006805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon            }
9016805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon        }
9026805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon    }
9036805923a2d91f9e193a4dd33f7a655587d2f173cSantos Cordon
9045c12c6e00101d16d2db776839a027c62c109dea8Santos Cordon    /** {@inheritDoc} */
9053d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon    @Override
9063d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon    protected void setServiceInterface(IBinder binder) {
9074b2c119562bf29b05c7dc139c77f5893d3d70d2cSantos Cordon        if (binder == null) {
908c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            // We have lost our service connection. Notify the world that this service is done.
9094b2c119562bf29b05c7dc139c77f5893d3d70d2cSantos Cordon            // We must notify the adapter before CallsManager. The adapter will force any pending
910c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            // outgoing calls to try the next service. This needs to happen before CallsManager
911c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            // tries to clean up any calls still associated with this service.
912c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            handleConnectionServiceDeath();
9138de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad            mCallsManager.handleConnectionServiceDeath(this);
9144b2c119562bf29b05c7dc139c77f5893d3d70d2cSantos Cordon            mServiceInterface = null;
9154b2c119562bf29b05c7dc139c77f5893d3d70d2cSantos Cordon        } else {
916c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            mServiceInterface = IConnectionService.Stub.asInterface(binder);
917c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal            addConnectionServiceAdapter(mAdapter);
9184b2c119562bf29b05c7dc139c77f5893d3d70d2cSantos Cordon        }
9195c12c6e00101d16d2db776839a027c62c109dea8Santos Cordon    }
9203d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon
921fb5560d634aef745466e8869f8acf496447da17bIhab Awad    private void handleCreateConnectionComplete(
922fb5560d634aef745466e8869f8acf496447da17bIhab Awad            String callId,
923fb5560d634aef745466e8869f8acf496447da17bIhab Awad            ConnectionRequest request,
924fb5560d634aef745466e8869f8acf496447da17bIhab Awad            ParcelableConnection connection) {
925fb5560d634aef745466e8869f8acf496447da17bIhab Awad        // TODO: Note we are not using parameter "request", which is a side effect of our tacit
926fb5560d634aef745466e8869f8acf496447da17bIhab Awad        // assumption that we have at most one outgoing connection attempt per ConnectionService.
927fb5560d634aef745466e8869f8acf496447da17bIhab Awad        // This may not continue to be the case.
928fb5560d634aef745466e8869f8acf496447da17bIhab Awad        if (connection.getState() == Connection.STATE_DISCONNECTED) {
929fb5560d634aef745466e8869f8acf496447da17bIhab Awad            // A connection that begins in the DISCONNECTED state is an indication of
930fb5560d634aef745466e8869f8acf496447da17bIhab Awad            // failure to connect; we handle all failures uniformly
931701dc006ac11625b55d872f1639107b028933895Andrew Lee            removeCall(callId, connection.getDisconnectCause());
932fb5560d634aef745466e8869f8acf496447da17bIhab Awad        } else {
933fb5560d634aef745466e8869f8acf496447da17bIhab Awad            // Successful connection
934fb5560d634aef745466e8869f8acf496447da17bIhab Awad            if (mPendingResponses.containsKey(callId)) {
9358000845a81fd6a88ff69cb11e1b6dff5f47c2332Ihab Awad                mPendingResponses.remove(callId)
9368000845a81fd6a88ff69cb11e1b6dff5f47c2332Ihab Awad                        .handleCreateConnectionSuccess(mCallIdMapper, connection);
937fb5560d634aef745466e8869f8acf496447da17bIhab Awad            }
938fb5560d634aef745466e8869f8acf496447da17bIhab Awad        }
939fb5560d634aef745466e8869f8acf496447da17bIhab Awad    }
940fb5560d634aef745466e8869f8acf496447da17bIhab Awad
9413d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon    /**
942c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal     * Called when the associated connection service dies.
9433d3b4059d7b1fc5a03c4b049b1d436f28ecf84ecSantos Cordon     */
944c92c436d84de46bb85100df9138378d9ffe0f2f2Sailesh Nepal    private void handleConnectionServiceDeath() {
945664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal        if (!mPendingResponses.isEmpty()) {
946664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            CreateConnectionResponse[] responses = mPendingResponses.values().toArray(
947664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal                    new CreateConnectionResponse[mPendingResponses.values().size()]);
948664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            mPendingResponses.clear();
949664837f9a8a98f98876417a0bfff64834e8032faSailesh Nepal            for (int i = 0; i < responses.length; i++) {
950701dc006ac11625b55d872f1639107b028933895Andrew Lee                responses[i].handleCreateConnectionFailure(
951701dc006ac11625b55d872f1639107b028933895Andrew Lee                        new DisconnectCause(DisconnectCause.ERROR));
952682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon            }
953682fe6ba2fe99e209d72a051539697a755b994c0Santos Cordon        }
954a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon        mCallIdMapper.clear();
955a161070ea054f91a5b2d5b4e3413381134d548b8Santos Cordon    }
95655a3428c6b62e5a84d21f890418cfa9a8494780eIhab Awad
95755a3428c6b62e5a84d21f890418cfa9a8494780eIhab Awad    private void logIncoming(String msg, Object... params) {
9587cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunn        Log.d(this, "ConnectionService -> Telecom: " + msg, params);
95955a3428c6b62e5a84d21f890418cfa9a8494780eIhab Awad    }
96055a3428c6b62e5a84d21f890418cfa9a8494780eIhab Awad
96155a3428c6b62e5a84d21f890418cfa9a8494780eIhab Awad    private void logOutgoing(String msg, Object... params) {
9627cc70b4f0ad1064a4a0dce6056ad82b205887160Tyler Gunn        Log.d(this, "Telecom -> ConnectionService: " + msg, params);
96355a3428c6b62e5a84d21f890418cfa9a8494780eIhab Awad    }
9645924beafe09bf3fb710ec1bafd59113a12b45adaSantos Cordon
9655924beafe09bf3fb710ec1bafd59113a12b45adaSantos Cordon    private void queryRemoteConnectionServices(final RemoteServiceCallback callback) {
966b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        // Only give remote connection services to this connection service if it is listed as
967b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        // the connection manager.
96891d43cf9c985cc5a83795f256ef5c46ebb8fbdc1Tyler Gunn        PhoneAccountHandle simCallManager = mPhoneAccountRegistrar.getSimCallManager();
969c17294cfaf9cc649a362117fba544f0b5cb18cdfIhab Awad        Log.d(this, "queryRemoteConnectionServices finds simCallManager = %s", simCallManager);
970b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        if (simCallManager == null ||
971b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                !simCallManager.getComponentName().equals(getComponentName())) {
972b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            noRemoteServices(callback);
973b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            return;
974b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        }
975b78b27693afbe9736f0a54ec473328955251f885Ihab Awad
976b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        // Make a list of ConnectionServices that are listed as being associated with SIM accounts
977a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shrauner        final Set<ConnectionServiceWrapper> simServices = Collections.newSetFromMap(
978a82c8f794a0a1a9eaa1329a6361abe28043d139aJay Shrauner                new ConcurrentHashMap<ConnectionServiceWrapper, Boolean>(8, 0.9f, 1));
9796a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon        for (PhoneAccountHandle handle : mPhoneAccountRegistrar.getSimPhoneAccounts()) {
9806a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon            ConnectionServiceWrapper service = mConnectionServiceRepository.getService(
9816a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon                    handle.getComponentName(), handle.getUserHandle());
9826a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon            if (service != null) {
9836a2126477ce3f527ecaec807fe4f40cd13ff02b0Santos Cordon                simServices.add(service);
984b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            }
985b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        }
9865924beafe09bf3fb710ec1bafd59113a12b45adaSantos Cordon
987b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        final List<ComponentName> simServiceComponentNames = new ArrayList<>();
988b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        final List<IBinder> simServiceBinders = new ArrayList<>();
9895924beafe09bf3fb710ec1bafd59113a12b45adaSantos Cordon
990b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        Log.v(this, "queryRemoteConnectionServices, simServices = %s", simServices);
991b78b27693afbe9736f0a54ec473328955251f885Ihab Awad
992b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        for (ConnectionServiceWrapper simService : simServices) {
993b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            if (simService == this) {
994b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                // Only happens in the unlikely case that a SIM service is also a SIM call manager
995b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                continue;
9965924beafe09bf3fb710ec1bafd59113a12b45adaSantos Cordon            }
997b78b27693afbe9736f0a54ec473328955251f885Ihab Awad
998b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            final ConnectionServiceWrapper currentSimService = simService;
999b78b27693afbe9736f0a54ec473328955251f885Ihab Awad
1000b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            currentSimService.mBinder.bind(new BindCallback() {
1001b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                @Override
1002b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                public void onSuccess() {
1003b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                    Log.d(this, "Adding simService %s", currentSimService.getComponentName());
1004b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                    simServiceComponentNames.add(currentSimService.getComponentName());
1005b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                    simServiceBinders.add(currentSimService.mServiceInterface.asBinder());
1006b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                    maybeComplete();
1007b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                }
1008b78b27693afbe9736f0a54ec473328955251f885Ihab Awad
1009b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                @Override
1010b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                public void onFailure() {
1011b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                    Log.d(this, "Failed simService %s", currentSimService.getComponentName());
1012b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                    // We know maybeComplete() will always be a no-op from now on, so go ahead and
1013b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                    // signal failure of the entire request
1014b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                    noRemoteServices(callback);
1015b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                }
1016b78b27693afbe9736f0a54ec473328955251f885Ihab Awad
1017b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                private void maybeComplete() {
1018b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                    if (simServiceComponentNames.size() == simServices.size()) {
1019b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                        setRemoteServices(callback, simServiceComponentNames, simServiceBinders);
1020b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                    }
1021b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                }
1022165c1ced107a1c3b9b359757d41438f9ca585e78Santos Cordon            }, null);
1023b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        }
1024b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    }
1025b78b27693afbe9736f0a54ec473328955251f885Ihab Awad
1026b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    private void setRemoteServices(
1027b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            RemoteServiceCallback callback,
1028b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            List<ComponentName> componentNames,
1029b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            List<IBinder> binders) {
1030b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        try {
1031b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            callback.onResult(componentNames, binders);
1032b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        } catch (RemoteException e) {
1033b78b27693afbe9736f0a54ec473328955251f885Ihab Awad            Log.e(this, e, "Contacting ConnectionService %s",
1034b78b27693afbe9736f0a54ec473328955251f885Ihab Awad                    ConnectionServiceWrapper.this.getComponentName());
1035b78b27693afbe9736f0a54ec473328955251f885Ihab Awad        }
1036b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    }
1037b78b27693afbe9736f0a54ec473328955251f885Ihab Awad
1038b78b27693afbe9736f0a54ec473328955251f885Ihab Awad    private void noRemoteServices(RemoteServiceCallback callback) {
10398de76915ea2772faeb41705aaaeb65f5b3478ac4Ihab Awad        setRemoteServices(callback, Collections.EMPTY_LIST, Collections.EMPTY_LIST);
10405924beafe09bf3fb710ec1bafd59113a12b45adaSantos Cordon    }
104163aeb16a14a94dd44345f6200c7c002e780a15ffSantos Cordon}
1042