blob: 5d7b47a833c4f5c93976fcdd69e8d39b6ba16643 [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;
64 private static final int MSG_SET_ACTIVE = 4;
65 private static final int MSG_SET_RINGING = 5;
66 private static final int MSG_SET_DIALING = 6;
67 private static final int MSG_SET_DISCONNECTED = 7;
68 private static final int MSG_SET_ON_HOLD = 8;
Ihab Awad50a57132014-05-28 16:49:38 -070069 private static final int MSG_SET_REQUESTING_RINGBACK = 9;
Evan Charlton352105c2014-06-03 14:10:54 -070070 private static final int MSG_ON_POST_DIAL_WAIT = 10;
Santos Cordona1610702014-06-04 20:22:56 -070071 private static final int MSG_CAN_CONFERENCE = 11;
72 private static final int MSG_SET_IS_CONFERENCED = 12;
73 private static final int MSG_ADD_CONFERENCE_CALL = 13;
74 private static final int MSG_HANDOFF_CALL = 14;
Santos Cordon5924bea2014-06-18 06:39:51 -070075 private static final int MSG_QUERY_REMOTE_CALL_SERVICES = 15;
Santos Cordon3d3b4052014-05-05 12:05:36 -070076
77 private final Handler mHandler = new Handler() {
78 @Override
79 public void handleMessage(Message msg) {
80 Call call;
81 switch (msg.what) {
Santos Cordon3d3b4052014-05-05 12:05:36 -070082 case MSG_NOTIFY_INCOMING_CALL:
83 CallInfo clientCallInfo = (CallInfo) msg.obj;
84 call = mCallIdMapper.getCall(clientCallInfo.getId());
Santos Cordon682fe6b2014-05-20 08:56:39 -070085 if (call != null && mPendingIncomingCalls.remove(call) &&
86 call.isIncoming()) {
Santos Cordon3d3b4052014-05-05 12:05:36 -070087 CallInfo callInfo = new CallInfo(null, clientCallInfo.getState(),
88 clientCallInfo.getHandle());
89 mIncomingCallsManager.handleSuccessfulIncomingCall(call, callInfo);
90 } else {
Santos Cordon5924bea2014-06-18 06:39:51 -070091 // TODO(santoscordon): For this an the other commented logging, we need
92 // to reenable it. At the moment all CallServiceAdapters receive
93 // notification of changes to all calls, even calls which it may not own
94 // (ala remote connections). We need to fix that and then uncomment the
95 // logging calls here.
96 //Log.w(this, "notifyIncomingCall, unknown incoming call: %s, id: %s",
97 // call, clientCallInfo.getId());
Santos Cordon3d3b4052014-05-05 12:05:36 -070098 }
99 break;
Santos Cordon682fe6b2014-05-20 08:56:39 -0700100 case MSG_HANDLE_SUCCESSFUL_OUTGOING_CALL: {
101 String callId = (String) msg.obj;
102 if (mPendingOutgoingCalls.containsKey(callId)) {
Ihab Awada3cb9e32014-06-03 18:45:05 -0700103 mPendingOutgoingCalls.remove(callId).onResult(true, 0, null);
Santos Cordon3d3b4052014-05-05 12:05:36 -0700104 } else {
Santos Cordon5924bea2014-06-18 06:39:51 -0700105 //Log.w(this, "handleSuccessfulOutgoingCall, unknown call: %s", callId);
Santos Cordon3d3b4052014-05-05 12:05:36 -0700106 }
107 break;
Santos Cordon682fe6b2014-05-20 08:56:39 -0700108 }
Santos Cordon3d3b4052014-05-05 12:05:36 -0700109 case MSG_HANDLE_FAILED_OUTGOING_CALL: {
110 SomeArgs args = (SomeArgs) msg.obj;
111 try {
Santos Cordon682fe6b2014-05-20 08:56:39 -0700112 String callId = (String) args.arg1;
Ihab Awada3cb9e32014-06-03 18:45:05 -0700113 int statusCode = args.argi1;
114 String statusMsg = (String) args.arg2;
Santos Cordon682fe6b2014-05-20 08:56:39 -0700115 // TODO(santoscordon): Do something with 'reason' or get rid of it.
116
117 if (mPendingOutgoingCalls.containsKey(callId)) {
Ihab Awada3cb9e32014-06-03 18:45:05 -0700118 mPendingOutgoingCalls.remove(callId).onResult(
119 false, statusCode, statusMsg);
Santos Cordon682fe6b2014-05-20 08:56:39 -0700120 mCallIdMapper.removeCall(callId);
Santos Cordon3d3b4052014-05-05 12:05:36 -0700121 } else {
Santos Cordon5924bea2014-06-18 06:39:51 -0700122 //Log.w(this, "handleFailedOutgoingCall, unknown call: %s", callId);
Santos Cordon3d3b4052014-05-05 12:05:36 -0700123 }
124 } finally {
125 args.recycle();
126 }
127 break;
128 }
129 case MSG_SET_ACTIVE:
130 call = mCallIdMapper.getCall(msg.obj);
131 if (call != null) {
132 mCallsManager.markCallAsActive(call);
133 } else {
Santos Cordon5924bea2014-06-18 06:39:51 -0700134 //Log.w(this, "setActive, unknown call id: %s", msg.obj);
Santos Cordon3d3b4052014-05-05 12:05:36 -0700135 }
136 break;
137 case MSG_SET_RINGING:
138 call = mCallIdMapper.getCall(msg.obj);
139 if (call != null) {
140 mCallsManager.markCallAsRinging(call);
141 } else {
Santos Cordon5924bea2014-06-18 06:39:51 -0700142 //Log.w(this, "setRinging, unknown call id: %s", msg.obj);
Santos Cordon3d3b4052014-05-05 12:05:36 -0700143 }
144 break;
145 case MSG_SET_DIALING:
146 call = mCallIdMapper.getCall(msg.obj);
147 if (call != null) {
148 mCallsManager.markCallAsDialing(call);
149 } else {
Santos Cordon5924bea2014-06-18 06:39:51 -0700150 //Log.w(this, "setDialing, unknown call id: %s", msg.obj);
Santos Cordon3d3b4052014-05-05 12:05:36 -0700151 }
152 break;
153 case MSG_SET_DISCONNECTED: {
154 SomeArgs args = (SomeArgs) msg.obj;
155 try {
156 call = mCallIdMapper.getCall(args.arg1);
157 String disconnectMessage = (String) args.arg2;
158 int disconnectCause = args.argi1;
159 if (call != null) {
160 mCallsManager.markCallAsDisconnected(call, disconnectCause,
161 disconnectMessage);
162 } else {
Santos Cordon5924bea2014-06-18 06:39:51 -0700163 //Log.w(this, "setDisconnected, unknown call id: %s", args.arg1);
Santos Cordon3d3b4052014-05-05 12:05:36 -0700164 }
165 } finally {
166 args.recycle();
167 }
168 break;
169 }
170 case MSG_SET_ON_HOLD:
171 call = mCallIdMapper.getCall(msg.obj);
172 if (call != null) {
173 mCallsManager.markCallAsOnHold(call);
174 } else {
Santos Cordon5924bea2014-06-18 06:39:51 -0700175 //Log.w(this, "setOnHold, unknown call id: %s", msg.obj);
Santos Cordon3d3b4052014-05-05 12:05:36 -0700176 }
177 break;
Evan Charlton352105c2014-06-03 14:10:54 -0700178 case MSG_SET_REQUESTING_RINGBACK: {
Ihab Awad50a57132014-05-28 16:49:38 -0700179 SomeArgs args = (SomeArgs) msg.obj;
180 try {
181 call = mCallIdMapper.getCall(args.arg1);
182 boolean ringback = (boolean) args.arg2;
183 if (call != null) {
184 call.setRequestingRingback(ringback);
185 } else {
Santos Cordon5924bea2014-06-18 06:39:51 -0700186 //Log.w(this, "setRingback, unknown call id: %s", args.arg1);
Ihab Awad50a57132014-05-28 16:49:38 -0700187 }
188 } finally {
189 args.recycle();
190 }
191 break;
Evan Charlton352105c2014-06-03 14:10:54 -0700192 }
Santos Cordona1610702014-06-04 20:22:56 -0700193 case MSG_ON_POST_DIAL_WAIT: {
Evan Charlton352105c2014-06-03 14:10:54 -0700194 SomeArgs args = (SomeArgs) msg.obj;
195 try {
196 call = mCallIdMapper.getCall(args.arg1);
197 if (call != null) {
198 String remaining = (String) args.arg2;
199 call.onPostDialWait(remaining);
200 } else {
Santos Cordon5924bea2014-06-18 06:39:51 -0700201 //Log.w(this, "onPostDialWait, unknown call id: %s", args.arg1);
Evan Charlton352105c2014-06-03 14:10:54 -0700202 }
203 } finally {
204 args.recycle();
205 }
Santos Cordona1610702014-06-04 20:22:56 -0700206 break;
207 }
Sailesh Nepal6098d2c2014-06-06 10:56:53 -0700208 case MSG_HANDOFF_CALL:
209 call = mCallIdMapper.getCall(msg.obj);
210 if (call != null) {
211 mCallsManager.startHandoffForCall(call);
212 } else {
Santos Cordon5924bea2014-06-18 06:39:51 -0700213 //Log.w(this, "handoffCall, unknown call id: %s", msg.obj);
Sailesh Nepal6098d2c2014-06-06 10:56:53 -0700214 }
215 break;
Santos Cordona1610702014-06-04 20:22:56 -0700216 case MSG_CAN_CONFERENCE: {
217 call = mCallIdMapper.getCall(msg.obj);
218 if (call != null) {
219 call.setIsConferenceCapable(msg.arg1 == 1);
220 } else {
Santos Cordon5924bea2014-06-18 06:39:51 -0700221 //Log.w(CallServiceWrapper.this, "canConference, unknown call id: %s",
222 // msg.obj);
Santos Cordona1610702014-06-04 20:22:56 -0700223 }
224 break;
225 }
226 case MSG_SET_IS_CONFERENCED: {
227 SomeArgs args = (SomeArgs) msg.obj;
228 try {
229 Call childCall = mCallIdMapper.getCall(args.arg1);
230 if (childCall != null) {
231 String conferenceCallId = (String) args.arg2;
Santos Cordona1610702014-06-04 20:22:56 -0700232 if (conferenceCallId == null) {
233 childCall.setParentCall(null);
234 } else {
235 Call conferenceCall = mCallIdMapper.getCall(conferenceCallId);
236 if (conferenceCall != null &&
237 !mPendingConferenceCalls.contains(conferenceCall)) {
238 childCall.setParentCall(conferenceCall);
239 } else {
Santos Cordon5924bea2014-06-18 06:39:51 -0700240 //Log.w(this, "setIsConferenced, unknown conference id %s",
241 // conferenceCallId);
Santos Cordona1610702014-06-04 20:22:56 -0700242 }
243 }
244 } else {
Santos Cordon5924bea2014-06-18 06:39:51 -0700245 //Log.w(this, "setIsConferenced, unknown call id: %s", args.arg1);
Santos Cordona1610702014-06-04 20:22:56 -0700246 }
247 } finally {
248 args.recycle();
249 }
250 break;
251 }
252 case MSG_ADD_CONFERENCE_CALL: {
253 SomeArgs args = (SomeArgs) msg.obj;
254 try {
255 String callId = (String) args.arg1;
Santos Cordona1610702014-06-04 20:22:56 -0700256 Call conferenceCall = mCallIdMapper.getCall(callId);
257 if (mPendingConferenceCalls.remove(conferenceCall)) {
258 Log.v(this, "confirming conf call %s", conferenceCall);
259 conferenceCall.confirmConference();
260 } else {
Santos Cordon5924bea2014-06-18 06:39:51 -0700261 //Log.w(this, "addConference, unknown call id: %s", callId);
Santos Cordona1610702014-06-04 20:22:56 -0700262 }
263 } finally {
264 args.recycle();
265 }
266 break;
267 }
Santos Cordon5924bea2014-06-18 06:39:51 -0700268 case MSG_QUERY_REMOTE_CALL_SERVICES: {
269 CallServiceWrapper.this.queryRemoteConnectionServices(
270 (RemoteServiceCallback) msg.obj);
271 }
Santos Cordon3d3b4052014-05-05 12:05:36 -0700272 }
273 }
274 };
275
276 /** {@inheritDoc} */
277 @Override
Santos Cordon3d3b4052014-05-05 12:05:36 -0700278 public void notifyIncomingCall(CallInfo callInfo) {
Ihab Awad55a34282014-06-18 10:31:09 -0700279 logIncoming("notifyIncomingCall %s", callInfo);
Santos Cordon3d3b4052014-05-05 12:05:36 -0700280 mCallIdMapper.checkValidCallId(callInfo.getId());
281 mHandler.obtainMessage(MSG_NOTIFY_INCOMING_CALL, callInfo).sendToTarget();
282 }
283
284 /** {@inheritDoc} */
285 @Override
286 public void handleSuccessfulOutgoingCall(String callId) {
Ihab Awad55a34282014-06-18 10:31:09 -0700287 logIncoming("handleSuccessfulOutgoingCall %s", callId);
Santos Cordon3d3b4052014-05-05 12:05:36 -0700288 mCallIdMapper.checkValidCallId(callId);
289 mHandler.obtainMessage(MSG_HANDLE_SUCCESSFUL_OUTGOING_CALL, callId).sendToTarget();
290 }
291
292 /** {@inheritDoc} */
293 @Override
Ihab Awada3cb9e32014-06-03 18:45:05 -0700294 public void handleFailedOutgoingCall(
295 ConnectionRequest request,
296 int errorCode,
297 String errorMsg) {
Ihab Awad55a34282014-06-18 10:31:09 -0700298 logIncoming("handleFailedOutgoingCall %s %d %s", request, errorCode, errorMsg);
Ihab Awada3cb9e32014-06-03 18:45:05 -0700299 mCallIdMapper.checkValidCallId(request.getCallId());
Santos Cordon3d3b4052014-05-05 12:05:36 -0700300 SomeArgs args = SomeArgs.obtain();
Ihab Awada3cb9e32014-06-03 18:45:05 -0700301 args.arg1 = request.getCallId();
302 args.argi1 = errorCode;
303 args.arg2 = errorMsg;
Santos Cordon3d3b4052014-05-05 12:05:36 -0700304 mHandler.obtainMessage(MSG_HANDLE_FAILED_OUTGOING_CALL, args).sendToTarget();
305 }
306
307 /** {@inheritDoc} */
308 @Override
309 public void setActive(String callId) {
Ihab Awad55a34282014-06-18 10:31:09 -0700310 logIncoming("setActive %s", callId);
Santos Cordon3d3b4052014-05-05 12:05:36 -0700311 mCallIdMapper.checkValidCallId(callId);
312 mHandler.obtainMessage(MSG_SET_ACTIVE, callId).sendToTarget();
313 }
314
315 /** {@inheritDoc} */
316 @Override
317 public void setRinging(String callId) {
Ihab Awad55a34282014-06-18 10:31:09 -0700318 logIncoming("setRinging %s", callId);
Santos Cordon3d3b4052014-05-05 12:05:36 -0700319 mCallIdMapper.checkValidCallId(callId);
320 mHandler.obtainMessage(MSG_SET_RINGING, callId).sendToTarget();
321 }
322
323 /** {@inheritDoc} */
324 @Override
325 public void setDialing(String callId) {
Ihab Awad55a34282014-06-18 10:31:09 -0700326 logIncoming("setDialing %s", callId);
Santos Cordon3d3b4052014-05-05 12:05:36 -0700327 mCallIdMapper.checkValidCallId(callId);
328 mHandler.obtainMessage(MSG_SET_DIALING, callId).sendToTarget();
329 }
330
331 /** {@inheritDoc} */
332 @Override
333 public void setDisconnected(
334 String callId, int disconnectCause, String disconnectMessage) {
Ihab Awad55a34282014-06-18 10:31:09 -0700335 logIncoming("setDisconnected %s %d %s", callId, disconnectCause, disconnectMessage);
Santos Cordon3d3b4052014-05-05 12:05:36 -0700336 mCallIdMapper.checkValidCallId(callId);
337 SomeArgs args = SomeArgs.obtain();
338 args.arg1 = callId;
339 args.arg2 = disconnectMessage;
340 args.argi1 = disconnectCause;
341 mHandler.obtainMessage(MSG_SET_DISCONNECTED, args).sendToTarget();
342 }
343
344 /** {@inheritDoc} */
345 @Override
346 public void setOnHold(String callId) {
Ihab Awad55a34282014-06-18 10:31:09 -0700347 logIncoming("setOnHold %s", callId);
Santos Cordon3d3b4052014-05-05 12:05:36 -0700348 mCallIdMapper.checkValidCallId(callId);
349 mHandler.obtainMessage(MSG_SET_ON_HOLD, callId).sendToTarget();
350 }
Ihab Awad50a57132014-05-28 16:49:38 -0700351
352 /** {@inheritDoc} */
353 @Override
354 public void setRequestingRingback(String callId, boolean ringback) {
Ihab Awad55a34282014-06-18 10:31:09 -0700355 logIncoming("setRequestingRingback %s %b", callId, ringback);
Ihab Awad50a57132014-05-28 16:49:38 -0700356 mCallIdMapper.checkValidCallId(callId);
357 SomeArgs args = SomeArgs.obtain();
358 args.arg1 = callId;
359 args.arg2 = ringback;
360 mHandler.obtainMessage(MSG_SET_REQUESTING_RINGBACK, args).sendToTarget();
361 }
Santos Cordon8f3282c2014-06-01 13:56:02 -0700362
363 /** ${inheritDoc} */
364 @Override
365 public void removeCall(String callId) {
Ihab Awad55a34282014-06-18 10:31:09 -0700366 logIncoming("removeCall %s", callId);
Santos Cordon8f3282c2014-06-01 13:56:02 -0700367 }
368
369 /** ${inheritDoc} */
370 @Override
Santos Cordona1610702014-06-04 20:22:56 -0700371 public void setCanConference(String callId, boolean canConference) {
Ihab Awad55a34282014-06-18 10:31:09 -0700372 logIncoming("setCanConference %s %b", callId, canConference);
Santos Cordona1610702014-06-04 20:22:56 -0700373 mHandler.obtainMessage(MSG_CAN_CONFERENCE, canConference ? 1 : 0, 0, callId)
374 .sendToTarget();
Santos Cordon8f3282c2014-06-01 13:56:02 -0700375 }
376
377 /** ${inheritDoc} */
378 @Override
Santos Cordona1610702014-06-04 20:22:56 -0700379 public void setIsConferenced(String callId, String conferenceCallId) {
Ihab Awad55a34282014-06-18 10:31:09 -0700380 logIncoming("setIsConferenced %s %s", callId, conferenceCallId);
Santos Cordona1610702014-06-04 20:22:56 -0700381 SomeArgs args = SomeArgs.obtain();
382 args.arg1 = callId;
383 args.arg2 = conferenceCallId;
384 mHandler.obtainMessage(MSG_SET_IS_CONFERENCED, args).sendToTarget();
385 }
386
387 /** ${InheritDoc} */
388 @Override
389 public void addConferenceCall(String callId, CallInfo callInfo) {
Ihab Awad55a34282014-06-18 10:31:09 -0700390 logIncoming("addConferenceCall %s %s", callId, callInfo);
Santos Cordona1610702014-06-04 20:22:56 -0700391 mCallIdMapper.checkValidCallId(callId);
392 SomeArgs args = SomeArgs.obtain();
393 args.arg1 = callId;
394 args.arg2 = callInfo;
395 mHandler.obtainMessage(MSG_ADD_CONFERENCE_CALL, args).sendToTarget();
Santos Cordon8f3282c2014-06-01 13:56:02 -0700396 }
Evan Charlton352105c2014-06-03 14:10:54 -0700397
398 @Override
399 public void onPostDialWait(String callId, String remaining) throws RemoteException {
Ihab Awad55a34282014-06-18 10:31:09 -0700400 logIncoming("onPostDialWait %s %s", callId, remaining);
Evan Charlton352105c2014-06-03 14:10:54 -0700401 mCallIdMapper.checkValidCallId(callId);
402 SomeArgs args = SomeArgs.obtain();
403 args.arg1 = callId;
404 args.arg2 = remaining;
405 mHandler.obtainMessage(MSG_ON_POST_DIAL_WAIT, args).sendToTarget();
406 }
Sailesh Nepal6098d2c2014-06-06 10:56:53 -0700407
408 /** {@inheritDoc} */
409 @Override
410 public void handoffCall(String callId) {
Ihab Awad55a34282014-06-18 10:31:09 -0700411 logIncoming("handoffCall %s", callId);
Sailesh Nepal6098d2c2014-06-06 10:56:53 -0700412 mCallIdMapper.checkValidCallId(callId);
413 mHandler.obtainMessage(MSG_HANDOFF_CALL, callId).sendToTarget();
414 }
Santos Cordon5924bea2014-06-18 06:39:51 -0700415
416 /** ${inheritDoc} */
417 @Override
418 public void queryRemoteConnectionServices(RemoteServiceCallback callback) {
419 logIncoming("queryRemoteCSs");
420 mHandler.obtainMessage(MSG_QUERY_REMOTE_CALL_SERVICES, callback).sendToTarget();
421 }
Santos Cordon3d3b4052014-05-05 12:05:36 -0700422 }
423
424 private final Adapter mAdapter = new Adapter();
425 private final CallsManager mCallsManager = CallsManager.getInstance();
Santos Cordona1610702014-06-04 20:22:56 -0700426 private final Set<Call> mPendingIncomingCalls = new HashSet<>();
427 private final Set<Call> mPendingConferenceCalls = new HashSet<>();
Ben Giladc5b22692014-02-18 20:03:22 -0800428 private final CallServiceDescriptor mDescriptor;
Santos Cordon3d3b4052014-05-05 12:05:36 -0700429 private final CallIdMapper mCallIdMapper = new CallIdMapper("CallService");
Santos Cordon3d3b4052014-05-05 12:05:36 -0700430 private final IncomingCallsManager mIncomingCallsManager;
Santos Cordon682fe6b2014-05-20 08:56:39 -0700431 private final Map<String, AsyncResultCallback<Boolean>> mPendingOutgoingCalls = new HashMap<>();
Santos Cordona1610702014-06-04 20:22:56 -0700432 private final Handler mHandler = new Handler();
Santos Cordonc195e362014-02-11 17:05:31 -0800433
Ben Gilad61925612014-03-11 19:06:36 -0700434 private Binder mBinder = new Binder();
Santos Cordon3d3b4052014-05-05 12:05:36 -0700435 private ICallService mServiceInterface;
Santos Cordon5924bea2014-06-18 06:39:51 -0700436 private final CallServiceRepository mCallServiceRepository;
Ben Gilad61925612014-03-11 19:06:36 -0700437
Santos Cordon63aeb162014-02-10 09:20:40 -0800438 /**
Sailesh Nepale59bb192014-04-01 18:33:59 -0700439 * Creates a call-service for the specified descriptor.
Santos Cordonc195e362014-02-11 17:05:31 -0800440 *
Santos Cordon61d0f702014-02-19 02:52:23 -0800441 * @param descriptor The call-service descriptor from
Santos Cordon3d3b4052014-05-05 12:05:36 -0700442 * {@link ICallServiceProvider#lookupCallServices}.
Sailesh Nepale59bb192014-04-01 18:33:59 -0700443 * @param incomingCallsManager Manages the incoming call initialization flow.
Santos Cordon5924bea2014-06-18 06:39:51 -0700444 * @param callServiceRepository Call service repository.
Santos Cordon63aeb162014-02-10 09:20:40 -0800445 */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700446 CallServiceWrapper(
447 CallServiceDescriptor descriptor,
Santos Cordon5924bea2014-06-18 06:39:51 -0700448 IncomingCallsManager incomingCallsManager,
449 CallServiceRepository callServiceRepository) {
Sailesh Nepala439e1b2014-03-11 18:19:58 -0700450 super(TelecommConstants.ACTION_CALL_SERVICE, descriptor.getServiceComponent());
Ben Giladc5b22692014-02-18 20:03:22 -0800451 mDescriptor = descriptor;
Santos Cordon3d3b4052014-05-05 12:05:36 -0700452 mIncomingCallsManager = incomingCallsManager;
Santos Cordon5924bea2014-06-18 06:39:51 -0700453 mCallServiceRepository = callServiceRepository;
Santos Cordon63aeb162014-02-10 09:20:40 -0800454 }
455
Ben Gilad61925612014-03-11 19:06:36 -0700456 CallServiceDescriptor getDescriptor() {
Ben Giladc5b22692014-02-18 20:03:22 -0800457 return mDescriptor;
Santos Cordonc195e362014-02-11 17:05:31 -0800458 }
459
Santos Cordon63aeb162014-02-10 09:20:40 -0800460 /** See {@link ICallService#setCallServiceAdapter}. */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700461 private void setCallServiceAdapter(ICallServiceAdapter callServiceAdapter) {
Santos Cordon61d0f702014-02-19 02:52:23 -0800462 if (isServiceValid("setCallServiceAdapter")) {
463 try {
Ihab Awad55a34282014-06-18 10:31:09 -0700464 logOutgoing("setCallServiceAdapter %s", callServiceAdapter);
Santos Cordon63aeb162014-02-10 09:20:40 -0800465 mServiceInterface.setCallServiceAdapter(callServiceAdapter);
Santos Cordon61d0f702014-02-19 02:52:23 -0800466 } catch (RemoteException e) {
Santos Cordon63aeb162014-02-10 09:20:40 -0800467 }
Santos Cordon63aeb162014-02-10 09:20:40 -0800468 }
469 }
470
Ben Gilad61925612014-03-11 19:06:36 -0700471 /**
Santos Cordon682fe6b2014-05-20 08:56:39 -0700472 * Attempts to place the specified call, see {@link ICallService#call}. Returns the result
473 * asynchronously through the specified callback.
Ben Gilad61925612014-03-11 19:06:36 -0700474 */
Santos Cordon682fe6b2014-05-20 08:56:39 -0700475 void call(final Call call, final AsyncResultCallback<Boolean> resultCallback) {
476 Log.d(this, "call(%s) via %s.", call, getComponentName());
Ben Gilad61925612014-03-11 19:06:36 -0700477 BindCallback callback = new BindCallback() {
Santos Cordon3d3b4052014-05-05 12:05:36 -0700478 @Override
479 public void onSuccess() {
Santos Cordon682fe6b2014-05-20 08:56:39 -0700480 String callId = mCallIdMapper.getCallId(call);
481 mPendingOutgoingCalls.put(callId, resultCallback);
482
483 try {
484 CallInfo callInfo = call.toCallInfo(callId);
Ihab Awad55a34282014-06-18 10:31:09 -0700485 logOutgoing("call %s", callInfo);
Santos Cordon682fe6b2014-05-20 08:56:39 -0700486 mServiceInterface.call(callInfo);
487 } catch (RemoteException e) {
Santos Cordon5924bea2014-06-18 06:39:51 -0700488 Log.e(this, e, "Failure to call -- %s", getDescriptor());
Ihab Awada3cb9e32014-06-03 18:45:05 -0700489 mPendingOutgoingCalls.remove(callId).onResult(
490 false, DisconnectCause.ERROR_UNSPECIFIED, e.toString());
Ben Gilad61925612014-03-11 19:06:36 -0700491 }
Santos Cordon63aeb162014-02-10 09:20:40 -0800492 }
Santos Cordon3d3b4052014-05-05 12:05:36 -0700493
494 @Override
495 public void onFailure() {
Santos Cordon5924bea2014-06-18 06:39:51 -0700496 Log.e(this, new Exception(), "Failure to call %s", getDescriptor());
Ihab Awada3cb9e32014-06-03 18:45:05 -0700497 resultCallback.onResult(false, DisconnectCause.ERROR_UNSPECIFIED, null);
Ben Gilad61925612014-03-11 19:06:36 -0700498 }
499 };
500
501 mBinder.bind(callback);
Santos Cordon63aeb162014-02-10 09:20:40 -0800502 }
503
Ihab Awad74549ec2014-03-10 15:33:25 -0700504 /** @see CallService#abort(String) */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700505 void abort(Call call) {
Santos Cordon682fe6b2014-05-20 08:56:39 -0700506 // Clear out any pending outgoing call data
507 String callId = mCallIdMapper.getCallId(call);
508
509 // If still bound, tell the call service to abort.
Ben Gilad28e8ad62014-03-06 17:01:54 -0800510 if (isServiceValid("abort")) {
511 try {
Ihab Awad55a34282014-06-18 10:31:09 -0700512 logOutgoing("abort %s", callId);
Santos Cordon682fe6b2014-05-20 08:56:39 -0700513 mServiceInterface.abort(callId);
Ben Gilad28e8ad62014-03-06 17:01:54 -0800514 } catch (RemoteException e) {
Santos Cordon63aeb162014-02-10 09:20:40 -0800515 }
Santos Cordon61d0f702014-02-19 02:52:23 -0800516 }
Santos Cordon682fe6b2014-05-20 08:56:39 -0700517
518 removeCall(call);
Santos Cordon61d0f702014-02-19 02:52:23 -0800519 }
520
Ihab Awad74549ec2014-03-10 15:33:25 -0700521 /** @see CallService#hold(String) */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700522 void hold(Call call) {
Yorke Leecdf3ebd2014-03-12 18:31:41 -0700523 if (isServiceValid("hold")) {
524 try {
Ihab Awad55a34282014-06-18 10:31:09 -0700525 logOutgoing("hold %s", mCallIdMapper.getCallId(call));
Sailesh Nepale59bb192014-04-01 18:33:59 -0700526 mServiceInterface.hold(mCallIdMapper.getCallId(call));
Yorke Leecdf3ebd2014-03-12 18:31:41 -0700527 } catch (RemoteException e) {
Yorke Leecdf3ebd2014-03-12 18:31:41 -0700528 }
529 }
530 }
531
Ihab Awad74549ec2014-03-10 15:33:25 -0700532 /** @see CallService#unhold(String) */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700533 void unhold(Call call) {
Yorke Leecdf3ebd2014-03-12 18:31:41 -0700534 if (isServiceValid("unhold")) {
535 try {
Ihab Awad55a34282014-06-18 10:31:09 -0700536 logOutgoing("unhold %s", mCallIdMapper.getCallId(call));
Sailesh Nepale59bb192014-04-01 18:33:59 -0700537 mServiceInterface.unhold(mCallIdMapper.getCallId(call));
Yorke Leecdf3ebd2014-03-12 18:31:41 -0700538 } catch (RemoteException e) {
Yorke Leecdf3ebd2014-03-12 18:31:41 -0700539 }
540 }
541 }
542
Ihab Awad74549ec2014-03-10 15:33:25 -0700543 /** @see CallService#onAudioStateChanged(String,CallAudioState) */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700544 void onAudioStateChanged(Call activeCall, CallAudioState audioState) {
Sailesh Nepal6aca10a2014-03-24 16:11:02 -0700545 if (isServiceValid("onAudioStateChanged")) {
546 try {
Ihab Awad55a34282014-06-18 10:31:09 -0700547 logOutgoing("onAudioStateChanged %s %s",
548 mCallIdMapper.getCallId(activeCall), audioState);
Sailesh Nepale59bb192014-04-01 18:33:59 -0700549 mServiceInterface.onAudioStateChanged(mCallIdMapper.getCallId(activeCall),
550 audioState);
Sailesh Nepal6aca10a2014-03-24 16:11:02 -0700551 } catch (RemoteException e) {
Sailesh Nepal6aca10a2014-03-24 16:11:02 -0700552 }
553 }
554 }
555
Ben Gilad61925612014-03-11 19:06:36 -0700556 /**
557 * Starts retrieval of details for an incoming call. Details are returned through the
558 * call-service adapter using the specified call ID. Upon failure, the specified error callback
Santos Cordon3d3b4052014-05-05 12:05:36 -0700559 * is invoked. Can be invoked even when the call service is unbound. See
560 * {@link ICallService#setIncomingCallId}.
Ben Gilad61925612014-03-11 19:06:36 -0700561 *
Sailesh Nepale59bb192014-04-01 18:33:59 -0700562 * @param call The call used for the incoming call.
Ben Gilad61925612014-03-11 19:06:36 -0700563 * @param extras The {@link CallService}-provided extras which need to be sent back.
564 * @param errorCallback The callback to invoke upon failure.
565 */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700566 void setIncomingCallId(final Call call, final Bundle extras, final Runnable errorCallback) {
567 Log.d(this, "setIncomingCall(%s) via %s.", call, getComponentName());
Ben Gilad61925612014-03-11 19:06:36 -0700568 BindCallback callback = new BindCallback() {
Santos Cordon3d3b4052014-05-05 12:05:36 -0700569 @Override
570 public void onSuccess() {
Ben Gilad61925612014-03-11 19:06:36 -0700571 if (isServiceValid("setIncomingCallId")) {
Santos Cordon682fe6b2014-05-20 08:56:39 -0700572 mPendingIncomingCalls.add(call);
Ben Gilad61925612014-03-11 19:06:36 -0700573 try {
Ihab Awad55a34282014-06-18 10:31:09 -0700574 logOutgoing("setIncomingCallId %s %s",
575 mCallIdMapper.getCallId(call), extras);
Sailesh Nepale59bb192014-04-01 18:33:59 -0700576 mServiceInterface.setIncomingCallId(mCallIdMapper.getCallId(call),
577 extras);
Ben Gilad61925612014-03-11 19:06:36 -0700578 } catch (RemoteException e) {
Ben Gilad61925612014-03-11 19:06:36 -0700579 }
580 }
Santos Cordon61d0f702014-02-19 02:52:23 -0800581 }
Santos Cordon3d3b4052014-05-05 12:05:36 -0700582
583 @Override
584 public void onFailure() {
Ben Gilad61925612014-03-11 19:06:36 -0700585 errorCallback.run();
586 }
587 };
588
589 mBinder.bind(callback);
Santos Cordon63aeb162014-02-10 09:20:40 -0800590 }
591
Ihab Awad74549ec2014-03-10 15:33:25 -0700592 /** @see CallService#disconnect(String) */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700593 void disconnect(Call call) {
Santos Cordon61d0f702014-02-19 02:52:23 -0800594 if (isServiceValid("disconnect")) {
595 try {
Ihab Awad55a34282014-06-18 10:31:09 -0700596 logOutgoing("disconnect %s", mCallIdMapper.getCallId(call));
Sailesh Nepale59bb192014-04-01 18:33:59 -0700597 mServiceInterface.disconnect(mCallIdMapper.getCallId(call));
Santos Cordon61d0f702014-02-19 02:52:23 -0800598 } catch (RemoteException e) {
Santos Cordon63aeb162014-02-10 09:20:40 -0800599 }
Santos Cordon63aeb162014-02-10 09:20:40 -0800600 }
601 }
Santos Cordon5c12c6e2014-02-13 14:35:31 -0800602
Ihab Awad74549ec2014-03-10 15:33:25 -0700603 /** @see CallService#answer(String) */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700604 void answer(Call call) {
Santos Cordon61d0f702014-02-19 02:52:23 -0800605 if (isServiceValid("answer")) {
606 try {
Ihab Awad55a34282014-06-18 10:31:09 -0700607 logOutgoing("answer %s", mCallIdMapper.getCallId(call));
Sailesh Nepale59bb192014-04-01 18:33:59 -0700608 mServiceInterface.answer(mCallIdMapper.getCallId(call));
Santos Cordon61d0f702014-02-19 02:52:23 -0800609 } catch (RemoteException e) {
Santos Cordon7917d382014-02-14 02:31:18 -0800610 }
Santos Cordon61d0f702014-02-19 02:52:23 -0800611 }
612 }
613
Ihab Awad74549ec2014-03-10 15:33:25 -0700614 /** @see CallService#reject(String) */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700615 void reject(Call call) {
Santos Cordon61d0f702014-02-19 02:52:23 -0800616 if (isServiceValid("reject")) {
617 try {
Ihab Awad55a34282014-06-18 10:31:09 -0700618 logOutgoing("reject %s", mCallIdMapper.getCallId(call));
Sailesh Nepale59bb192014-04-01 18:33:59 -0700619 mServiceInterface.reject(mCallIdMapper.getCallId(call));
Santos Cordon61d0f702014-02-19 02:52:23 -0800620 } catch (RemoteException e) {
Ihab Awad74549ec2014-03-10 15:33:25 -0700621 }
622 }
623 }
624
625 /** @see CallService#playDtmfTone(String,char) */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700626 void playDtmfTone(Call call, char digit) {
Ihab Awad74549ec2014-03-10 15:33:25 -0700627 if (isServiceValid("playDtmfTone")) {
628 try {
Ihab Awad55a34282014-06-18 10:31:09 -0700629 logOutgoing("playDtmfTone %s %c", mCallIdMapper.getCallId(call), digit);
Sailesh Nepale59bb192014-04-01 18:33:59 -0700630 mServiceInterface.playDtmfTone(mCallIdMapper.getCallId(call), digit);
Ihab Awad74549ec2014-03-10 15:33:25 -0700631 } catch (RemoteException e) {
Ihab Awad74549ec2014-03-10 15:33:25 -0700632 }
633 }
634 }
635
636 /** @see CallService#stopDtmfTone(String) */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700637 void stopDtmfTone(Call call) {
Ihab Awad74549ec2014-03-10 15:33:25 -0700638 if (isServiceValid("stopDtmfTone")) {
639 try {
Ihab Awad55a34282014-06-18 10:31:09 -0700640 logOutgoing("stopDtmfTone %s", mCallIdMapper.getCallId(call));
Sailesh Nepale59bb192014-04-01 18:33:59 -0700641 mServiceInterface.stopDtmfTone(mCallIdMapper.getCallId(call));
Ihab Awad74549ec2014-03-10 15:33:25 -0700642 } catch (RemoteException e) {
Santos Cordon61d0f702014-02-19 02:52:23 -0800643 }
Santos Cordon7917d382014-02-14 02:31:18 -0800644 }
645 }
646
Sailesh Nepale59bb192014-04-01 18:33:59 -0700647 void addCall(Call call) {
Santos Cordona1610702014-06-04 20:22:56 -0700648 if (mCallIdMapper.getCallId(call) == null) {
649 mCallIdMapper.addCall(call);
650 }
Santos Cordon7917d382014-02-14 02:31:18 -0800651 }
652
Sailesh Nepal0e5410a2014-04-04 01:20:58 -0700653 /**
654 * Associates newCall with this call service by replacing callToReplace.
655 */
656 void replaceCall(Call newCall, Call callToReplace) {
657 Preconditions.checkState(callToReplace.getCallService() == this);
658 mCallIdMapper.replaceCall(newCall, callToReplace);
659 }
660
Sailesh Nepale59bb192014-04-01 18:33:59 -0700661 void removeCall(Call call) {
Santos Cordon682fe6b2014-05-20 08:56:39 -0700662 mPendingIncomingCalls.remove(call);
663
664 AsyncResultCallback<Boolean> outgoingResultCallback =
665 mPendingOutgoingCalls.remove(mCallIdMapper.getCallId(call));
666 if (outgoingResultCallback != null) {
Ihab Awada3cb9e32014-06-03 18:45:05 -0700667 outgoingResultCallback.onResult(false, DisconnectCause.ERROR_UNSPECIFIED, null);
Santos Cordon682fe6b2014-05-20 08:56:39 -0700668 }
669
Sailesh Nepale59bb192014-04-01 18:33:59 -0700670 mCallIdMapper.removeCall(call);
Yorke Leeadee12d2014-03-13 12:08:30 -0700671 }
672
Evan Charlton352105c2014-06-03 14:10:54 -0700673 void onPostDialContinue(Call call, boolean proceed) {
674 if (isServiceValid("onPostDialContinue")) {
675 try {
Ihab Awad55a34282014-06-18 10:31:09 -0700676 logOutgoing("onPostDialContinue %s %b", mCallIdMapper.getCallId(call), proceed);
Evan Charlton352105c2014-06-03 14:10:54 -0700677 mServiceInterface.onPostDialContinue(mCallIdMapper.getCallId(call), proceed);
678 } catch (RemoteException ignored) {
679 }
680 }
681 }
682
Santos Cordona1610702014-06-04 20:22:56 -0700683 void conference(final Call conferenceCall, Call call) {
684 if (isServiceValid("conference")) {
685 try {
686 conferenceCall.setCallService(this);
687 mPendingConferenceCalls.add(conferenceCall);
688 mHandler.postDelayed(new Runnable() {
689 @Override public void run() {
690 if (mPendingConferenceCalls.remove(conferenceCall)) {
691 conferenceCall.expireConference();
692 Log.i(this, "Conference call expired: %s", conferenceCall);
693 }
694 }
695 }, Timeouts.getConferenceCallExpireMillis());
696
Ihab Awad55a34282014-06-18 10:31:09 -0700697 logOutgoing("conference %s %s",
698 mCallIdMapper.getCallId(conferenceCall),
699 mCallIdMapper.getCallId(call));
Santos Cordona1610702014-06-04 20:22:56 -0700700 mServiceInterface.conference(
701 mCallIdMapper.getCallId(conferenceCall),
702 mCallIdMapper.getCallId(call));
703 } catch (RemoteException ignored) {
704 }
705 }
706 }
707
708 void splitFromConference(Call call) {
709 if (isServiceValid("splitFromConference")) {
710 try {
Ihab Awad55a34282014-06-18 10:31:09 -0700711 logOutgoing("splitFromConference %s", mCallIdMapper.getCallId(call));
Santos Cordona1610702014-06-04 20:22:56 -0700712 mServiceInterface.splitFromConference(mCallIdMapper.getCallId(call));
713 } catch (RemoteException ignored) {
714 }
715 }
716 }
717
Santos Cordon5c12c6e2014-02-13 14:35:31 -0800718 /** {@inheritDoc} */
Santos Cordon3d3b4052014-05-05 12:05:36 -0700719 @Override
720 protected void setServiceInterface(IBinder binder) {
Santos Cordon4b2c1192014-03-19 18:15:38 -0700721 if (binder == null) {
722 // We have lost our service connection. Notify the world that this call service is done.
723 // We must notify the adapter before CallsManager. The adapter will force any pending
724 // outgoing calls to try the next call service. This needs to happen before CallsManager
725 // tries to clean up any calls still associated with this call service.
Santos Cordon3d3b4052014-05-05 12:05:36 -0700726 handleCallServiceDeath();
Santos Cordon4b2c1192014-03-19 18:15:38 -0700727 CallsManager.getInstance().handleCallServiceDeath(this);
728 mServiceInterface = null;
729 } else {
730 mServiceInterface = ICallService.Stub.asInterface(binder);
731 setCallServiceAdapter(mAdapter);
732 }
Santos Cordon5c12c6e2014-02-13 14:35:31 -0800733 }
Santos Cordon3d3b4052014-05-05 12:05:36 -0700734
735 /**
736 * Called when the associated call service dies.
737 */
738 private void handleCallServiceDeath() {
Santos Cordon682fe6b2014-05-20 08:56:39 -0700739 if (!mPendingOutgoingCalls.isEmpty()) {
740 for (AsyncResultCallback<Boolean> callback : mPendingOutgoingCalls.values()) {
Ihab Awada3cb9e32014-06-03 18:45:05 -0700741 callback.onResult(false, DisconnectCause.ERROR_UNSPECIFIED, null);
Santos Cordon682fe6b2014-05-20 08:56:39 -0700742 }
743 mPendingOutgoingCalls.clear();
744 }
745
746 if (!mPendingIncomingCalls.isEmpty()) {
Santos Cordon3d3b4052014-05-05 12:05:36 -0700747 // Iterate through a copy because the code inside the loop will modify the original
748 // list.
Santos Cordon682fe6b2014-05-20 08:56:39 -0700749 for (Call call : ImmutableList.copyOf(mPendingIncomingCalls)) {
750 Preconditions.checkState(call.isIncoming());
751 mIncomingCallsManager.handleFailedIncomingCall(call);
Santos Cordon3d3b4052014-05-05 12:05:36 -0700752 }
753
Santos Cordona1610702014-06-04 20:22:56 -0700754 if (!mPendingIncomingCalls.isEmpty()) {
755 Log.wtf(this, "Pending calls did not get cleared.");
756 mPendingIncomingCalls.clear();
757 }
758 }
Santos Cordon8f3282c2014-06-01 13:56:02 -0700759
Santos Cordona1610702014-06-04 20:22:56 -0700760 mCallIdMapper.clear();
761 }
Ihab Awad55a34282014-06-18 10:31:09 -0700762
763 private void logIncoming(String msg, Object... params) {
764 Log.d(this, "CallService -> Telecomm: " + msg, params);
765 }
766
767 private void logOutgoing(String msg, Object... params) {
768 Log.d(this, "Telecomm -> CallService: " + msg, params);
769 }
Santos Cordon5924bea2014-06-18 06:39:51 -0700770
771 private void queryRemoteConnectionServices(final RemoteServiceCallback callback) {
772 final List<IBinder> callServices = new ArrayList<>();
773 final List<ComponentName> components = new ArrayList<>();
774
775 mCallServiceRepository.lookupServices(new LookupCallback<CallServiceWrapper>() {
776 private int mRemainingResponses;
777
778 /** ${inheritDoc} */
779 @Override
780 public void onComplete(Collection<CallServiceWrapper> services) {
781 mRemainingResponses = services.size() - 1;
782 for (CallServiceWrapper cs : services) {
783 if (cs != CallServiceWrapper.this) {
784 final CallServiceWrapper currentCallService = cs;
785 cs.mBinder.bind(new BindCallback() {
786 @Override
787 public void onSuccess() {
788 Log.d(this, "Adding ***** %s", currentCallService.getDescriptor());
789 callServices.add(currentCallService.mServiceInterface.asBinder());
790 components.add(currentCallService.getComponentName());
791 maybeComplete();
792 }
793
794 @Override
795 public void onFailure() {
796 // add null so that we always add up to totalExpected even if
797 // some of the call services fail to bind.
798 maybeComplete();
799 }
800
801 private void maybeComplete() {
802 if (--mRemainingResponses == 0) {
803 try {
804 callback.onResult(components, callServices);
805 } catch (RemoteException ignored) {
806 }
807 }
808 }
809 });
810 }
811 }
812 }
813 });
814 }
Santos Cordon63aeb162014-02-10 09:20:40 -0800815}