blob: 39de235088873681e9b4a216e2da55e0efe52caa [file] [log] [blame]
Santos Cordon681663d2014-01-30 04:32:15 -08001/*
2 * Copyright (C) 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
Ben Gilad9f2bed32013-12-12 17:43:26 -080017package com.android.telecomm;
18
Santos Cordon681663d2014-01-30 04:32:15 -080019import android.os.Handler;
Sailesh Nepal10ea4602014-04-01 17:23:32 -070020import android.os.Message;
Santos Cordon681663d2014-01-30 04:32:15 -080021import android.telecomm.CallInfo;
Santos Cordon681663d2014-01-30 04:32:15 -080022
Sailesh Nepala439e1b2014-03-11 18:19:58 -070023import com.android.internal.telecomm.ICallServiceAdapter;
Santos Cordon7917d382014-02-14 02:31:18 -080024import com.google.android.collect.Sets;
Santos Cordon681663d2014-01-30 04:32:15 -080025import com.google.common.base.Strings;
Santos Cordon4b2c1192014-03-19 18:15:38 -070026import com.google.common.collect.ImmutableList;
Sailesh Nepal10ea4602014-04-01 17:23:32 -070027import com.android.internal.os.SomeArgs;
Santos Cordon681663d2014-01-30 04:32:15 -080028
Santos Cordon7917d382014-02-14 02:31:18 -080029import java.util.Set;
30
Ben Gilad9f2bed32013-12-12 17:43:26 -080031/**
Sailesh Nepale59bb192014-04-01 18:33:59 -070032 * Used by call services to communicate with Telecomm. Each call service is given its own instance
33 * of the adapter for the lifetmie of the binding.
Santos Cordon63aeb162014-02-10 09:20:40 -080034 * TODO(santoscordon): Do we need Binder.clear/restoreCallingIdentity() in the service methods?
Ben Gilad9f2bed32013-12-12 17:43:26 -080035 */
Santos Cordon681663d2014-01-30 04:32:15 -080036public final class CallServiceAdapter extends ICallServiceAdapter.Stub {
Sailesh Nepal10ea4602014-04-01 17:23:32 -070037 private static final int MSG_SET_IS_COMPATIBLE_WITH = 0;
38 private static final int MSG_NOTIFY_INCOMING_CALL = 1;
39 private static final int MSG_HANDLE_SUCCESSFUL_OUTGOING_CALL = 2;
40 private static final int MSG_HANDLE_FAILED_OUTGOING_CALL = 3;
41 private static final int MSG_SET_ACTIVE = 4;
42 private static final int MSG_SET_RINGING = 5;
43 private static final int MSG_SET_DIALING = 6;
44 private static final int MSG_SET_DISCONNECTED = 7;
45 private static final int MSG_SET_ON_HOLD = 8;
46
47 private final class CallServiceAdapterHandler extends Handler {
48 @Override
49 public void handleMessage(Message msg) {
Sailesh Nepale59bb192014-04-01 18:33:59 -070050 Call call;
Sailesh Nepal10ea4602014-04-01 17:23:32 -070051 switch (msg.what) {
52 case MSG_SET_IS_COMPATIBLE_WITH:
Sailesh Nepale59bb192014-04-01 18:33:59 -070053 call = mCallIdMapper.getCall(msg.obj);
54 if (call != null && !call.isIncoming()) {
55 mOutgoingCallsManager.setIsCompatibleWith(call,
Sailesh Nepal10ea4602014-04-01 17:23:32 -070056 msg.arg1 == 1 ? true : false);
57 } else {
Sailesh Nepal84fa5f82014-04-02 11:01:11 -070058 Log.w(this, "setIsCompatibleWith, unknown call: %s, id: %s", call, msg.obj);
Sailesh Nepal10ea4602014-04-01 17:23:32 -070059 }
60 break;
61 case MSG_NOTIFY_INCOMING_CALL:
Sailesh Nepale59bb192014-04-01 18:33:59 -070062 CallInfo clientCallInfo = (CallInfo) msg.obj;
63 call = mCallIdMapper.getCall(clientCallInfo.getId());
64 if (call != null && mPendingCalls.remove(call) && call.isIncoming()) {
65 CallInfo callInfo = new CallInfo(null, clientCallInfo.getState(),
66 clientCallInfo.getHandle());
67 mIncomingCallsManager.handleSuccessfulIncomingCall(call, callInfo);
Sailesh Nepal10ea4602014-04-01 17:23:32 -070068 } else {
Sailesh Nepal84fa5f82014-04-02 11:01:11 -070069 Log.w(this, "notifyIncomingCall, unknown incoming call: %s, id: %s", call,
Sailesh Nepal6ab6fb72014-04-01 20:03:19 -070070 clientCallInfo.getId());
Sailesh Nepal10ea4602014-04-01 17:23:32 -070071 }
72 break;
73 case MSG_HANDLE_SUCCESSFUL_OUTGOING_CALL:
Sailesh Nepale59bb192014-04-01 18:33:59 -070074 call = mCallIdMapper.getCall(msg.obj);
75 if (call != null && mPendingCalls.remove(call) && !call.isIncoming()) {
76 mOutgoingCallsManager.handleSuccessfulCallAttempt(call);
Sailesh Nepal10ea4602014-04-01 17:23:32 -070077 } else {
78 // TODO(gilad): Figure out how to wire up the callService.abort() call.
Sailesh Nepal84fa5f82014-04-02 11:01:11 -070079 Log.w(this,
80 "handleSuccessfulOutgoingCall, unknown outgoing call: %s, id: %s",
81 call, msg.obj);
Sailesh Nepal10ea4602014-04-01 17:23:32 -070082 }
83 break;
84 case MSG_HANDLE_FAILED_OUTGOING_CALL: {
85 SomeArgs args = (SomeArgs) msg.obj;
86 try {
Sailesh Nepale59bb192014-04-01 18:33:59 -070087 call = mCallIdMapper.getCall(args.arg1);
Sailesh Nepal10ea4602014-04-01 17:23:32 -070088 String reason = (String) args.arg2;
Sailesh Nepale59bb192014-04-01 18:33:59 -070089 if (call != null && mPendingCalls.remove(call) && !call.isIncoming()) {
90 mOutgoingCallsManager.handleFailedCallAttempt(call, reason);
Sailesh Nepal10ea4602014-04-01 17:23:32 -070091 } else {
Sailesh Nepal84fa5f82014-04-02 11:01:11 -070092 Log.w(this,
93 "handleFailedOutgoingCall, unknown outgoing call: %s, id: %s",
94 call, args.arg1);
Sailesh Nepal10ea4602014-04-01 17:23:32 -070095 }
96 } finally {
97 args.recycle();
98 }
99 break;
100 }
101 case MSG_SET_ACTIVE:
Sailesh Nepale59bb192014-04-01 18:33:59 -0700102 call = mCallIdMapper.getCall(msg.obj);
103 if (call != null) {
104 mCallsManager.markCallAsActive(call);
105 } else {
Sailesh Nepal84fa5f82014-04-02 11:01:11 -0700106 Log.w(this, "setActive, unknown call id: %s", msg.obj);
Sailesh Nepale59bb192014-04-01 18:33:59 -0700107 }
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700108 break;
109 case MSG_SET_RINGING:
Sailesh Nepale59bb192014-04-01 18:33:59 -0700110 call = mCallIdMapper.getCall(msg.obj);
111 if (call != null) {
112 mCallsManager.markCallAsRinging(call);
113 } else {
Sailesh Nepal84fa5f82014-04-02 11:01:11 -0700114 Log.w(this, "setRinging, unknown call id: %s", msg.obj);
Sailesh Nepale59bb192014-04-01 18:33:59 -0700115 }
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700116 break;
117 case MSG_SET_DIALING:
Sailesh Nepale59bb192014-04-01 18:33:59 -0700118 call = mCallIdMapper.getCall(msg.obj);
119 if (call != null) {
120 mCallsManager.markCallAsDialing(call);
121 } else {
Sailesh Nepal84fa5f82014-04-02 11:01:11 -0700122 Log.w(this, "setDialing, unknown call id: %s", msg.obj);
Sailesh Nepale59bb192014-04-01 18:33:59 -0700123 }
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700124 break;
125 case MSG_SET_DISCONNECTED: {
126 SomeArgs args = (SomeArgs) msg.obj;
127 try {
Sailesh Nepale59bb192014-04-01 18:33:59 -0700128 call = mCallIdMapper.getCall(args.arg1);
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700129 String disconnectMessage = (String) args.arg2;
130 int disconnectCause = args.argi1;
Sailesh Nepale59bb192014-04-01 18:33:59 -0700131 if (call != null) {
132 mCallsManager.markCallAsDisconnected(call, disconnectCause,
133 disconnectMessage);
134 } else {
Sailesh Nepal84fa5f82014-04-02 11:01:11 -0700135 Log.w(this, "setDisconnected, unknown call id: %s", args.arg1);
Sailesh Nepale59bb192014-04-01 18:33:59 -0700136 }
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700137 } finally {
138 args.recycle();
139 }
140 break;
141 }
142 case MSG_SET_ON_HOLD:
Sailesh Nepale59bb192014-04-01 18:33:59 -0700143 call = mCallIdMapper.getCall(msg.obj);
144 if (call != null) {
145 mCallsManager.markCallAsOnHold(call);
146 } else {
Sailesh Nepal84fa5f82014-04-02 11:01:11 -0700147 Log.w(this, "setOnHold, unknown call id: %s", msg.obj);
Sailesh Nepale59bb192014-04-01 18:33:59 -0700148 }
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700149 break;
150 }
151 }
152 }
153
Santos Cordon681663d2014-01-30 04:32:15 -0800154 private final CallsManager mCallsManager;
Santos Cordon681663d2014-01-30 04:32:15 -0800155 private final OutgoingCallsManager mOutgoingCallsManager;
Santos Cordon493e8f22014-02-19 03:15:12 -0800156 private final IncomingCallsManager mIncomingCallsManager;
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700157 private final Handler mHandler = new CallServiceAdapterHandler();
Sailesh Nepale59bb192014-04-01 18:33:59 -0700158 private final CallIdMapper mCallIdMapper;
159 private final Set<Call> mPendingCalls = Sets.newHashSet();
Santos Cordon7917d382014-02-14 02:31:18 -0800160
Santos Cordon681663d2014-01-30 04:32:15 -0800161 /**
162 * Persists the specified parameters.
Santos Cordon493e8f22014-02-19 03:15:12 -0800163 *
164 * @param outgoingCallsManager Manages the placing of outgoing calls.
165 * @param incomingCallsManager Manages the incoming call initialization flow.
Santos Cordon681663d2014-01-30 04:32:15 -0800166 */
Santos Cordon493e8f22014-02-19 03:15:12 -0800167 CallServiceAdapter(
Sailesh Nepale59bb192014-04-01 18:33:59 -0700168 OutgoingCallsManager outgoingCallsManager,
169 IncomingCallsManager incomingCallsManager,
170 CallIdMapper callIdMapper) {
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700171 ThreadUtil.checkOnMainThread();
Santos Cordon681663d2014-01-30 04:32:15 -0800172 mCallsManager = CallsManager.getInstance();
173 mOutgoingCallsManager = outgoingCallsManager;
Santos Cordon493e8f22014-02-19 03:15:12 -0800174 mIncomingCallsManager = incomingCallsManager;
Sailesh Nepale59bb192014-04-01 18:33:59 -0700175 mCallIdMapper = callIdMapper;
Santos Cordon681663d2014-01-30 04:32:15 -0800176 }
177
178 /** {@inheritDoc} */
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700179 @Override
180 public void setIsCompatibleWith(String callId, boolean isCompatible) {
Evan Charlton0ebf8402014-04-02 16:26:15 -0700181 Log.v(this, "setIsCompatibleWith id: %s, isCompatible: %b", callId, isCompatible);
Sailesh Nepale59bb192014-04-01 18:33:59 -0700182 mCallIdMapper.checkValidCallId(callId);
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700183 mHandler.obtainMessage(MSG_SET_IS_COMPATIBLE_WITH, isCompatible ? 1 : 0, 0, callId).
184 sendToTarget();
Santos Cordon681663d2014-01-30 04:32:15 -0800185 }
186
Santos Cordon7917d382014-02-14 02:31:18 -0800187 /** {@inheritDoc} */
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700188 @Override
189 public void notifyIncomingCall(CallInfo callInfo) {
Sailesh Nepale59bb192014-04-01 18:33:59 -0700190 mCallIdMapper.checkValidCallId(callInfo.getId());
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700191 mHandler.obtainMessage(MSG_NOTIFY_INCOMING_CALL, callInfo).sendToTarget();
Santos Cordon681663d2014-01-30 04:32:15 -0800192 }
193
194 /** {@inheritDoc} */
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700195 @Override
196 public void handleSuccessfulOutgoingCall(String callId) {
Sailesh Nepale59bb192014-04-01 18:33:59 -0700197 mCallIdMapper.checkValidCallId(callId);
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700198 mHandler.obtainMessage(MSG_HANDLE_SUCCESSFUL_OUTGOING_CALL, callId).sendToTarget();
Santos Cordon681663d2014-01-30 04:32:15 -0800199 }
200
201 /** {@inheritDoc} */
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700202 @Override
203 public void handleFailedOutgoingCall(String callId, String reason) {
Sailesh Nepale59bb192014-04-01 18:33:59 -0700204 mCallIdMapper.checkValidCallId(callId);
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700205 SomeArgs args = SomeArgs.obtain();
206 args.arg1 = callId;
207 args.arg2 = reason;
208 mHandler.obtainMessage(MSG_HANDLE_FAILED_OUTGOING_CALL, args).sendToTarget();
Santos Cordon681663d2014-01-30 04:32:15 -0800209 }
210
211 /** {@inheritDoc} */
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700212 @Override
213 public void setActive(String callId) {
Sailesh Nepale59bb192014-04-01 18:33:59 -0700214 mCallIdMapper.checkValidCallId(callId);
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700215 mHandler.obtainMessage(MSG_SET_ACTIVE, callId).sendToTarget();
Santos Cordon681663d2014-01-30 04:32:15 -0800216 }
217
218 /** {@inheritDoc} */
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700219 @Override
220 public void setRinging(String callId) {
Sailesh Nepale59bb192014-04-01 18:33:59 -0700221 mCallIdMapper.checkValidCallId(callId);
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700222 mHandler.obtainMessage(MSG_SET_RINGING, callId).sendToTarget();
Santos Cordon681663d2014-01-30 04:32:15 -0800223 }
224
225 /** {@inheritDoc} */
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700226 @Override
227 public void setDialing(String callId) {
Sailesh Nepale59bb192014-04-01 18:33:59 -0700228 mCallIdMapper.checkValidCallId(callId);
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700229 mHandler.obtainMessage(MSG_SET_DIALING, callId).sendToTarget();
Santos Cordon681663d2014-01-30 04:32:15 -0800230 }
231
232 /** {@inheritDoc} */
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700233 @Override
234 public void setDisconnected(
235 String callId, int disconnectCause, String disconnectMessage) {
Sailesh Nepale59bb192014-04-01 18:33:59 -0700236 mCallIdMapper.checkValidCallId(callId);
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700237 SomeArgs args = SomeArgs.obtain();
238 args.arg1 = callId;
239 args.arg2 = disconnectMessage;
240 args.argi1 = disconnectCause;
241 mHandler.obtainMessage(MSG_SET_DISCONNECTED, args).sendToTarget();
Santos Cordon681663d2014-01-30 04:32:15 -0800242 }
243
Yorke Leecdf3ebd2014-03-12 18:31:41 -0700244 /** {@inheritDoc} */
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700245 @Override
246 public void setOnHold(String callId) {
Sailesh Nepale59bb192014-04-01 18:33:59 -0700247 mCallIdMapper.checkValidCallId(callId);
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700248 mHandler.obtainMessage(MSG_SET_ON_HOLD, callId).sendToTarget();
Yorke Leecdf3ebd2014-03-12 18:31:41 -0700249 }
250
Santos Cordon681663d2014-01-30 04:32:15 -0800251 /**
Sailesh Nepale59bb192014-04-01 18:33:59 -0700252 * Adds the specified call to the list of pending calls. Only calls in this list which are
253 * outgoing will be handled by {@link #isCompatibleWith}, {@link handleSuccessfulOutgoingCall},
254 * and {@link handleFailedOutgoingCall}. Similarly, only calls in this list which are incoming
255 * will be handled by {@link notifyIncomingCall}.
Ben Gilad28e8ad62014-03-06 17:01:54 -0800256 */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700257 void addPendingCall(Call call) {
258 mPendingCalls.add(call);
Ben Gilad28e8ad62014-03-06 17:01:54 -0800259 }
260
261 /**
Sailesh Nepale59bb192014-04-01 18:33:59 -0700262 * Removes the specified call from the list of pending calls.
Ben Gilad28e8ad62014-03-06 17:01:54 -0800263 */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700264 void removePendingCall(Call call) {
265 mPendingCalls.remove(call);
Santos Cordon7917d382014-02-14 02:31:18 -0800266 }
267
268 /**
Santos Cordon4b2c1192014-03-19 18:15:38 -0700269 * Called when the associated call service dies.
270 */
271 void handleCallServiceDeath() {
Sailesh Nepale59bb192014-04-01 18:33:59 -0700272 if (!mPendingCalls.isEmpty()) {
273 // Iterate through a copy because the code inside the loop will modify the original
274 // list.
275 for (Call call : ImmutableList.copyOf(mPendingCalls)) {
276 if (call.isIncoming()) {
277 mIncomingCallsManager.handleFailedIncomingCall(call);
278 } else {
279 mOutgoingCallsManager.handleFailedCallAttempt(call,
280 "Call service disconnected.");
281 }
Santos Cordon4b2c1192014-03-19 18:15:38 -0700282 }
283
Sailesh Nepale59bb192014-04-01 18:33:59 -0700284 if (!mPendingCalls.isEmpty()) {
285 Log.wtf(this, "Pending calls did not get cleared.");
286 mPendingCalls.clear();
Santos Cordon4b2c1192014-03-19 18:15:38 -0700287 }
288 }
Santos Cordon681663d2014-01-30 04:32:15 -0800289 }
Ben Gilad9f2bed32013-12-12 17:43:26 -0800290}