blob: 7dcfdfbd5abdd0b15dbd65973549074baff7067d [file] [log] [blame]
Tyler Gunn86014fc2015-06-12 14:31:25 -07001/*
2 * Copyright (C) 2015 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.server.telecom;
18
19import android.net.Uri;
20import android.os.IBinder;
21import android.os.Looper;
22import android.os.RemoteException;
23import android.telecom.Connection;
24import android.telecom.InCallService;
25import android.telecom.VideoProfile;
26import android.view.Surface;
27
28import com.android.internal.telecom.IVideoCallback;
29import com.android.internal.telecom.IVideoProvider;
30
31import java.util.Collections;
32import java.util.HashMap;
33import java.util.Set;
34import java.util.concurrent.ConcurrentHashMap;
35
36/**
37 * Proxies video provider messages from {@link InCallService.VideoCall}
38 * implementations to the underlying {@link Connection.VideoProvider} implementation. Also proxies
39 * callbacks from the {@link Connection.VideoProvider} to {@link InCallService.VideoCall}
40 * implementations.
41 *
42 * Also provides a means for Telecom to send and receive these messages.
43 */
44public class VideoProviderProxy extends Connection.VideoProvider {
45
46 /**
47 * Listener for Telecom components interested in callbacks from the video provider.
48 */
49 interface Listener {
50 void onSessionModifyRequestReceived(Call call, VideoProfile videoProfile);
51 }
52
53 /**
54 * Set of listeners on this VideoProviderProxy.
55 *
56 * ConcurrentHashMap constructor params: 8 is initial table size, 0.9f is
57 * load factor before resizing, 1 means we only expect a single thread to
58 * access the map so make only a single shard
59 */
60 private final Set<Listener> mListeners = Collections.newSetFromMap(
61 new ConcurrentHashMap<Listener, Boolean>(8, 0.9f, 1));
62
63 /** The TelecomSystem SyncRoot used for synchronized operations. */
64 private final TelecomSystem.SyncRoot mLock;
65
66 /**
67 * The {@link android.telecom.Connection.VideoProvider} implementation residing with the
68 * {@link android.telecom.ConnectionService} which is being wrapped by this
69 * {@link VideoProviderProxy}.
70 */
71 private final IVideoProvider mConectionServiceVideoProvider;
72
73 /**
74 * Binder used to bind to the {@link android.telecom.ConnectionService}'s
75 * {@link com.android.internal.telecom.IVideoCallback}.
76 */
77 private final VideoCallListenerBinder mVideoCallListenerBinder;
78
79 /**
80 * The Telecom {@link Call} this {@link VideoProviderProxy} is associated with.
81 */
82 private Call mCall;
83
84 private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
85 @Override
86 public void binderDied() {
87 mConectionServiceVideoProvider.asBinder().unlinkToDeath(this, 0);
88 }
89 };
90
91 /**
92 * Creates a new instance of the {@link VideoProviderProxy}, binding it to the passed in
93 * {@code videoProvider} residing with the {@link android.telecom.ConnectionService}.
94 *
95 *
96 * @param lock
97 * @param videoProvider The {@link android.telecom.ConnectionService}'s video provider.
98 * @param call The current call.
99 * @throws RemoteException Remote exception.
100 */
101 VideoProviderProxy(TelecomSystem.SyncRoot lock,
102 IVideoProvider videoProvider, Call call) throws RemoteException {
103
104 super(Looper.getMainLooper());
105
106 mLock = lock;
107
108 mConectionServiceVideoProvider = videoProvider;
109 mConectionServiceVideoProvider.asBinder().linkToDeath(mDeathRecipient, 0);
110
111 mVideoCallListenerBinder = new VideoCallListenerBinder();
112 mConectionServiceVideoProvider.addVideoCallback(mVideoCallListenerBinder);
113 mCall = call;
114 }
115
116 /**
117 * IVideoCallback stub implementation. An instance of this class receives callbacks from the
118 * {@code ConnectionService}'s video provider.
119 */
120 private final class VideoCallListenerBinder extends IVideoCallback.Stub {
121 /**
122 * Proxies a request from the {@link #mConectionServiceVideoProvider} to the
123 * {@link InCallService} when a session modification request is received.
124 *
125 * @param videoProfile The requested video profile.
126 */
127 @Override
128 public void receiveSessionModifyRequest(VideoProfile videoProfile) {
129 synchronized (mLock) {
130 logFromVideoProvider("receiveSessionModifyRequest: " + videoProfile);
131
132 // Inform other Telecom components of the session modification request.
133 for (Listener listener : mListeners) {
134 listener.onSessionModifyRequestReceived(mCall, videoProfile);
135 }
136
137 VideoProviderProxy.this.receiveSessionModifyRequest(videoProfile);
138 }
139 }
140
141 /**
142 * Proxies a request from the {@link #mConectionServiceVideoProvider} to the
143 * {@link InCallService} when a session modification response is received.
144 *
145 * @param status The status of the response.
146 * @param requestProfile The requested video profile.
147 * @param responseProfile The response video profile.
148 */
149 @Override
150 public void receiveSessionModifyResponse(int status, VideoProfile requestProfile,
151 VideoProfile responseProfile) {
152 synchronized (mLock) {
153 logFromVideoProvider("receiveSessionModifyResponse: status=" + status +
154 " requestProfile=" + requestProfile + " responseProfile=" +
155 responseProfile);
156 VideoProviderProxy.this.receiveSessionModifyResponse(status, requestProfile,
157 responseProfile);
158 }
159 }
160
161 /**
162 * Proxies a request from the {@link #mConectionServiceVideoProvider} to the
163 * {@link InCallService} when a call session event occurs.
164 *
165 * @param event The call session event.
166 */
167 @Override
168 public void handleCallSessionEvent(int event) {
169 synchronized (mLock) {
170 logFromVideoProvider("handleCallSessionEvent: " + event);
171 VideoProviderProxy.this.handleCallSessionEvent(event);
172 }
173 }
174
175 /**
176 * Proxies a request from the {@link #mConectionServiceVideoProvider} to the
177 * {@link InCallService} when the peer dimensions change.
178 *
179 * @param width The width of the peer's video.
180 * @param height The height of the peer's video.
181 */
182 @Override
183 public void changePeerDimensions(int width, int height) {
184 synchronized (mLock) {
185 logFromVideoProvider("changePeerDimensions: width=" + width + " height=" +
186 height);
187 VideoProviderProxy.this.changePeerDimensions(width, height);
188 }
189 }
190
191 /**
192 * Proxies a request from the {@link #mConectionServiceVideoProvider} to the
193 * {@link InCallService} when the video quality changes.
194 *
195 * @param videoQuality The video quality.
196 */
197 @Override
198 public void changeVideoQuality(int videoQuality) {
199 synchronized (mLock) {
200 logFromVideoProvider("changeVideoQuality: " + videoQuality);
201 VideoProviderProxy.this.changeVideoQuality(videoQuality);
202 }
203 }
204
205 /**
206 * Proxies a request from the {@link #mConectionServiceVideoProvider} to the
207 * {@link InCallService} when the call data usage changes.
208 *
209 * @param dataUsage The data usage.
210 */
211 @Override
212 public void changeCallDataUsage(long dataUsage) {
213 synchronized (mLock) {
214 logFromVideoProvider("changeCallDataUsage: " + dataUsage);
215 VideoProviderProxy.this.setCallDataUsage(dataUsage);
216 }
217 }
218
219 /**
220 * Proxies a request from the {@link #mConectionServiceVideoProvider} to the
221 * {@link InCallService} when the camera capabilities change.
222 *
223 * @param cameraCapabilities The camera capabilities.
224 */
225 @Override
226 public void changeCameraCapabilities(VideoProfile.CameraCapabilities cameraCapabilities) {
227 synchronized (mLock) {
228 logFromVideoProvider("changeCameraCapabilities: " + cameraCapabilities);
229 VideoProviderProxy.this.changeCameraCapabilities(cameraCapabilities);
230 }
231 }
232 }
233
234 /**
235 * Proxies a request from the {@link InCallService} to the
236 * {@link #mConectionServiceVideoProvider} to change the camera.
237 *
238 * @param cameraId The id of the camera.
239 */
240 @Override
241 public void onSetCamera(String cameraId) {
242 synchronized (mLock) {
243 logFromInCall("setCamera: " + cameraId);
244 try {
245 mConectionServiceVideoProvider.setCamera(cameraId);
246 } catch (RemoteException e) {
247 }
248 }
249 }
250
251 /**
252 * Proxies a request from the {@link InCallService} to the
253 * {@link #mConectionServiceVideoProvider} to set the preview surface.
254 *
255 * @param surface The surface.
256 */
257 @Override
258 public void onSetPreviewSurface(Surface surface) {
259 synchronized (mLock) {
260 logFromInCall("setPreviewSurface");
261 try {
262 mConectionServiceVideoProvider.setPreviewSurface(surface);
263 } catch (RemoteException e) {
264 }
265 }
266 }
267
268 /**
269 * Proxies a request from the {@link InCallService} to the
270 * {@link #mConectionServiceVideoProvider} to change the display surface.
271 *
272 * @param surface The surface.
273 */
274 @Override
275 public void onSetDisplaySurface(Surface surface) {
276 synchronized (mLock) {
277 logFromInCall("setDisplaySurface");
278 try {
279 mConectionServiceVideoProvider.setDisplaySurface(surface);
280 } catch (RemoteException e) {
281 }
282 }
283 }
284
285 /**
286 * Proxies a request from the {@link InCallService} to the
287 * {@link #mConectionServiceVideoProvider} to change the device orientation.
288 *
289 * @param rotation The device orientation, in degrees.
290 */
291 @Override
292 public void onSetDeviceOrientation(int rotation) {
293 synchronized (mLock) {
294 logFromInCall("setDeviceOrientation: " + rotation);
295 try {
296 mConectionServiceVideoProvider.setDeviceOrientation(rotation);
297 } catch (RemoteException e) {
298 }
299 }
300 }
301
302 /**
303 * Proxies a request from the {@link InCallService} to the
304 * {@link #mConectionServiceVideoProvider} to change the camera zoom ratio.
305 *
306 * @param value The camera zoom ratio.
307 */
308 @Override
309 public void onSetZoom(float value) {
310 synchronized (mLock) {
311 logFromInCall("setZoom: " + value);
312 try {
313 mConectionServiceVideoProvider.setZoom(value);
314 } catch (RemoteException e) {
315 }
316 }
317 }
318
319 /**
320 * Proxies a request from the {@link InCallService} to the
321 * {@link #mConectionServiceVideoProvider} to provide a response to a session modification
322 * request.
323 *
324 * @param fromProfile The video properties prior to the request.
325 * @param toProfile The video properties with the requested changes made.
326 */
327 @Override
328 public void onSendSessionModifyRequest(VideoProfile fromProfile, VideoProfile toProfile) {
329 synchronized (mLock) {
330 logFromInCall("sendSessionModifyRequest: from=" + fromProfile + " to=" + toProfile);
331 try {
332 mConectionServiceVideoProvider.sendSessionModifyRequest(fromProfile, toProfile);
333 } catch (RemoteException e) {
334 }
335 }
336 }
337
338 /**
339 * Proxies a request from the {@link InCallService} to the
340 * {@link #mConectionServiceVideoProvider} to send a session modification request.
341 *
342 * @param responseProfile The response connection video properties.
343 */
344 @Override
345 public void onSendSessionModifyResponse(VideoProfile responseProfile) {
346 synchronized (mLock) {
347 logFromInCall("sendSessionModifyResponse: " + responseProfile);
348 try {
349 mConectionServiceVideoProvider.sendSessionModifyResponse(responseProfile);
350 } catch (RemoteException e) {
351 }
352 }
353 }
354
355 /**
356 * Proxies a request from the {@link InCallService} to the
357 * {@link #mConectionServiceVideoProvider} to request the camera capabilities.
358 */
359 @Override
360 public void onRequestCameraCapabilities() {
361 synchronized (mLock) {
362 logFromInCall("requestCameraCapabilities");
363 try {
364 mConectionServiceVideoProvider.requestCameraCapabilities();
365 } catch (RemoteException e) {
366 }
367 }
368 }
369
370 /**
371 * Proxies a request from the {@link InCallService} to the
372 * {@link #mConectionServiceVideoProvider} to request the connection data usage.
373 */
374 @Override
375 public void onRequestConnectionDataUsage() {
376 synchronized (mLock) {
377 logFromInCall("requestCallDataUsage");
378 try {
379 mConectionServiceVideoProvider.requestCallDataUsage();
380 } catch (RemoteException e) {
381 }
382 }
383 }
384
385 /**
386 * Proxies a request from the {@link InCallService} to the
387 * {@link #mConectionServiceVideoProvider} to set the pause image.
388 *
389 * @param uri URI of image to display.
390 */
391 @Override
392 public void onSetPauseImage(Uri uri) {
393 synchronized (mLock) {
394 logFromInCall("setPauseImage: " + uri);
395 try {
396 mConectionServiceVideoProvider.setPauseImage(uri);
397 } catch (RemoteException e) {
398 }
399 }
400 }
401
402 /**
403 * Add a listener to this {@link VideoProviderProxy}.
404 *
405 * @param listener The listener.
406 */
407 public void addListener(Listener listener) {
408 mListeners.add(listener);
409 }
410
411 /**
412 * Remove a listener from this {@link VideoProviderProxy}.
413 *
414 * @param listener The listener.
415 */
416 public void removeListener(Listener listener) {
417 if (listener != null) {
418 mListeners.remove(listener);
419 }
420 }
421
422 /**
423 * Logs a message originating from the {@link InCallService}.
424 *
425 * @param toLog The message to log.
426 */
427 private void logFromInCall(String toLog) {
428 Log.v(this, "IC->VP: " + toLog);
429 }
430
431 /**
432 * Logs a message originating from the {@link android.telecom.ConnectionService}'s
433 * {@link Connection.VideoProvider}.
434 *
435 * @param toLog The message to log.
436 */
437 private void logFromVideoProvider(String toLog) {
438 Log.v(this, "VP->IC: " + toLog);
439 }
440}