blob: 195ac1773e4a176c8a9126cd8c7d1af884df5cf1 [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 Nepale59bb192014-04-01 18:33:59 -070058 Log.w(this, "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 Nepal6ab6fb72014-04-01 20:03:19 -070069 Log.w(this, "Unknown incoming call: %s, id: %s", call,
70 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 Nepale59bb192014-04-01 18:33:59 -070079 Log.w(this, "Unknown outgoing call: %s, id: %s", call, msg.obj);
Sailesh Nepal10ea4602014-04-01 17:23:32 -070080 }
81 break;
82 case MSG_HANDLE_FAILED_OUTGOING_CALL: {
83 SomeArgs args = (SomeArgs) msg.obj;
84 try {
Sailesh Nepale59bb192014-04-01 18:33:59 -070085 call = mCallIdMapper.getCall(args.arg1);
Sailesh Nepal10ea4602014-04-01 17:23:32 -070086 String reason = (String) args.arg2;
Sailesh Nepale59bb192014-04-01 18:33:59 -070087 if (call != null && mPendingCalls.remove(call) && !call.isIncoming()) {
88 mOutgoingCallsManager.handleFailedCallAttempt(call, reason);
Sailesh Nepal10ea4602014-04-01 17:23:32 -070089 } else {
Sailesh Nepal6ab6fb72014-04-01 20:03:19 -070090 Log.w(this, "Unknown outgoing call: %s, id: %s", call, args.arg1);
Sailesh Nepal10ea4602014-04-01 17:23:32 -070091 }
92 } finally {
93 args.recycle();
94 }
95 break;
96 }
97 case MSG_SET_ACTIVE:
Sailesh Nepale59bb192014-04-01 18:33:59 -070098 call = mCallIdMapper.getCall(msg.obj);
99 if (call != null) {
100 mCallsManager.markCallAsActive(call);
101 } else {
102 Log.w(this, "Unknown call id: %s", msg.obj);
103 }
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700104 break;
105 case MSG_SET_RINGING:
Sailesh Nepale59bb192014-04-01 18:33:59 -0700106 call = mCallIdMapper.getCall(msg.obj);
107 if (call != null) {
108 mCallsManager.markCallAsRinging(call);
109 } else {
110 Log.w(this, "Unknown call id: %s", msg.obj);
111 }
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700112 break;
113 case MSG_SET_DIALING:
Sailesh Nepale59bb192014-04-01 18:33:59 -0700114 call = mCallIdMapper.getCall(msg.obj);
115 if (call != null) {
116 mCallsManager.markCallAsDialing(call);
117 } else {
118 Log.w(this, "Unknown call id: %s", msg.obj);
119 }
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700120 break;
121 case MSG_SET_DISCONNECTED: {
122 SomeArgs args = (SomeArgs) msg.obj;
123 try {
Sailesh Nepale59bb192014-04-01 18:33:59 -0700124 call = mCallIdMapper.getCall(args.arg1);
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700125 String disconnectMessage = (String) args.arg2;
126 int disconnectCause = args.argi1;
Sailesh Nepale59bb192014-04-01 18:33:59 -0700127 if (call != null) {
128 mCallsManager.markCallAsDisconnected(call, disconnectCause,
129 disconnectMessage);
130 } else {
Sailesh Nepal6ab6fb72014-04-01 20:03:19 -0700131 Log.w(this, "Unknown call id: %s", args.arg1);
Sailesh Nepale59bb192014-04-01 18:33:59 -0700132 }
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700133 } finally {
134 args.recycle();
135 }
136 break;
137 }
138 case MSG_SET_ON_HOLD:
Sailesh Nepale59bb192014-04-01 18:33:59 -0700139 call = mCallIdMapper.getCall(msg.obj);
140 if (call != null) {
141 mCallsManager.markCallAsOnHold(call);
142 } else {
143 Log.w(this, "Unknown call id: %s", msg.obj);
144 }
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700145 break;
146 }
147 }
148 }
149
Santos Cordon681663d2014-01-30 04:32:15 -0800150 private final CallsManager mCallsManager;
Santos Cordon681663d2014-01-30 04:32:15 -0800151 private final OutgoingCallsManager mOutgoingCallsManager;
Santos Cordon493e8f22014-02-19 03:15:12 -0800152 private final IncomingCallsManager mIncomingCallsManager;
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700153 private final Handler mHandler = new CallServiceAdapterHandler();
Sailesh Nepale59bb192014-04-01 18:33:59 -0700154 private final CallIdMapper mCallIdMapper;
155 private final Set<Call> mPendingCalls = Sets.newHashSet();
Santos Cordon7917d382014-02-14 02:31:18 -0800156
Santos Cordon681663d2014-01-30 04:32:15 -0800157 /**
158 * Persists the specified parameters.
Santos Cordon493e8f22014-02-19 03:15:12 -0800159 *
160 * @param outgoingCallsManager Manages the placing of outgoing calls.
161 * @param incomingCallsManager Manages the incoming call initialization flow.
Santos Cordon681663d2014-01-30 04:32:15 -0800162 */
Santos Cordon493e8f22014-02-19 03:15:12 -0800163 CallServiceAdapter(
Sailesh Nepale59bb192014-04-01 18:33:59 -0700164 OutgoingCallsManager outgoingCallsManager,
165 IncomingCallsManager incomingCallsManager,
166 CallIdMapper callIdMapper) {
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700167 ThreadUtil.checkOnMainThread();
Santos Cordon681663d2014-01-30 04:32:15 -0800168 mCallsManager = CallsManager.getInstance();
169 mOutgoingCallsManager = outgoingCallsManager;
Santos Cordon493e8f22014-02-19 03:15:12 -0800170 mIncomingCallsManager = incomingCallsManager;
Sailesh Nepale59bb192014-04-01 18:33:59 -0700171 mCallIdMapper = callIdMapper;
Santos Cordon681663d2014-01-30 04:32:15 -0800172 }
173
174 /** {@inheritDoc} */
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700175 @Override
176 public void setIsCompatibleWith(String callId, boolean isCompatible) {
Evan Charlton0ebf8402014-04-02 16:26:15 -0700177 Log.v(this, "setIsCompatibleWith id: %s, isCompatible: %b", callId, isCompatible);
Sailesh Nepale59bb192014-04-01 18:33:59 -0700178 mCallIdMapper.checkValidCallId(callId);
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700179 mHandler.obtainMessage(MSG_SET_IS_COMPATIBLE_WITH, isCompatible ? 1 : 0, 0, callId).
180 sendToTarget();
Santos Cordon681663d2014-01-30 04:32:15 -0800181 }
182
Santos Cordon7917d382014-02-14 02:31:18 -0800183 /** {@inheritDoc} */
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700184 @Override
185 public void notifyIncomingCall(CallInfo callInfo) {
Sailesh Nepale59bb192014-04-01 18:33:59 -0700186 mCallIdMapper.checkValidCallId(callInfo.getId());
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700187 mHandler.obtainMessage(MSG_NOTIFY_INCOMING_CALL, callInfo).sendToTarget();
Santos Cordon681663d2014-01-30 04:32:15 -0800188 }
189
190 /** {@inheritDoc} */
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700191 @Override
192 public void handleSuccessfulOutgoingCall(String callId) {
Sailesh Nepale59bb192014-04-01 18:33:59 -0700193 mCallIdMapper.checkValidCallId(callId);
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700194 mHandler.obtainMessage(MSG_HANDLE_SUCCESSFUL_OUTGOING_CALL, callId).sendToTarget();
Santos Cordon681663d2014-01-30 04:32:15 -0800195 }
196
197 /** {@inheritDoc} */
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700198 @Override
199 public void handleFailedOutgoingCall(String callId, String reason) {
Sailesh Nepale59bb192014-04-01 18:33:59 -0700200 mCallIdMapper.checkValidCallId(callId);
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700201 SomeArgs args = SomeArgs.obtain();
202 args.arg1 = callId;
203 args.arg2 = reason;
204 mHandler.obtainMessage(MSG_HANDLE_FAILED_OUTGOING_CALL, args).sendToTarget();
Santos Cordon681663d2014-01-30 04:32:15 -0800205 }
206
207 /** {@inheritDoc} */
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700208 @Override
209 public void setActive(String callId) {
Sailesh Nepale59bb192014-04-01 18:33:59 -0700210 mCallIdMapper.checkValidCallId(callId);
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700211 mHandler.obtainMessage(MSG_SET_ACTIVE, callId).sendToTarget();
Santos Cordon681663d2014-01-30 04:32:15 -0800212 }
213
214 /** {@inheritDoc} */
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700215 @Override
216 public void setRinging(String callId) {
Sailesh Nepale59bb192014-04-01 18:33:59 -0700217 mCallIdMapper.checkValidCallId(callId);
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700218 mHandler.obtainMessage(MSG_SET_RINGING, callId).sendToTarget();
Santos Cordon681663d2014-01-30 04:32:15 -0800219 }
220
221 /** {@inheritDoc} */
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700222 @Override
223 public void setDialing(String callId) {
Sailesh Nepale59bb192014-04-01 18:33:59 -0700224 mCallIdMapper.checkValidCallId(callId);
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700225 mHandler.obtainMessage(MSG_SET_DIALING, callId).sendToTarget();
Santos Cordon681663d2014-01-30 04:32:15 -0800226 }
227
228 /** {@inheritDoc} */
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700229 @Override
230 public void setDisconnected(
231 String callId, int disconnectCause, String disconnectMessage) {
Sailesh Nepale59bb192014-04-01 18:33:59 -0700232 mCallIdMapper.checkValidCallId(callId);
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700233 SomeArgs args = SomeArgs.obtain();
234 args.arg1 = callId;
235 args.arg2 = disconnectMessage;
236 args.argi1 = disconnectCause;
237 mHandler.obtainMessage(MSG_SET_DISCONNECTED, args).sendToTarget();
Santos Cordon681663d2014-01-30 04:32:15 -0800238 }
239
Yorke Leecdf3ebd2014-03-12 18:31:41 -0700240 /** {@inheritDoc} */
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700241 @Override
242 public void setOnHold(String callId) {
Sailesh Nepale59bb192014-04-01 18:33:59 -0700243 mCallIdMapper.checkValidCallId(callId);
Sailesh Nepal10ea4602014-04-01 17:23:32 -0700244 mHandler.obtainMessage(MSG_SET_ON_HOLD, callId).sendToTarget();
Yorke Leecdf3ebd2014-03-12 18:31:41 -0700245 }
246
Santos Cordon681663d2014-01-30 04:32:15 -0800247 /**
Sailesh Nepale59bb192014-04-01 18:33:59 -0700248 * Adds the specified call to the list of pending calls. Only calls in this list which are
249 * outgoing will be handled by {@link #isCompatibleWith}, {@link handleSuccessfulOutgoingCall},
250 * and {@link handleFailedOutgoingCall}. Similarly, only calls in this list which are incoming
251 * will be handled by {@link notifyIncomingCall}.
Ben Gilad28e8ad62014-03-06 17:01:54 -0800252 */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700253 void addPendingCall(Call call) {
254 mPendingCalls.add(call);
Ben Gilad28e8ad62014-03-06 17:01:54 -0800255 }
256
257 /**
Sailesh Nepale59bb192014-04-01 18:33:59 -0700258 * Removes the specified call from the list of pending calls.
Ben Gilad28e8ad62014-03-06 17:01:54 -0800259 */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700260 void removePendingCall(Call call) {
261 mPendingCalls.remove(call);
Santos Cordon7917d382014-02-14 02:31:18 -0800262 }
263
264 /**
Santos Cordon4b2c1192014-03-19 18:15:38 -0700265 * Called when the associated call service dies.
266 */
267 void handleCallServiceDeath() {
Sailesh Nepale59bb192014-04-01 18:33:59 -0700268 if (!mPendingCalls.isEmpty()) {
269 // Iterate through a copy because the code inside the loop will modify the original
270 // list.
271 for (Call call : ImmutableList.copyOf(mPendingCalls)) {
272 if (call.isIncoming()) {
273 mIncomingCallsManager.handleFailedIncomingCall(call);
274 } else {
275 mOutgoingCallsManager.handleFailedCallAttempt(call,
276 "Call service disconnected.");
277 }
Santos Cordon4b2c1192014-03-19 18:15:38 -0700278 }
279
Sailesh Nepale59bb192014-04-01 18:33:59 -0700280 if (!mPendingCalls.isEmpty()) {
281 Log.wtf(this, "Pending calls did not get cleared.");
282 mPendingCalls.clear();
Santos Cordon4b2c1192014-03-19 18:15:38 -0700283 }
284 }
Santos Cordon681663d2014-01-30 04:32:15 -0800285 }
Ben Gilad9f2bed32013-12-12 17:43:26 -0800286}