blob: 782f7a47db735778c8aa295c8e35396449019ccd [file] [log] [blame]
Santos Cordon63aeb162014-02-10 09:20:40 -08001/*
2 * Copyright 2014, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.telecomm;
18
Santos Cordon5924bea2014-06-18 06:39:51 -070019import android.content.ComponentName;
Evan Charltona05805b2014-03-05 08:21:46 -080020import android.os.Bundle;
Santos Cordon3d3b4052014-05-05 12:05:36 -070021import android.os.Handler;
Santos Cordon63aeb162014-02-10 09:20:40 -080022import android.os.IBinder;
Santos Cordon3d3b4052014-05-05 12:05:36 -070023import android.os.Message;
Santos Cordon63aeb162014-02-10 09:20:40 -080024import android.os.RemoteException;
Sailesh Nepal6aca10a2014-03-24 16:11:02 -070025import android.telecomm.CallAudioState;
Santos Cordon63aeb162014-02-10 09:20:40 -080026import android.telecomm.CallInfo;
Evan Charltona05805b2014-03-05 08:21:46 -080027import android.telecomm.CallService;
Ben Giladc5b22692014-02-18 20:03:22 -080028import android.telecomm.CallServiceDescriptor;
Ihab Awada3cb9e32014-06-03 18:45:05 -070029import android.telecomm.ConnectionRequest;
Sailesh Nepal83cfe7c2014-03-11 19:54:22 -070030import android.telecomm.TelecommConstants;
Ihab Awada3cb9e32014-06-03 18:45:05 -070031import android.telephony.DisconnectCause;
Sailesh Nepala439e1b2014-03-11 18:19:58 -070032
Santos Cordon3d3b4052014-05-05 12:05:36 -070033import com.android.internal.os.SomeArgs;
Sailesh Nepala439e1b2014-03-11 18:19:58 -070034import com.android.internal.telecomm.ICallService;
35import com.android.internal.telecomm.ICallServiceAdapter;
36import com.android.internal.telecomm.ICallServiceProvider;
Santos Cordon5924bea2014-06-18 06:39:51 -070037import com.android.internal.telecomm.RemoteServiceCallback;
38import com.android.telecomm.BaseRepository.LookupCallback;
Sailesh Nepal0e5410a2014-04-04 01:20:58 -070039import com.google.common.base.Preconditions;
Santos Cordon3d3b4052014-05-05 12:05:36 -070040import com.google.common.collect.ImmutableList;
Santos Cordon3d3b4052014-05-05 12:05:36 -070041
Ihab Awada3cb9e32014-06-03 18:45:05 -070042import org.apache.http.conn.ClientConnectionRequest;
43
Santos Cordon5924bea2014-06-18 06:39:51 -070044import java.util.ArrayList;
45import java.util.Collection;
Santos Cordon682fe6b2014-05-20 08:56:39 -070046import java.util.HashMap;
Santos Cordona1610702014-06-04 20:22:56 -070047import java.util.HashSet;
Santos Cordon8f3282c2014-06-01 13:56:02 -070048import java.util.List;
Santos Cordon682fe6b2014-05-20 08:56:39 -070049import java.util.Map;
Santos Cordon3d3b4052014-05-05 12:05:36 -070050import java.util.Set;
Santos Cordon63aeb162014-02-10 09:20:40 -080051
52/**
53 * Wrapper for {@link ICallService}s, handles binding to {@link ICallService} and keeps track of
54 * when the object can safely be unbound. Other classes should not use {@link ICallService} directly
55 * and instead should use this class to invoke methods of {@link ICallService}.
Santos Cordon63aeb162014-02-10 09:20:40 -080056 */
Ben Gilad61925612014-03-11 19:06:36 -070057final class CallServiceWrapper extends ServiceBinder<ICallService> {
Santos Cordona1610702014-06-04 20:22:56 -070058 private static final String TAG = CallServiceWrapper.class.getSimpleName();
Santos Cordon63aeb162014-02-10 09:20:40 -080059
Santos Cordon3d3b4052014-05-05 12:05:36 -070060 private final class Adapter extends ICallServiceAdapter.Stub {
Santos Cordon3d3b4052014-05-05 12:05:36 -070061 private static final int MSG_NOTIFY_INCOMING_CALL = 1;
62 private static final int MSG_HANDLE_SUCCESSFUL_OUTGOING_CALL = 2;
63 private static final int MSG_HANDLE_FAILED_OUTGOING_CALL = 3;
Sailesh Nepal5a73b032014-06-25 15:53:21 -070064 private static final int MSG_CANCEL_OUTGOING_CALL = 4;
65 private static final int MSG_SET_ACTIVE = 5;
66 private static final int MSG_SET_RINGING = 6;
67 private static final int MSG_SET_DIALING = 7;
68 private static final int MSG_SET_DISCONNECTED = 8;
69 private static final int MSG_SET_ON_HOLD = 9;
70 private static final int MSG_SET_REQUESTING_RINGBACK = 10;
71 private static final int MSG_ON_POST_DIAL_WAIT = 11;
72 private static final int MSG_CAN_CONFERENCE = 12;
73 private static final int MSG_SET_IS_CONFERENCED = 13;
74 private static final int MSG_ADD_CONFERENCE_CALL = 14;
75 private static final int MSG_HANDOFF_CALL = 15;
76 private static final int MSG_QUERY_REMOTE_CALL_SERVICES = 16;
Santos Cordon3d3b4052014-05-05 12:05:36 -070077
78 private final Handler mHandler = new Handler() {
79 @Override
80 public void handleMessage(Message msg) {
81 Call call;
82 switch (msg.what) {
Santos Cordon3d3b4052014-05-05 12:05:36 -070083 case MSG_NOTIFY_INCOMING_CALL:
84 CallInfo clientCallInfo = (CallInfo) msg.obj;
85 call = mCallIdMapper.getCall(clientCallInfo.getId());
Santos Cordon682fe6b2014-05-20 08:56:39 -070086 if (call != null && mPendingIncomingCalls.remove(call) &&
87 call.isIncoming()) {
Santos Cordon3d3b4052014-05-05 12:05:36 -070088 CallInfo callInfo = new CallInfo(null, clientCallInfo.getState(),
89 clientCallInfo.getHandle());
90 mIncomingCallsManager.handleSuccessfulIncomingCall(call, callInfo);
91 } else {
Santos Cordon5924bea2014-06-18 06:39:51 -070092 // TODO(santoscordon): For this an the other commented logging, we need
93 // to reenable it. At the moment all CallServiceAdapters receive
94 // notification of changes to all calls, even calls which it may not own
95 // (ala remote connections). We need to fix that and then uncomment the
96 // logging calls here.
97 //Log.w(this, "notifyIncomingCall, unknown incoming call: %s, id: %s",
98 // call, clientCallInfo.getId());
Santos Cordon3d3b4052014-05-05 12:05:36 -070099 }
100 break;
Santos Cordon682fe6b2014-05-20 08:56:39 -0700101 case MSG_HANDLE_SUCCESSFUL_OUTGOING_CALL: {
102 String callId = (String) msg.obj;
103 if (mPendingOutgoingCalls.containsKey(callId)) {
Sailesh Nepal5a73b032014-06-25 15:53:21 -0700104 mPendingOutgoingCalls.remove(callId).onOutgoingCallSuccess();
Santos Cordon3d3b4052014-05-05 12:05:36 -0700105 } else {
Santos Cordon5924bea2014-06-18 06:39:51 -0700106 //Log.w(this, "handleSuccessfulOutgoingCall, unknown call: %s", callId);
Santos Cordon3d3b4052014-05-05 12:05:36 -0700107 }
108 break;
Santos Cordon682fe6b2014-05-20 08:56:39 -0700109 }
Santos Cordon3d3b4052014-05-05 12:05:36 -0700110 case MSG_HANDLE_FAILED_OUTGOING_CALL: {
111 SomeArgs args = (SomeArgs) msg.obj;
112 try {
Santos Cordon682fe6b2014-05-20 08:56:39 -0700113 String callId = (String) args.arg1;
Ihab Awada3cb9e32014-06-03 18:45:05 -0700114 int statusCode = args.argi1;
115 String statusMsg = (String) args.arg2;
Santos Cordon682fe6b2014-05-20 08:56:39 -0700116 // TODO(santoscordon): Do something with 'reason' or get rid of it.
117
118 if (mPendingOutgoingCalls.containsKey(callId)) {
Sailesh Nepal5a73b032014-06-25 15:53:21 -0700119 mPendingOutgoingCalls.remove(callId).onOutgoingCallFailure(
120 statusCode, statusMsg);
Santos Cordon682fe6b2014-05-20 08:56:39 -0700121 mCallIdMapper.removeCall(callId);
Santos Cordon3d3b4052014-05-05 12:05:36 -0700122 } else {
Santos Cordon5924bea2014-06-18 06:39:51 -0700123 //Log.w(this, "handleFailedOutgoingCall, unknown call: %s", callId);
Santos Cordon3d3b4052014-05-05 12:05:36 -0700124 }
125 } finally {
126 args.recycle();
127 }
128 break;
129 }
Sailesh Nepal5a73b032014-06-25 15:53:21 -0700130 case MSG_CANCEL_OUTGOING_CALL: {
131 String callId = (String) msg.obj;
132 if (mPendingOutgoingCalls.containsKey(callId)) {
133 mPendingOutgoingCalls.remove(callId).onOutgoingCallCancel();
134 } else {
135 //Log.w(this, "cancelOutgoingCall, unknown call: %s", callId);
136 }
137 break;
138 }
Santos Cordon3d3b4052014-05-05 12:05:36 -0700139 case MSG_SET_ACTIVE:
140 call = mCallIdMapper.getCall(msg.obj);
141 if (call != null) {
142 mCallsManager.markCallAsActive(call);
143 } else {
Santos Cordon5924bea2014-06-18 06:39:51 -0700144 //Log.w(this, "setActive, unknown call id: %s", msg.obj);
Santos Cordon3d3b4052014-05-05 12:05:36 -0700145 }
146 break;
147 case MSG_SET_RINGING:
148 call = mCallIdMapper.getCall(msg.obj);
149 if (call != null) {
150 mCallsManager.markCallAsRinging(call);
151 } else {
Santos Cordon5924bea2014-06-18 06:39:51 -0700152 //Log.w(this, "setRinging, unknown call id: %s", msg.obj);
Santos Cordon3d3b4052014-05-05 12:05:36 -0700153 }
154 break;
155 case MSG_SET_DIALING:
156 call = mCallIdMapper.getCall(msg.obj);
157 if (call != null) {
158 mCallsManager.markCallAsDialing(call);
159 } else {
Santos Cordon5924bea2014-06-18 06:39:51 -0700160 //Log.w(this, "setDialing, unknown call id: %s", msg.obj);
Santos Cordon3d3b4052014-05-05 12:05:36 -0700161 }
162 break;
163 case MSG_SET_DISCONNECTED: {
164 SomeArgs args = (SomeArgs) msg.obj;
165 try {
166 call = mCallIdMapper.getCall(args.arg1);
167 String disconnectMessage = (String) args.arg2;
168 int disconnectCause = args.argi1;
169 if (call != null) {
170 mCallsManager.markCallAsDisconnected(call, disconnectCause,
171 disconnectMessage);
172 } else {
Santos Cordon5924bea2014-06-18 06:39:51 -0700173 //Log.w(this, "setDisconnected, unknown call id: %s", args.arg1);
Santos Cordon3d3b4052014-05-05 12:05:36 -0700174 }
175 } finally {
176 args.recycle();
177 }
178 break;
179 }
180 case MSG_SET_ON_HOLD:
181 call = mCallIdMapper.getCall(msg.obj);
182 if (call != null) {
183 mCallsManager.markCallAsOnHold(call);
184 } else {
Santos Cordon5924bea2014-06-18 06:39:51 -0700185 //Log.w(this, "setOnHold, unknown call id: %s", msg.obj);
Santos Cordon3d3b4052014-05-05 12:05:36 -0700186 }
187 break;
Evan Charlton352105c2014-06-03 14:10:54 -0700188 case MSG_SET_REQUESTING_RINGBACK: {
Ihab Awad50a57132014-05-28 16:49:38 -0700189 SomeArgs args = (SomeArgs) msg.obj;
190 try {
191 call = mCallIdMapper.getCall(args.arg1);
192 boolean ringback = (boolean) args.arg2;
193 if (call != null) {
194 call.setRequestingRingback(ringback);
195 } else {
Santos Cordon5924bea2014-06-18 06:39:51 -0700196 //Log.w(this, "setRingback, unknown call id: %s", args.arg1);
Ihab Awad50a57132014-05-28 16:49:38 -0700197 }
198 } finally {
199 args.recycle();
200 }
201 break;
Evan Charlton352105c2014-06-03 14:10:54 -0700202 }
Santos Cordona1610702014-06-04 20:22:56 -0700203 case MSG_ON_POST_DIAL_WAIT: {
Evan Charlton352105c2014-06-03 14:10:54 -0700204 SomeArgs args = (SomeArgs) msg.obj;
205 try {
206 call = mCallIdMapper.getCall(args.arg1);
207 if (call != null) {
208 String remaining = (String) args.arg2;
209 call.onPostDialWait(remaining);
210 } else {
Santos Cordon5924bea2014-06-18 06:39:51 -0700211 //Log.w(this, "onPostDialWait, unknown call id: %s", args.arg1);
Evan Charlton352105c2014-06-03 14:10:54 -0700212 }
213 } finally {
214 args.recycle();
215 }
Santos Cordona1610702014-06-04 20:22:56 -0700216 break;
217 }
Sailesh Nepal6098d2c2014-06-06 10:56:53 -0700218 case MSG_HANDOFF_CALL:
219 call = mCallIdMapper.getCall(msg.obj);
220 if (call != null) {
221 mCallsManager.startHandoffForCall(call);
222 } else {
Santos Cordon5924bea2014-06-18 06:39:51 -0700223 //Log.w(this, "handoffCall, unknown call id: %s", msg.obj);
Sailesh Nepal6098d2c2014-06-06 10:56:53 -0700224 }
225 break;
Santos Cordona1610702014-06-04 20:22:56 -0700226 case MSG_CAN_CONFERENCE: {
227 call = mCallIdMapper.getCall(msg.obj);
228 if (call != null) {
229 call.setIsConferenceCapable(msg.arg1 == 1);
230 } else {
Santos Cordon5924bea2014-06-18 06:39:51 -0700231 //Log.w(CallServiceWrapper.this, "canConference, unknown call id: %s",
232 // msg.obj);
Santos Cordona1610702014-06-04 20:22:56 -0700233 }
234 break;
235 }
236 case MSG_SET_IS_CONFERENCED: {
237 SomeArgs args = (SomeArgs) msg.obj;
238 try {
239 Call childCall = mCallIdMapper.getCall(args.arg1);
240 if (childCall != null) {
241 String conferenceCallId = (String) args.arg2;
Santos Cordona1610702014-06-04 20:22:56 -0700242 if (conferenceCallId == null) {
243 childCall.setParentCall(null);
244 } else {
245 Call conferenceCall = mCallIdMapper.getCall(conferenceCallId);
246 if (conferenceCall != null &&
247 !mPendingConferenceCalls.contains(conferenceCall)) {
248 childCall.setParentCall(conferenceCall);
249 } else {
Santos Cordon5924bea2014-06-18 06:39:51 -0700250 //Log.w(this, "setIsConferenced, unknown conference id %s",
251 // conferenceCallId);
Santos Cordona1610702014-06-04 20:22:56 -0700252 }
253 }
254 } else {
Santos Cordon5924bea2014-06-18 06:39:51 -0700255 //Log.w(this, "setIsConferenced, unknown call id: %s", args.arg1);
Santos Cordona1610702014-06-04 20:22:56 -0700256 }
257 } finally {
258 args.recycle();
259 }
260 break;
261 }
262 case MSG_ADD_CONFERENCE_CALL: {
263 SomeArgs args = (SomeArgs) msg.obj;
264 try {
265 String callId = (String) args.arg1;
Santos Cordona1610702014-06-04 20:22:56 -0700266 Call conferenceCall = mCallIdMapper.getCall(callId);
267 if (mPendingConferenceCalls.remove(conferenceCall)) {
268 Log.v(this, "confirming conf call %s", conferenceCall);
269 conferenceCall.confirmConference();
270 } else {
Santos Cordon5924bea2014-06-18 06:39:51 -0700271 //Log.w(this, "addConference, unknown call id: %s", callId);
Santos Cordona1610702014-06-04 20:22:56 -0700272 }
273 } finally {
274 args.recycle();
275 }
276 break;
277 }
Santos Cordon5924bea2014-06-18 06:39:51 -0700278 case MSG_QUERY_REMOTE_CALL_SERVICES: {
279 CallServiceWrapper.this.queryRemoteConnectionServices(
280 (RemoteServiceCallback) msg.obj);
281 }
Santos Cordon3d3b4052014-05-05 12:05:36 -0700282 }
283 }
284 };
285
286 /** {@inheritDoc} */
287 @Override
Santos Cordon3d3b4052014-05-05 12:05:36 -0700288 public void notifyIncomingCall(CallInfo callInfo) {
Ihab Awad55a34282014-06-18 10:31:09 -0700289 logIncoming("notifyIncomingCall %s", callInfo);
Santos Cordon3d3b4052014-05-05 12:05:36 -0700290 mCallIdMapper.checkValidCallId(callInfo.getId());
291 mHandler.obtainMessage(MSG_NOTIFY_INCOMING_CALL, callInfo).sendToTarget();
292 }
293
294 /** {@inheritDoc} */
295 @Override
296 public void handleSuccessfulOutgoingCall(String callId) {
Ihab Awad55a34282014-06-18 10:31:09 -0700297 logIncoming("handleSuccessfulOutgoingCall %s", callId);
Santos Cordon3d3b4052014-05-05 12:05:36 -0700298 mCallIdMapper.checkValidCallId(callId);
299 mHandler.obtainMessage(MSG_HANDLE_SUCCESSFUL_OUTGOING_CALL, callId).sendToTarget();
300 }
301
302 /** {@inheritDoc} */
303 @Override
Ihab Awada3cb9e32014-06-03 18:45:05 -0700304 public void handleFailedOutgoingCall(
305 ConnectionRequest request,
306 int errorCode,
307 String errorMsg) {
Ihab Awad55a34282014-06-18 10:31:09 -0700308 logIncoming("handleFailedOutgoingCall %s %d %s", request, errorCode, errorMsg);
Ihab Awada3cb9e32014-06-03 18:45:05 -0700309 mCallIdMapper.checkValidCallId(request.getCallId());
Santos Cordon3d3b4052014-05-05 12:05:36 -0700310 SomeArgs args = SomeArgs.obtain();
Ihab Awada3cb9e32014-06-03 18:45:05 -0700311 args.arg1 = request.getCallId();
312 args.argi1 = errorCode;
313 args.arg2 = errorMsg;
Santos Cordon3d3b4052014-05-05 12:05:36 -0700314 mHandler.obtainMessage(MSG_HANDLE_FAILED_OUTGOING_CALL, args).sendToTarget();
315 }
316
317 /** {@inheritDoc} */
318 @Override
Sailesh Nepal5a73b032014-06-25 15:53:21 -0700319 public void cancelOutgoingCall(String callId) {
320 logIncoming("cancelOutgoingCall %s", callId);
321 mCallIdMapper.checkValidCallId(callId);
322 mHandler.obtainMessage(MSG_CANCEL_OUTGOING_CALL, callId).sendToTarget();
323 }
324
325 /** {@inheritDoc} */
326 @Override
Santos Cordon3d3b4052014-05-05 12:05:36 -0700327 public void setActive(String callId) {
Ihab Awad55a34282014-06-18 10:31:09 -0700328 logIncoming("setActive %s", callId);
Santos Cordon3d3b4052014-05-05 12:05:36 -0700329 mCallIdMapper.checkValidCallId(callId);
330 mHandler.obtainMessage(MSG_SET_ACTIVE, callId).sendToTarget();
331 }
332
333 /** {@inheritDoc} */
334 @Override
335 public void setRinging(String callId) {
Ihab Awad55a34282014-06-18 10:31:09 -0700336 logIncoming("setRinging %s", callId);
Santos Cordon3d3b4052014-05-05 12:05:36 -0700337 mCallIdMapper.checkValidCallId(callId);
338 mHandler.obtainMessage(MSG_SET_RINGING, callId).sendToTarget();
339 }
340
341 /** {@inheritDoc} */
342 @Override
343 public void setDialing(String callId) {
Ihab Awad55a34282014-06-18 10:31:09 -0700344 logIncoming("setDialing %s", callId);
Santos Cordon3d3b4052014-05-05 12:05:36 -0700345 mCallIdMapper.checkValidCallId(callId);
346 mHandler.obtainMessage(MSG_SET_DIALING, callId).sendToTarget();
347 }
348
349 /** {@inheritDoc} */
350 @Override
351 public void setDisconnected(
352 String callId, int disconnectCause, String disconnectMessage) {
Ihab Awad55a34282014-06-18 10:31:09 -0700353 logIncoming("setDisconnected %s %d %s", callId, disconnectCause, disconnectMessage);
Santos Cordon3d3b4052014-05-05 12:05:36 -0700354 mCallIdMapper.checkValidCallId(callId);
355 SomeArgs args = SomeArgs.obtain();
356 args.arg1 = callId;
357 args.arg2 = disconnectMessage;
358 args.argi1 = disconnectCause;
359 mHandler.obtainMessage(MSG_SET_DISCONNECTED, args).sendToTarget();
360 }
361
362 /** {@inheritDoc} */
363 @Override
364 public void setOnHold(String callId) {
Ihab Awad55a34282014-06-18 10:31:09 -0700365 logIncoming("setOnHold %s", callId);
Santos Cordon3d3b4052014-05-05 12:05:36 -0700366 mCallIdMapper.checkValidCallId(callId);
367 mHandler.obtainMessage(MSG_SET_ON_HOLD, callId).sendToTarget();
368 }
Ihab Awad50a57132014-05-28 16:49:38 -0700369
370 /** {@inheritDoc} */
371 @Override
372 public void setRequestingRingback(String callId, boolean ringback) {
Ihab Awad55a34282014-06-18 10:31:09 -0700373 logIncoming("setRequestingRingback %s %b", callId, ringback);
Ihab Awad50a57132014-05-28 16:49:38 -0700374 mCallIdMapper.checkValidCallId(callId);
375 SomeArgs args = SomeArgs.obtain();
376 args.arg1 = callId;
377 args.arg2 = ringback;
378 mHandler.obtainMessage(MSG_SET_REQUESTING_RINGBACK, args).sendToTarget();
379 }
Santos Cordon8f3282c2014-06-01 13:56:02 -0700380
381 /** ${inheritDoc} */
382 @Override
383 public void removeCall(String callId) {
Ihab Awad55a34282014-06-18 10:31:09 -0700384 logIncoming("removeCall %s", callId);
Santos Cordon8f3282c2014-06-01 13:56:02 -0700385 }
386
387 /** ${inheritDoc} */
388 @Override
Santos Cordona1610702014-06-04 20:22:56 -0700389 public void setCanConference(String callId, boolean canConference) {
Ihab Awad55a34282014-06-18 10:31:09 -0700390 logIncoming("setCanConference %s %b", callId, canConference);
Santos Cordona1610702014-06-04 20:22:56 -0700391 mHandler.obtainMessage(MSG_CAN_CONFERENCE, canConference ? 1 : 0, 0, callId)
392 .sendToTarget();
Santos Cordon8f3282c2014-06-01 13:56:02 -0700393 }
394
395 /** ${inheritDoc} */
396 @Override
Santos Cordona1610702014-06-04 20:22:56 -0700397 public void setIsConferenced(String callId, String conferenceCallId) {
Ihab Awad55a34282014-06-18 10:31:09 -0700398 logIncoming("setIsConferenced %s %s", callId, conferenceCallId);
Santos Cordona1610702014-06-04 20:22:56 -0700399 SomeArgs args = SomeArgs.obtain();
400 args.arg1 = callId;
401 args.arg2 = conferenceCallId;
402 mHandler.obtainMessage(MSG_SET_IS_CONFERENCED, args).sendToTarget();
403 }
404
405 /** ${InheritDoc} */
406 @Override
407 public void addConferenceCall(String callId, CallInfo callInfo) {
Ihab Awad55a34282014-06-18 10:31:09 -0700408 logIncoming("addConferenceCall %s %s", callId, callInfo);
Santos Cordona1610702014-06-04 20:22:56 -0700409 mCallIdMapper.checkValidCallId(callId);
410 SomeArgs args = SomeArgs.obtain();
411 args.arg1 = callId;
412 args.arg2 = callInfo;
413 mHandler.obtainMessage(MSG_ADD_CONFERENCE_CALL, args).sendToTarget();
Santos Cordon8f3282c2014-06-01 13:56:02 -0700414 }
Evan Charlton352105c2014-06-03 14:10:54 -0700415
416 @Override
417 public void onPostDialWait(String callId, String remaining) throws RemoteException {
Ihab Awad55a34282014-06-18 10:31:09 -0700418 logIncoming("onPostDialWait %s %s", callId, remaining);
Evan Charlton352105c2014-06-03 14:10:54 -0700419 mCallIdMapper.checkValidCallId(callId);
420 SomeArgs args = SomeArgs.obtain();
421 args.arg1 = callId;
422 args.arg2 = remaining;
423 mHandler.obtainMessage(MSG_ON_POST_DIAL_WAIT, args).sendToTarget();
424 }
Sailesh Nepal6098d2c2014-06-06 10:56:53 -0700425
426 /** {@inheritDoc} */
427 @Override
428 public void handoffCall(String callId) {
Ihab Awad55a34282014-06-18 10:31:09 -0700429 logIncoming("handoffCall %s", callId);
Sailesh Nepal6098d2c2014-06-06 10:56:53 -0700430 mCallIdMapper.checkValidCallId(callId);
431 mHandler.obtainMessage(MSG_HANDOFF_CALL, callId).sendToTarget();
432 }
Santos Cordon5924bea2014-06-18 06:39:51 -0700433
434 /** ${inheritDoc} */
435 @Override
436 public void queryRemoteConnectionServices(RemoteServiceCallback callback) {
437 logIncoming("queryRemoteCSs");
438 mHandler.obtainMessage(MSG_QUERY_REMOTE_CALL_SERVICES, callback).sendToTarget();
439 }
Santos Cordon3d3b4052014-05-05 12:05:36 -0700440 }
441
442 private final Adapter mAdapter = new Adapter();
443 private final CallsManager mCallsManager = CallsManager.getInstance();
Santos Cordona1610702014-06-04 20:22:56 -0700444 private final Set<Call> mPendingIncomingCalls = new HashSet<>();
445 private final Set<Call> mPendingConferenceCalls = new HashSet<>();
Ben Giladc5b22692014-02-18 20:03:22 -0800446 private final CallServiceDescriptor mDescriptor;
Santos Cordon3d3b4052014-05-05 12:05:36 -0700447 private final CallIdMapper mCallIdMapper = new CallIdMapper("CallService");
Santos Cordon3d3b4052014-05-05 12:05:36 -0700448 private final IncomingCallsManager mIncomingCallsManager;
Sailesh Nepal5a73b032014-06-25 15:53:21 -0700449 private final Map<String, OutgoingCallResponse> mPendingOutgoingCalls = new HashMap<>();
Santos Cordona1610702014-06-04 20:22:56 -0700450 private final Handler mHandler = new Handler();
Santos Cordonc195e362014-02-11 17:05:31 -0800451
Ben Gilad61925612014-03-11 19:06:36 -0700452 private Binder mBinder = new Binder();
Santos Cordon3d3b4052014-05-05 12:05:36 -0700453 private ICallService mServiceInterface;
Santos Cordon5924bea2014-06-18 06:39:51 -0700454 private final CallServiceRepository mCallServiceRepository;
Ben Gilad61925612014-03-11 19:06:36 -0700455
Santos Cordon63aeb162014-02-10 09:20:40 -0800456 /**
Sailesh Nepale59bb192014-04-01 18:33:59 -0700457 * Creates a call-service for the specified descriptor.
Santos Cordonc195e362014-02-11 17:05:31 -0800458 *
Santos Cordon61d0f702014-02-19 02:52:23 -0800459 * @param descriptor The call-service descriptor from
Santos Cordon3d3b4052014-05-05 12:05:36 -0700460 * {@link ICallServiceProvider#lookupCallServices}.
Sailesh Nepale59bb192014-04-01 18:33:59 -0700461 * @param incomingCallsManager Manages the incoming call initialization flow.
Santos Cordon5924bea2014-06-18 06:39:51 -0700462 * @param callServiceRepository Call service repository.
Santos Cordon63aeb162014-02-10 09:20:40 -0800463 */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700464 CallServiceWrapper(
465 CallServiceDescriptor descriptor,
Santos Cordon5924bea2014-06-18 06:39:51 -0700466 IncomingCallsManager incomingCallsManager,
467 CallServiceRepository callServiceRepository) {
Sailesh Nepala439e1b2014-03-11 18:19:58 -0700468 super(TelecommConstants.ACTION_CALL_SERVICE, descriptor.getServiceComponent());
Ben Giladc5b22692014-02-18 20:03:22 -0800469 mDescriptor = descriptor;
Santos Cordon3d3b4052014-05-05 12:05:36 -0700470 mIncomingCallsManager = incomingCallsManager;
Santos Cordon5924bea2014-06-18 06:39:51 -0700471 mCallServiceRepository = callServiceRepository;
Santos Cordon63aeb162014-02-10 09:20:40 -0800472 }
473
Ben Gilad61925612014-03-11 19:06:36 -0700474 CallServiceDescriptor getDescriptor() {
Ben Giladc5b22692014-02-18 20:03:22 -0800475 return mDescriptor;
Santos Cordonc195e362014-02-11 17:05:31 -0800476 }
477
Santos Cordon63aeb162014-02-10 09:20:40 -0800478 /** See {@link ICallService#setCallServiceAdapter}. */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700479 private void setCallServiceAdapter(ICallServiceAdapter callServiceAdapter) {
Santos Cordon61d0f702014-02-19 02:52:23 -0800480 if (isServiceValid("setCallServiceAdapter")) {
481 try {
Ihab Awad55a34282014-06-18 10:31:09 -0700482 logOutgoing("setCallServiceAdapter %s", callServiceAdapter);
Santos Cordon63aeb162014-02-10 09:20:40 -0800483 mServiceInterface.setCallServiceAdapter(callServiceAdapter);
Santos Cordon61d0f702014-02-19 02:52:23 -0800484 } catch (RemoteException e) {
Santos Cordon63aeb162014-02-10 09:20:40 -0800485 }
Santos Cordon63aeb162014-02-10 09:20:40 -0800486 }
487 }
488
Ben Gilad61925612014-03-11 19:06:36 -0700489 /**
Santos Cordon682fe6b2014-05-20 08:56:39 -0700490 * Attempts to place the specified call, see {@link ICallService#call}. Returns the result
491 * asynchronously through the specified callback.
Ben Gilad61925612014-03-11 19:06:36 -0700492 */
Sailesh Nepal5a73b032014-06-25 15:53:21 -0700493 void call(final Call call, final OutgoingCallResponse callResponse) {
Santos Cordon682fe6b2014-05-20 08:56:39 -0700494 Log.d(this, "call(%s) via %s.", call, getComponentName());
Ben Gilad61925612014-03-11 19:06:36 -0700495 BindCallback callback = new BindCallback() {
Santos Cordon3d3b4052014-05-05 12:05:36 -0700496 @Override
497 public void onSuccess() {
Santos Cordon682fe6b2014-05-20 08:56:39 -0700498 String callId = mCallIdMapper.getCallId(call);
Sailesh Nepal5a73b032014-06-25 15:53:21 -0700499 mPendingOutgoingCalls.put(callId, callResponse);
Santos Cordon682fe6b2014-05-20 08:56:39 -0700500
501 try {
502 CallInfo callInfo = call.toCallInfo(callId);
Ihab Awad55a34282014-06-18 10:31:09 -0700503 logOutgoing("call %s", callInfo);
Santos Cordon682fe6b2014-05-20 08:56:39 -0700504 mServiceInterface.call(callInfo);
505 } catch (RemoteException e) {
Santos Cordon5924bea2014-06-18 06:39:51 -0700506 Log.e(this, e, "Failure to call -- %s", getDescriptor());
Sailesh Nepal5a73b032014-06-25 15:53:21 -0700507 mPendingOutgoingCalls.remove(callId).onOutgoingCallFailure(
508 DisconnectCause.ERROR_UNSPECIFIED, e.toString());
Ben Gilad61925612014-03-11 19:06:36 -0700509 }
Santos Cordon63aeb162014-02-10 09:20:40 -0800510 }
Santos Cordon3d3b4052014-05-05 12:05:36 -0700511
512 @Override
513 public void onFailure() {
Santos Cordon5924bea2014-06-18 06:39:51 -0700514 Log.e(this, new Exception(), "Failure to call %s", getDescriptor());
Sailesh Nepal5a73b032014-06-25 15:53:21 -0700515 callResponse.onOutgoingCallFailure(DisconnectCause.ERROR_UNSPECIFIED, null);
Ben Gilad61925612014-03-11 19:06:36 -0700516 }
517 };
518
519 mBinder.bind(callback);
Santos Cordon63aeb162014-02-10 09:20:40 -0800520 }
521
Ihab Awad74549ec2014-03-10 15:33:25 -0700522 /** @see CallService#abort(String) */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700523 void abort(Call call) {
Santos Cordon682fe6b2014-05-20 08:56:39 -0700524 // Clear out any pending outgoing call data
525 String callId = mCallIdMapper.getCallId(call);
526
527 // If still bound, tell the call service to abort.
Ben Gilad28e8ad62014-03-06 17:01:54 -0800528 if (isServiceValid("abort")) {
529 try {
Ihab Awad55a34282014-06-18 10:31:09 -0700530 logOutgoing("abort %s", callId);
Santos Cordon682fe6b2014-05-20 08:56:39 -0700531 mServiceInterface.abort(callId);
Ben Gilad28e8ad62014-03-06 17:01:54 -0800532 } catch (RemoteException e) {
Santos Cordon63aeb162014-02-10 09:20:40 -0800533 }
Santos Cordon61d0f702014-02-19 02:52:23 -0800534 }
Santos Cordon682fe6b2014-05-20 08:56:39 -0700535
536 removeCall(call);
Santos Cordon61d0f702014-02-19 02:52:23 -0800537 }
538
Ihab Awad74549ec2014-03-10 15:33:25 -0700539 /** @see CallService#hold(String) */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700540 void hold(Call call) {
Yorke Leecdf3ebd2014-03-12 18:31:41 -0700541 if (isServiceValid("hold")) {
542 try {
Ihab Awad55a34282014-06-18 10:31:09 -0700543 logOutgoing("hold %s", mCallIdMapper.getCallId(call));
Sailesh Nepale59bb192014-04-01 18:33:59 -0700544 mServiceInterface.hold(mCallIdMapper.getCallId(call));
Yorke Leecdf3ebd2014-03-12 18:31:41 -0700545 } catch (RemoteException e) {
Yorke Leecdf3ebd2014-03-12 18:31:41 -0700546 }
547 }
548 }
549
Ihab Awad74549ec2014-03-10 15:33:25 -0700550 /** @see CallService#unhold(String) */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700551 void unhold(Call call) {
Yorke Leecdf3ebd2014-03-12 18:31:41 -0700552 if (isServiceValid("unhold")) {
553 try {
Ihab Awad55a34282014-06-18 10:31:09 -0700554 logOutgoing("unhold %s", mCallIdMapper.getCallId(call));
Sailesh Nepale59bb192014-04-01 18:33:59 -0700555 mServiceInterface.unhold(mCallIdMapper.getCallId(call));
Yorke Leecdf3ebd2014-03-12 18:31:41 -0700556 } catch (RemoteException e) {
Yorke Leecdf3ebd2014-03-12 18:31:41 -0700557 }
558 }
559 }
560
Ihab Awad74549ec2014-03-10 15:33:25 -0700561 /** @see CallService#onAudioStateChanged(String,CallAudioState) */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700562 void onAudioStateChanged(Call activeCall, CallAudioState audioState) {
Sailesh Nepal6aca10a2014-03-24 16:11:02 -0700563 if (isServiceValid("onAudioStateChanged")) {
564 try {
Ihab Awad55a34282014-06-18 10:31:09 -0700565 logOutgoing("onAudioStateChanged %s %s",
566 mCallIdMapper.getCallId(activeCall), audioState);
Sailesh Nepale59bb192014-04-01 18:33:59 -0700567 mServiceInterface.onAudioStateChanged(mCallIdMapper.getCallId(activeCall),
568 audioState);
Sailesh Nepal6aca10a2014-03-24 16:11:02 -0700569 } catch (RemoteException e) {
Sailesh Nepal6aca10a2014-03-24 16:11:02 -0700570 }
571 }
572 }
573
Ben Gilad61925612014-03-11 19:06:36 -0700574 /**
575 * Starts retrieval of details for an incoming call. Details are returned through the
576 * call-service adapter using the specified call ID. Upon failure, the specified error callback
Santos Cordon3d3b4052014-05-05 12:05:36 -0700577 * is invoked. Can be invoked even when the call service is unbound. See
578 * {@link ICallService#setIncomingCallId}.
Ben Gilad61925612014-03-11 19:06:36 -0700579 *
Sailesh Nepale59bb192014-04-01 18:33:59 -0700580 * @param call The call used for the incoming call.
Ben Gilad61925612014-03-11 19:06:36 -0700581 * @param extras The {@link CallService}-provided extras which need to be sent back.
582 * @param errorCallback The callback to invoke upon failure.
583 */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700584 void setIncomingCallId(final Call call, final Bundle extras, final Runnable errorCallback) {
585 Log.d(this, "setIncomingCall(%s) via %s.", call, getComponentName());
Ben Gilad61925612014-03-11 19:06:36 -0700586 BindCallback callback = new BindCallback() {
Santos Cordon3d3b4052014-05-05 12:05:36 -0700587 @Override
588 public void onSuccess() {
Ben Gilad61925612014-03-11 19:06:36 -0700589 if (isServiceValid("setIncomingCallId")) {
Santos Cordon682fe6b2014-05-20 08:56:39 -0700590 mPendingIncomingCalls.add(call);
Ben Gilad61925612014-03-11 19:06:36 -0700591 try {
Ihab Awad55a34282014-06-18 10:31:09 -0700592 logOutgoing("setIncomingCallId %s %s",
593 mCallIdMapper.getCallId(call), extras);
Sailesh Nepale59bb192014-04-01 18:33:59 -0700594 mServiceInterface.setIncomingCallId(mCallIdMapper.getCallId(call),
595 extras);
Ben Gilad61925612014-03-11 19:06:36 -0700596 } catch (RemoteException e) {
Ben Gilad61925612014-03-11 19:06:36 -0700597 }
598 }
Santos Cordon61d0f702014-02-19 02:52:23 -0800599 }
Santos Cordon3d3b4052014-05-05 12:05:36 -0700600
601 @Override
602 public void onFailure() {
Ben Gilad61925612014-03-11 19:06:36 -0700603 errorCallback.run();
604 }
605 };
606
607 mBinder.bind(callback);
Santos Cordon63aeb162014-02-10 09:20:40 -0800608 }
609
Ihab Awad74549ec2014-03-10 15:33:25 -0700610 /** @see CallService#disconnect(String) */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700611 void disconnect(Call call) {
Santos Cordon61d0f702014-02-19 02:52:23 -0800612 if (isServiceValid("disconnect")) {
613 try {
Ihab Awad55a34282014-06-18 10:31:09 -0700614 logOutgoing("disconnect %s", mCallIdMapper.getCallId(call));
Sailesh Nepale59bb192014-04-01 18:33:59 -0700615 mServiceInterface.disconnect(mCallIdMapper.getCallId(call));
Santos Cordon61d0f702014-02-19 02:52:23 -0800616 } catch (RemoteException e) {
Santos Cordon63aeb162014-02-10 09:20:40 -0800617 }
Santos Cordon63aeb162014-02-10 09:20:40 -0800618 }
619 }
Santos Cordon5c12c6e2014-02-13 14:35:31 -0800620
Ihab Awad74549ec2014-03-10 15:33:25 -0700621 /** @see CallService#answer(String) */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700622 void answer(Call call) {
Santos Cordon61d0f702014-02-19 02:52:23 -0800623 if (isServiceValid("answer")) {
624 try {
Ihab Awad55a34282014-06-18 10:31:09 -0700625 logOutgoing("answer %s", mCallIdMapper.getCallId(call));
Sailesh Nepale59bb192014-04-01 18:33:59 -0700626 mServiceInterface.answer(mCallIdMapper.getCallId(call));
Santos Cordon61d0f702014-02-19 02:52:23 -0800627 } catch (RemoteException e) {
Santos Cordon7917d382014-02-14 02:31:18 -0800628 }
Santos Cordon61d0f702014-02-19 02:52:23 -0800629 }
630 }
631
Ihab Awad74549ec2014-03-10 15:33:25 -0700632 /** @see CallService#reject(String) */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700633 void reject(Call call) {
Santos Cordon61d0f702014-02-19 02:52:23 -0800634 if (isServiceValid("reject")) {
635 try {
Ihab Awad55a34282014-06-18 10:31:09 -0700636 logOutgoing("reject %s", mCallIdMapper.getCallId(call));
Sailesh Nepale59bb192014-04-01 18:33:59 -0700637 mServiceInterface.reject(mCallIdMapper.getCallId(call));
Santos Cordon61d0f702014-02-19 02:52:23 -0800638 } catch (RemoteException e) {
Ihab Awad74549ec2014-03-10 15:33:25 -0700639 }
640 }
641 }
642
643 /** @see CallService#playDtmfTone(String,char) */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700644 void playDtmfTone(Call call, char digit) {
Ihab Awad74549ec2014-03-10 15:33:25 -0700645 if (isServiceValid("playDtmfTone")) {
646 try {
Ihab Awad55a34282014-06-18 10:31:09 -0700647 logOutgoing("playDtmfTone %s %c", mCallIdMapper.getCallId(call), digit);
Sailesh Nepale59bb192014-04-01 18:33:59 -0700648 mServiceInterface.playDtmfTone(mCallIdMapper.getCallId(call), digit);
Ihab Awad74549ec2014-03-10 15:33:25 -0700649 } catch (RemoteException e) {
Ihab Awad74549ec2014-03-10 15:33:25 -0700650 }
651 }
652 }
653
654 /** @see CallService#stopDtmfTone(String) */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700655 void stopDtmfTone(Call call) {
Ihab Awad74549ec2014-03-10 15:33:25 -0700656 if (isServiceValid("stopDtmfTone")) {
657 try {
Ihab Awad55a34282014-06-18 10:31:09 -0700658 logOutgoing("stopDtmfTone %s", mCallIdMapper.getCallId(call));
Sailesh Nepale59bb192014-04-01 18:33:59 -0700659 mServiceInterface.stopDtmfTone(mCallIdMapper.getCallId(call));
Ihab Awad74549ec2014-03-10 15:33:25 -0700660 } catch (RemoteException e) {
Santos Cordon61d0f702014-02-19 02:52:23 -0800661 }
Santos Cordon7917d382014-02-14 02:31:18 -0800662 }
663 }
664
Sailesh Nepale59bb192014-04-01 18:33:59 -0700665 void addCall(Call call) {
Santos Cordona1610702014-06-04 20:22:56 -0700666 if (mCallIdMapper.getCallId(call) == null) {
667 mCallIdMapper.addCall(call);
668 }
Santos Cordon7917d382014-02-14 02:31:18 -0800669 }
670
Sailesh Nepal0e5410a2014-04-04 01:20:58 -0700671 /**
672 * Associates newCall with this call service by replacing callToReplace.
673 */
674 void replaceCall(Call newCall, Call callToReplace) {
675 Preconditions.checkState(callToReplace.getCallService() == this);
676 mCallIdMapper.replaceCall(newCall, callToReplace);
677 }
678
Sailesh Nepale59bb192014-04-01 18:33:59 -0700679 void removeCall(Call call) {
Santos Cordon682fe6b2014-05-20 08:56:39 -0700680 mPendingIncomingCalls.remove(call);
681
Sailesh Nepal5a73b032014-06-25 15:53:21 -0700682 OutgoingCallResponse outgoingResultCallback =
683 mPendingOutgoingCalls.remove(mCallIdMapper.getCallId(call));
Santos Cordon682fe6b2014-05-20 08:56:39 -0700684 if (outgoingResultCallback != null) {
Sailesh Nepal5a73b032014-06-25 15:53:21 -0700685 outgoingResultCallback.onOutgoingCallFailure(DisconnectCause.ERROR_UNSPECIFIED, null);
Santos Cordon682fe6b2014-05-20 08:56:39 -0700686 }
687
Sailesh Nepale59bb192014-04-01 18:33:59 -0700688 mCallIdMapper.removeCall(call);
Yorke Leeadee12d2014-03-13 12:08:30 -0700689 }
690
Evan Charlton352105c2014-06-03 14:10:54 -0700691 void onPostDialContinue(Call call, boolean proceed) {
692 if (isServiceValid("onPostDialContinue")) {
693 try {
Ihab Awad55a34282014-06-18 10:31:09 -0700694 logOutgoing("onPostDialContinue %s %b", mCallIdMapper.getCallId(call), proceed);
Evan Charlton352105c2014-06-03 14:10:54 -0700695 mServiceInterface.onPostDialContinue(mCallIdMapper.getCallId(call), proceed);
696 } catch (RemoteException ignored) {
697 }
698 }
699 }
700
Santos Cordona1610702014-06-04 20:22:56 -0700701 void conference(final Call conferenceCall, Call call) {
702 if (isServiceValid("conference")) {
703 try {
704 conferenceCall.setCallService(this);
705 mPendingConferenceCalls.add(conferenceCall);
706 mHandler.postDelayed(new Runnable() {
707 @Override public void run() {
708 if (mPendingConferenceCalls.remove(conferenceCall)) {
709 conferenceCall.expireConference();
710 Log.i(this, "Conference call expired: %s", conferenceCall);
711 }
712 }
713 }, Timeouts.getConferenceCallExpireMillis());
714
Ihab Awad55a34282014-06-18 10:31:09 -0700715 logOutgoing("conference %s %s",
716 mCallIdMapper.getCallId(conferenceCall),
717 mCallIdMapper.getCallId(call));
Santos Cordona1610702014-06-04 20:22:56 -0700718 mServiceInterface.conference(
719 mCallIdMapper.getCallId(conferenceCall),
720 mCallIdMapper.getCallId(call));
721 } catch (RemoteException ignored) {
722 }
723 }
724 }
725
726 void splitFromConference(Call call) {
727 if (isServiceValid("splitFromConference")) {
728 try {
Ihab Awad55a34282014-06-18 10:31:09 -0700729 logOutgoing("splitFromConference %s", mCallIdMapper.getCallId(call));
Santos Cordona1610702014-06-04 20:22:56 -0700730 mServiceInterface.splitFromConference(mCallIdMapper.getCallId(call));
731 } catch (RemoteException ignored) {
732 }
733 }
734 }
735
Santos Cordon5c12c6e2014-02-13 14:35:31 -0800736 /** {@inheritDoc} */
Santos Cordon3d3b4052014-05-05 12:05:36 -0700737 @Override
738 protected void setServiceInterface(IBinder binder) {
Santos Cordon4b2c1192014-03-19 18:15:38 -0700739 if (binder == null) {
740 // We have lost our service connection. Notify the world that this call service is done.
741 // We must notify the adapter before CallsManager. The adapter will force any pending
742 // outgoing calls to try the next call service. This needs to happen before CallsManager
743 // tries to clean up any calls still associated with this call service.
Santos Cordon3d3b4052014-05-05 12:05:36 -0700744 handleCallServiceDeath();
Santos Cordon4b2c1192014-03-19 18:15:38 -0700745 CallsManager.getInstance().handleCallServiceDeath(this);
746 mServiceInterface = null;
747 } else {
748 mServiceInterface = ICallService.Stub.asInterface(binder);
749 setCallServiceAdapter(mAdapter);
750 }
Santos Cordon5c12c6e2014-02-13 14:35:31 -0800751 }
Santos Cordon3d3b4052014-05-05 12:05:36 -0700752
753 /**
754 * Called when the associated call service dies.
755 */
756 private void handleCallServiceDeath() {
Santos Cordon682fe6b2014-05-20 08:56:39 -0700757 if (!mPendingOutgoingCalls.isEmpty()) {
Sailesh Nepal5a73b032014-06-25 15:53:21 -0700758 for (OutgoingCallResponse callback : mPendingOutgoingCalls.values()) {
759 callback.onOutgoingCallFailure(DisconnectCause.ERROR_UNSPECIFIED, null);
Santos Cordon682fe6b2014-05-20 08:56:39 -0700760 }
761 mPendingOutgoingCalls.clear();
762 }
763
764 if (!mPendingIncomingCalls.isEmpty()) {
Santos Cordon3d3b4052014-05-05 12:05:36 -0700765 // Iterate through a copy because the code inside the loop will modify the original
766 // list.
Santos Cordon682fe6b2014-05-20 08:56:39 -0700767 for (Call call : ImmutableList.copyOf(mPendingIncomingCalls)) {
768 Preconditions.checkState(call.isIncoming());
769 mIncomingCallsManager.handleFailedIncomingCall(call);
Santos Cordon3d3b4052014-05-05 12:05:36 -0700770 }
771
Santos Cordona1610702014-06-04 20:22:56 -0700772 if (!mPendingIncomingCalls.isEmpty()) {
773 Log.wtf(this, "Pending calls did not get cleared.");
774 mPendingIncomingCalls.clear();
775 }
776 }
Santos Cordon8f3282c2014-06-01 13:56:02 -0700777
Santos Cordona1610702014-06-04 20:22:56 -0700778 mCallIdMapper.clear();
779 }
Ihab Awad55a34282014-06-18 10:31:09 -0700780
781 private void logIncoming(String msg, Object... params) {
782 Log.d(this, "CallService -> Telecomm: " + msg, params);
783 }
784
785 private void logOutgoing(String msg, Object... params) {
786 Log.d(this, "Telecomm -> CallService: " + msg, params);
787 }
Santos Cordon5924bea2014-06-18 06:39:51 -0700788
789 private void queryRemoteConnectionServices(final RemoteServiceCallback callback) {
790 final List<IBinder> callServices = new ArrayList<>();
791 final List<ComponentName> components = new ArrayList<>();
792
793 mCallServiceRepository.lookupServices(new LookupCallback<CallServiceWrapper>() {
794 private int mRemainingResponses;
795
796 /** ${inheritDoc} */
797 @Override
798 public void onComplete(Collection<CallServiceWrapper> services) {
799 mRemainingResponses = services.size() - 1;
800 for (CallServiceWrapper cs : services) {
801 if (cs != CallServiceWrapper.this) {
802 final CallServiceWrapper currentCallService = cs;
803 cs.mBinder.bind(new BindCallback() {
804 @Override
805 public void onSuccess() {
806 Log.d(this, "Adding ***** %s", currentCallService.getDescriptor());
807 callServices.add(currentCallService.mServiceInterface.asBinder());
808 components.add(currentCallService.getComponentName());
809 maybeComplete();
810 }
811
812 @Override
813 public void onFailure() {
814 // add null so that we always add up to totalExpected even if
815 // some of the call services fail to bind.
816 maybeComplete();
817 }
818
819 private void maybeComplete() {
820 if (--mRemainingResponses == 0) {
821 try {
822 callback.onResult(components, callServices);
823 } catch (RemoteException ignored) {
824 }
825 }
826 }
827 });
828 }
829 }
830 }
831 });
832 }
Santos Cordon63aeb162014-02-10 09:20:40 -0800833}