blob: 007d35aea9ab5fa4d015cafd8c28ec15d8ddb045 [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
Evan Charltona05805b2014-03-05 08:21:46 -080019import android.os.Bundle;
Santos Cordon63aeb162014-02-10 09:20:40 -080020import android.os.IBinder;
21import android.os.RemoteException;
Sailesh Nepal6aca10a2014-03-24 16:11:02 -070022import android.telecomm.CallAudioState;
Santos Cordon63aeb162014-02-10 09:20:40 -080023import android.telecomm.CallInfo;
Evan Charltona05805b2014-03-05 08:21:46 -080024import android.telecomm.CallService;
Ben Giladc5b22692014-02-18 20:03:22 -080025import android.telecomm.CallServiceDescriptor;
Sailesh Nepal83cfe7c2014-03-11 19:54:22 -070026import android.telecomm.TelecommConstants;
Sailesh Nepala439e1b2014-03-11 18:19:58 -070027
28import com.android.internal.telecomm.ICallService;
29import com.android.internal.telecomm.ICallServiceAdapter;
30import com.android.internal.telecomm.ICallServiceProvider;
Santos Cordon63aeb162014-02-10 09:20:40 -080031
32/**
33 * Wrapper for {@link ICallService}s, handles binding to {@link ICallService} and keeps track of
34 * when the object can safely be unbound. Other classes should not use {@link ICallService} directly
35 * and instead should use this class to invoke methods of {@link ICallService}.
Santos Cordon63aeb162014-02-10 09:20:40 -080036 */
Ben Gilad61925612014-03-11 19:06:36 -070037final class CallServiceWrapper extends ServiceBinder<ICallService> {
Santos Cordon63aeb162014-02-10 09:20:40 -080038
Santos Cordonc195e362014-02-11 17:05:31 -080039 /** The descriptor of this call service as supplied by the call-service provider. */
Ben Giladc5b22692014-02-18 20:03:22 -080040 private final CallServiceDescriptor mDescriptor;
Santos Cordonc195e362014-02-11 17:05:31 -080041
42 /**
43 * The adapter used by the underlying call-service implementation to communicate with Telecomm.
44 */
45 private final CallServiceAdapter mAdapter;
46
47 /** The actual service implementation. */
48 private ICallService mServiceInterface;
49
Ben Gilad61925612014-03-11 19:06:36 -070050 private Binder mBinder = new Binder();
Sailesh Nepale59bb192014-04-01 18:33:59 -070051 private final CallIdMapper mCallIdMapper;
Ben Gilad61925612014-03-11 19:06:36 -070052
Santos Cordon63aeb162014-02-10 09:20:40 -080053 /**
Sailesh Nepale59bb192014-04-01 18:33:59 -070054 * Creates a call-service for the specified descriptor.
Santos Cordonc195e362014-02-11 17:05:31 -080055 *
Santos Cordon61d0f702014-02-19 02:52:23 -080056 * @param descriptor The call-service descriptor from
57 * {@link ICallServiceProvider#lookupCallServices}.
Sailesh Nepale59bb192014-04-01 18:33:59 -070058 * @param outgoingCallsManager Manages the placing of outgoing calls.
59 * @param incomingCallsManager Manages the incoming call initialization flow.
Santos Cordon63aeb162014-02-10 09:20:40 -080060 */
Sailesh Nepale59bb192014-04-01 18:33:59 -070061 CallServiceWrapper(
62 CallServiceDescriptor descriptor,
63 OutgoingCallsManager outgoingCallsManager,
64 IncomingCallsManager incomingCallsManager) {
Sailesh Nepala439e1b2014-03-11 18:19:58 -070065 super(TelecommConstants.ACTION_CALL_SERVICE, descriptor.getServiceComponent());
Ben Giladc5b22692014-02-18 20:03:22 -080066 mDescriptor = descriptor;
Sailesh Nepale59bb192014-04-01 18:33:59 -070067 mCallIdMapper = new CallIdMapper("CallService");
68 mAdapter = new CallServiceAdapter(outgoingCallsManager, incomingCallsManager,
69 mCallIdMapper);
Santos Cordon63aeb162014-02-10 09:20:40 -080070 }
71
Ben Gilad61925612014-03-11 19:06:36 -070072 CallServiceDescriptor getDescriptor() {
Ben Giladc5b22692014-02-18 20:03:22 -080073 return mDescriptor;
Santos Cordonc195e362014-02-11 17:05:31 -080074 }
75
Santos Cordon63aeb162014-02-10 09:20:40 -080076 /** See {@link ICallService#setCallServiceAdapter}. */
Sailesh Nepale59bb192014-04-01 18:33:59 -070077 private void setCallServiceAdapter(ICallServiceAdapter callServiceAdapter) {
Santos Cordon61d0f702014-02-19 02:52:23 -080078 if (isServiceValid("setCallServiceAdapter")) {
79 try {
Santos Cordon63aeb162014-02-10 09:20:40 -080080 mServiceInterface.setCallServiceAdapter(callServiceAdapter);
Santos Cordon61d0f702014-02-19 02:52:23 -080081 } catch (RemoteException e) {
Santos Cordon63aeb162014-02-10 09:20:40 -080082 }
Santos Cordon63aeb162014-02-10 09:20:40 -080083 }
84 }
85
Ben Gilad61925612014-03-11 19:06:36 -070086 /**
87 * Checks whether or not the specified call is compatible with this call-service implementation,
88 * see {@link ICallService#isCompatibleWith}. Upon failure, the specified error callback is
89 * invoked. Can be invoked even when the call service is unbound.
90 *
Ben Gilad61925612014-03-11 19:06:36 -070091 * @param errorCallback The callback to invoke upon failure.
92 */
Sailesh Nepale59bb192014-04-01 18:33:59 -070093 void isCompatibleWith(final Call call, final Runnable errorCallback) {
94 Log.d(this, "isCompatibleWith(%s) via %s.", call, getComponentName());
Ben Gilad61925612014-03-11 19:06:36 -070095 BindCallback callback = new BindCallback() {
96 @Override public void onSuccess() {
97 if (isServiceValid("isCompatibleWith")) {
98 try {
Sailesh Nepale59bb192014-04-01 18:33:59 -070099 mAdapter.addPendingCall(call);
100 CallInfo callInfo = call.toCallInfo(mCallIdMapper.getCallId(call));
Ben Gilad61925612014-03-11 19:06:36 -0700101 mServiceInterface.isCompatibleWith(callInfo);
102 } catch (RemoteException e) {
Ben Gilad61925612014-03-11 19:06:36 -0700103 }
104 }
Santos Cordon63aeb162014-02-10 09:20:40 -0800105 }
Ben Gilad61925612014-03-11 19:06:36 -0700106 @Override public void onFailure() {
107 errorCallback.run();
108 }
109 };
110
111 mBinder.bind(callback);
Santos Cordon63aeb162014-02-10 09:20:40 -0800112 }
113
Ben Gilad61925612014-03-11 19:06:36 -0700114 /**
115 * Attempts to place the specified call, see {@link ICallService#call}. Upon failure, the
116 * specified error callback is invoked. Can be invoked even when the call service is unbound.
Ben Gilad61925612014-03-11 19:06:36 -0700117 */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700118 void call(Call call) {
119 Log.d(this, "call(%s) via %s.", call, getComponentName());
120 if (isServiceValid("call")) {
121 try {
122 CallInfo callInfo = call.toCallInfo(mCallIdMapper.getCallId(call));
123 mServiceInterface.call(callInfo);
124 } catch (RemoteException e) {
Ben Gilad28e8ad62014-03-06 17:01:54 -0800125 }
Sailesh Nepale59bb192014-04-01 18:33:59 -0700126 }
Ben Gilad28e8ad62014-03-06 17:01:54 -0800127 }
128
Ihab Awad74549ec2014-03-10 15:33:25 -0700129 /** @see CallService#abort(String) */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700130 void abort(Call call) {
131 mAdapter.removePendingCall(call);
Ben Gilad28e8ad62014-03-06 17:01:54 -0800132 if (isServiceValid("abort")) {
133 try {
Sailesh Nepale59bb192014-04-01 18:33:59 -0700134 mServiceInterface.abort(mCallIdMapper.getCallId(call));
Ben Gilad28e8ad62014-03-06 17:01:54 -0800135 } catch (RemoteException e) {
Santos Cordon63aeb162014-02-10 09:20:40 -0800136 }
Santos Cordon61d0f702014-02-19 02:52:23 -0800137 }
138 }
139
Ihab Awad74549ec2014-03-10 15:33:25 -0700140 /** @see CallService#hold(String) */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700141 void hold(Call call) {
Yorke Leecdf3ebd2014-03-12 18:31:41 -0700142 if (isServiceValid("hold")) {
143 try {
Sailesh Nepale59bb192014-04-01 18:33:59 -0700144 mServiceInterface.hold(mCallIdMapper.getCallId(call));
Yorke Leecdf3ebd2014-03-12 18:31:41 -0700145 } catch (RemoteException e) {
Yorke Leecdf3ebd2014-03-12 18:31:41 -0700146 }
147 }
148 }
149
Ihab Awad74549ec2014-03-10 15:33:25 -0700150 /** @see CallService#unhold(String) */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700151 void unhold(Call call) {
Yorke Leecdf3ebd2014-03-12 18:31:41 -0700152 if (isServiceValid("unhold")) {
153 try {
Sailesh Nepale59bb192014-04-01 18:33:59 -0700154 mServiceInterface.unhold(mCallIdMapper.getCallId(call));
Yorke Leecdf3ebd2014-03-12 18:31:41 -0700155 } catch (RemoteException e) {
Yorke Leecdf3ebd2014-03-12 18:31:41 -0700156 }
157 }
158 }
159
Ihab Awad74549ec2014-03-10 15:33:25 -0700160 /** @see CallService#onAudioStateChanged(String,CallAudioState) */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700161 void onAudioStateChanged(Call activeCall, CallAudioState audioState) {
Sailesh Nepal6aca10a2014-03-24 16:11:02 -0700162 if (isServiceValid("onAudioStateChanged")) {
163 try {
Sailesh Nepale59bb192014-04-01 18:33:59 -0700164 mServiceInterface.onAudioStateChanged(mCallIdMapper.getCallId(activeCall),
165 audioState);
Sailesh Nepal6aca10a2014-03-24 16:11:02 -0700166 } catch (RemoteException e) {
Sailesh Nepal6aca10a2014-03-24 16:11:02 -0700167 }
168 }
169 }
170
Ben Gilad61925612014-03-11 19:06:36 -0700171 /**
172 * Starts retrieval of details for an incoming call. Details are returned through the
173 * call-service adapter using the specified call ID. Upon failure, the specified error callback
174 * is invoked. Can be invoked even when the call service is unbound.
175 * See {@link ICallService#setIncomingCallId}.
176 *
Sailesh Nepale59bb192014-04-01 18:33:59 -0700177 * @param call The call used for the incoming call.
Ben Gilad61925612014-03-11 19:06:36 -0700178 * @param extras The {@link CallService}-provided extras which need to be sent back.
179 * @param errorCallback The callback to invoke upon failure.
180 */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700181 void setIncomingCallId(final Call call, final Bundle extras, final Runnable errorCallback) {
182 Log.d(this, "setIncomingCall(%s) via %s.", call, getComponentName());
Ben Gilad61925612014-03-11 19:06:36 -0700183 BindCallback callback = new BindCallback() {
184 @Override public void onSuccess() {
185 if (isServiceValid("setIncomingCallId")) {
Sailesh Nepale59bb192014-04-01 18:33:59 -0700186 mAdapter.addPendingCall(call);
Ben Gilad61925612014-03-11 19:06:36 -0700187 try {
Sailesh Nepale59bb192014-04-01 18:33:59 -0700188 mServiceInterface.setIncomingCallId(mCallIdMapper.getCallId(call),
189 extras);
Ben Gilad61925612014-03-11 19:06:36 -0700190 } catch (RemoteException e) {
Ben Gilad61925612014-03-11 19:06:36 -0700191 }
192 }
Santos Cordon61d0f702014-02-19 02:52:23 -0800193 }
Ben Gilad61925612014-03-11 19:06:36 -0700194 @Override public void onFailure() {
195 errorCallback.run();
196 }
197 };
198
199 mBinder.bind(callback);
Santos Cordon63aeb162014-02-10 09:20:40 -0800200 }
201
Ihab Awad74549ec2014-03-10 15:33:25 -0700202 /** @see CallService#disconnect(String) */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700203 void disconnect(Call call) {
Santos Cordon61d0f702014-02-19 02:52:23 -0800204 if (isServiceValid("disconnect")) {
205 try {
Sailesh Nepale59bb192014-04-01 18:33:59 -0700206 mServiceInterface.disconnect(mCallIdMapper.getCallId(call));
Santos Cordon61d0f702014-02-19 02:52:23 -0800207 } catch (RemoteException e) {
Santos Cordon63aeb162014-02-10 09:20:40 -0800208 }
Santos Cordon63aeb162014-02-10 09:20:40 -0800209 }
210 }
Santos Cordon5c12c6e2014-02-13 14:35:31 -0800211
Ihab Awad74549ec2014-03-10 15:33:25 -0700212 /** @see CallService#answer(String) */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700213 void answer(Call call) {
Santos Cordon61d0f702014-02-19 02:52:23 -0800214 if (isServiceValid("answer")) {
215 try {
Sailesh Nepale59bb192014-04-01 18:33:59 -0700216 mServiceInterface.answer(mCallIdMapper.getCallId(call));
Santos Cordon61d0f702014-02-19 02:52:23 -0800217 } catch (RemoteException e) {
Santos Cordon7917d382014-02-14 02:31:18 -0800218 }
Santos Cordon61d0f702014-02-19 02:52:23 -0800219 }
220 }
221
Ihab Awad74549ec2014-03-10 15:33:25 -0700222 /** @see CallService#reject(String) */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700223 void reject(Call call) {
Santos Cordon61d0f702014-02-19 02:52:23 -0800224 if (isServiceValid("reject")) {
225 try {
Sailesh Nepale59bb192014-04-01 18:33:59 -0700226 mServiceInterface.reject(mCallIdMapper.getCallId(call));
Santos Cordon61d0f702014-02-19 02:52:23 -0800227 } catch (RemoteException e) {
Ihab Awad74549ec2014-03-10 15:33:25 -0700228 }
229 }
230 }
231
232 /** @see CallService#playDtmfTone(String,char) */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700233 void playDtmfTone(Call call, char digit) {
Ihab Awad74549ec2014-03-10 15:33:25 -0700234 if (isServiceValid("playDtmfTone")) {
235 try {
Sailesh Nepale59bb192014-04-01 18:33:59 -0700236 mServiceInterface.playDtmfTone(mCallIdMapper.getCallId(call), digit);
Ihab Awad74549ec2014-03-10 15:33:25 -0700237 } catch (RemoteException e) {
Ihab Awad74549ec2014-03-10 15:33:25 -0700238 }
239 }
240 }
241
242 /** @see CallService#stopDtmfTone(String) */
Sailesh Nepale59bb192014-04-01 18:33:59 -0700243 void stopDtmfTone(Call call) {
Ihab Awad74549ec2014-03-10 15:33:25 -0700244 if (isServiceValid("stopDtmfTone")) {
245 try {
Sailesh Nepale59bb192014-04-01 18:33:59 -0700246 mServiceInterface.stopDtmfTone(mCallIdMapper.getCallId(call));
Ihab Awad74549ec2014-03-10 15:33:25 -0700247 } catch (RemoteException e) {
Santos Cordon61d0f702014-02-19 02:52:23 -0800248 }
Santos Cordon7917d382014-02-14 02:31:18 -0800249 }
250 }
251
Sailesh Nepale59bb192014-04-01 18:33:59 -0700252 void addCall(Call call) {
253 mCallIdMapper.addCall(call);
Santos Cordon7917d382014-02-14 02:31:18 -0800254 }
255
Sailesh Nepale59bb192014-04-01 18:33:59 -0700256 void removeCall(Call call) {
257 mAdapter.removePendingCall(call);
258 mCallIdMapper.removeCall(call);
Yorke Leeadee12d2014-03-13 12:08:30 -0700259 }
260
Santos Cordon5c12c6e2014-02-13 14:35:31 -0800261 /** {@inheritDoc} */
262 @Override protected void setServiceInterface(IBinder binder) {
Santos Cordon4b2c1192014-03-19 18:15:38 -0700263 if (binder == null) {
264 // We have lost our service connection. Notify the world that this call service is done.
265 // We must notify the adapter before CallsManager. The adapter will force any pending
266 // outgoing calls to try the next call service. This needs to happen before CallsManager
267 // tries to clean up any calls still associated with this call service.
268 mAdapter.handleCallServiceDeath();
269 CallsManager.getInstance().handleCallServiceDeath(this);
270 mServiceInterface = null;
271 } else {
272 mServiceInterface = ICallService.Stub.asInterface(binder);
273 setCallServiceAdapter(mAdapter);
274 }
Santos Cordon5c12c6e2014-02-13 14:35:31 -0800275 }
Santos Cordon63aeb162014-02-10 09:20:40 -0800276}