blob: 5352dfc431da9d137b99112692e64e2dd21cd3eb [file] [log] [blame]
Andrew Lee50aca232014-07-22 16:41:54 -07001/*
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
Tyler Gunnef9f6f92014-09-12 22:16:17 -070017package android.telecom;
Andrew Lee50aca232014-07-22 16:41:54 -070018
19import android.os.Handler;
20import android.os.IBinder;
21import android.os.Looper;
22import android.os.Message;
23import android.os.RemoteException;
Tyler Gunnef9f6f92014-09-12 22:16:17 -070024import android.telecom.InCallService.VideoCall;
Andrew Lee50aca232014-07-22 16:41:54 -070025import android.view.Surface;
26
27import com.android.internal.os.SomeArgs;
Tyler Gunnef9f6f92014-09-12 22:16:17 -070028import com.android.internal.telecom.IVideoCallback;
29import com.android.internal.telecom.IVideoProvider;
Andrew Lee50aca232014-07-22 16:41:54 -070030
31/**
32 * Implementation of a Video Call, which allows InCallUi to communicate commands to the underlying
Ihab Awadb19a0bc2014-08-07 19:46:01 -070033 * {@link Connection.VideoProvider}, and direct callbacks from the
34 * {@link Connection.VideoProvider} to the appropriate {@link VideoCall.Listener}.
35 *
36 * {@hide}
Andrew Lee50aca232014-07-22 16:41:54 -070037 */
38public class VideoCallImpl extends VideoCall {
Andrew Lee50aca232014-07-22 16:41:54 -070039
Ihab Awadb19a0bc2014-08-07 19:46:01 -070040 private final IVideoProvider mVideoProvider;
Andrew Lee50aca232014-07-22 16:41:54 -070041 private final VideoCallListenerBinder mBinder;
Andrew Leeda80c872015-04-15 14:09:50 -070042 private VideoCall.Callback mCallback;
Tyler Gunn45382162015-05-06 08:52:27 -070043 private int mVideoQuality = VideoProfile.QUALITY_UNKNOWN;
44 private Call mCall;
Andrew Lee50aca232014-07-22 16:41:54 -070045
46 private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
47 @Override
48 public void binderDied() {
Ihab Awadb19a0bc2014-08-07 19:46:01 -070049 mVideoProvider.asBinder().unlinkToDeath(this, 0);
Andrew Lee50aca232014-07-22 16:41:54 -070050 }
51 };
52
53 /**
Ihab Awadb19a0bc2014-08-07 19:46:01 -070054 * IVideoCallback stub implementation.
Andrew Lee50aca232014-07-22 16:41:54 -070055 */
Ihab Awadb19a0bc2014-08-07 19:46:01 -070056 private final class VideoCallListenerBinder extends IVideoCallback.Stub {
Andrew Lee50aca232014-07-22 16:41:54 -070057 @Override
Ihab Awadb19a0bc2014-08-07 19:46:01 -070058 public void receiveSessionModifyRequest(VideoProfile videoProfile) {
Andrew Lee011728f2015-04-23 15:47:06 -070059 mHandler.obtainMessage(MessageHandler.MSG_RECEIVE_SESSION_MODIFY_REQUEST,
Ihab Awadb19a0bc2014-08-07 19:46:01 -070060 videoProfile).sendToTarget();
Andrew Lee50aca232014-07-22 16:41:54 -070061 }
62
63 @Override
Ihab Awadb19a0bc2014-08-07 19:46:01 -070064 public void receiveSessionModifyResponse(int status, VideoProfile requestProfile,
65 VideoProfile responseProfile) {
Andrew Lee50aca232014-07-22 16:41:54 -070066 SomeArgs args = SomeArgs.obtain();
67 args.arg1 = status;
68 args.arg2 = requestProfile;
69 args.arg3 = responseProfile;
Andrew Lee011728f2015-04-23 15:47:06 -070070 mHandler.obtainMessage(MessageHandler.MSG_RECEIVE_SESSION_MODIFY_RESPONSE, args)
71 .sendToTarget();
Andrew Lee50aca232014-07-22 16:41:54 -070072 }
73
74 @Override
75 public void handleCallSessionEvent(int event) {
Andrew Lee011728f2015-04-23 15:47:06 -070076 mHandler.obtainMessage(MessageHandler.MSG_HANDLE_CALL_SESSION_EVENT, event)
77 .sendToTarget();
Andrew Lee50aca232014-07-22 16:41:54 -070078 }
79
80 @Override
81 public void changePeerDimensions(int width, int height) {
82 SomeArgs args = SomeArgs.obtain();
83 args.arg1 = width;
84 args.arg2 = height;
Andrew Lee011728f2015-04-23 15:47:06 -070085 mHandler.obtainMessage(MessageHandler.MSG_CHANGE_PEER_DIMENSIONS, args).sendToTarget();
Andrew Lee50aca232014-07-22 16:41:54 -070086 }
87
88 @Override
Rekha Kumar07366812015-03-24 16:42:31 -070089 public void changeVideoQuality(int videoQuality) {
Andrew Lee011728f2015-04-23 15:47:06 -070090 mHandler.obtainMessage(MessageHandler.MSG_CHANGE_VIDEO_QUALITY, videoQuality, 0)
91 .sendToTarget();
Rekha Kumar07366812015-03-24 16:42:31 -070092 }
93
94 @Override
95 public void changeCallDataUsage(long dataUsage) {
Andrew Lee011728f2015-04-23 15:47:06 -070096 mHandler.obtainMessage(MessageHandler.MSG_CHANGE_CALL_DATA_USAGE, dataUsage)
97 .sendToTarget();
Andrew Lee50aca232014-07-22 16:41:54 -070098 }
99
100 @Override
Yorke Lee400470f2015-05-12 13:31:25 -0700101 public void changeCameraCapabilities(VideoProfile.CameraCapabilities cameraCapabilities) {
Andrew Lee011728f2015-04-23 15:47:06 -0700102 mHandler.obtainMessage(MessageHandler.MSG_CHANGE_CAMERA_CAPABILITIES,
Andrew Lee50aca232014-07-22 16:41:54 -0700103 cameraCapabilities).sendToTarget();
104 }
105 }
106
107 /** Default handler used to consolidate binder method calls onto a single thread. */
Andrew Lee011728f2015-04-23 15:47:06 -0700108 private final class MessageHandler extends Handler {
109 private static final int MSG_RECEIVE_SESSION_MODIFY_REQUEST = 1;
110 private static final int MSG_RECEIVE_SESSION_MODIFY_RESPONSE = 2;
111 private static final int MSG_HANDLE_CALL_SESSION_EVENT = 3;
112 private static final int MSG_CHANGE_PEER_DIMENSIONS = 4;
113 private static final int MSG_CHANGE_CALL_DATA_USAGE = 5;
114 private static final int MSG_CHANGE_CAMERA_CAPABILITIES = 6;
115 private static final int MSG_CHANGE_VIDEO_QUALITY = 7;
116
117 public MessageHandler(Looper looper) {
118 super(looper);
119 }
120
Andrew Lee50aca232014-07-22 16:41:54 -0700121 @Override
122 public void handleMessage(Message msg) {
Andrew Leeda80c872015-04-15 14:09:50 -0700123 if (mCallback == null) {
Andrew Lee50aca232014-07-22 16:41:54 -0700124 return;
125 }
126
127 SomeArgs args;
128 switch (msg.what) {
129 case MSG_RECEIVE_SESSION_MODIFY_REQUEST:
Andrew Leeda80c872015-04-15 14:09:50 -0700130 mCallback.onSessionModifyRequestReceived((VideoProfile) msg.obj);
Andrew Lee50aca232014-07-22 16:41:54 -0700131 break;
132 case MSG_RECEIVE_SESSION_MODIFY_RESPONSE:
133 args = (SomeArgs) msg.obj;
134 try {
135 int status = (int) args.arg1;
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700136 VideoProfile requestProfile = (VideoProfile) args.arg2;
137 VideoProfile responseProfile = (VideoProfile) args.arg3;
Andrew Lee50aca232014-07-22 16:41:54 -0700138
Andrew Leeda80c872015-04-15 14:09:50 -0700139 mCallback.onSessionModifyResponseReceived(
Andrew Lee50aca232014-07-22 16:41:54 -0700140 status, requestProfile, responseProfile);
141 } finally {
142 args.recycle();
143 }
144 break;
145 case MSG_HANDLE_CALL_SESSION_EVENT:
Andrew Leeda80c872015-04-15 14:09:50 -0700146 mCallback.onCallSessionEvent((int) msg.obj);
Andrew Lee50aca232014-07-22 16:41:54 -0700147 break;
148 case MSG_CHANGE_PEER_DIMENSIONS:
149 args = (SomeArgs) msg.obj;
150 try {
151 int width = (int) args.arg1;
152 int height = (int) args.arg2;
Andrew Leeda80c872015-04-15 14:09:50 -0700153 mCallback.onPeerDimensionsChanged(width, height);
Andrew Lee50aca232014-07-22 16:41:54 -0700154 } finally {
155 args.recycle();
156 }
157 break;
158 case MSG_CHANGE_CALL_DATA_USAGE:
Andrew Leeda80c872015-04-15 14:09:50 -0700159 mCallback.onCallDataUsageChanged((long) msg.obj);
Andrew Lee50aca232014-07-22 16:41:54 -0700160 break;
161 case MSG_CHANGE_CAMERA_CAPABILITIES:
Andrew Leeda80c872015-04-15 14:09:50 -0700162 mCallback.onCameraCapabilitiesChanged(
Yorke Lee400470f2015-05-12 13:31:25 -0700163 (VideoProfile.CameraCapabilities) msg.obj);
Andrew Lee50aca232014-07-22 16:41:54 -0700164 break;
Rekha Kumar07366812015-03-24 16:42:31 -0700165 case MSG_CHANGE_VIDEO_QUALITY:
Tyler Gunn45382162015-05-06 08:52:27 -0700166 mVideoQuality = msg.arg1;
Andrew Leeda80c872015-04-15 14:09:50 -0700167 mCallback.onVideoQualityChanged(msg.arg1);
Rekha Kumar07366812015-03-24 16:42:31 -0700168 break;
Andrew Lee50aca232014-07-22 16:41:54 -0700169 default:
170 break;
171 }
172 }
173 };
174
Andrew Lee011728f2015-04-23 15:47:06 -0700175 private Handler mHandler;
176
Tyler Gunn45382162015-05-06 08:52:27 -0700177 VideoCallImpl(IVideoProvider videoProvider, Call call) throws RemoteException {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700178 mVideoProvider = videoProvider;
179 mVideoProvider.asBinder().linkToDeath(mDeathRecipient, 0);
Andrew Lee50aca232014-07-22 16:41:54 -0700180
181 mBinder = new VideoCallListenerBinder();
Tyler Gunn75958422015-04-15 14:23:42 -0700182 mVideoProvider.addVideoCallback(mBinder);
Tyler Gunn45382162015-05-06 08:52:27 -0700183 mCall = call;
Andrew Lee50aca232014-07-22 16:41:54 -0700184 }
185
Andrew Lee011728f2015-04-23 15:47:06 -0700186 public void destroy() {
187 unregisterCallback(mCallback);
Andrew Lee50aca232014-07-22 16:41:54 -0700188 }
189
190 /** {@inheritDoc} */
Andrew Lee011728f2015-04-23 15:47:06 -0700191 public void registerCallback(VideoCall.Callback callback) {
192 registerCallback(callback, null);
193 }
194
195 /** {@inheritDoc} */
196 public void registerCallback(VideoCall.Callback callback, Handler handler) {
197 mCallback = callback;
198 if (handler == null) {
199 mHandler = new MessageHandler(Looper.getMainLooper());
200 } else {
201 mHandler = new MessageHandler(handler.getLooper());
202 }
203 }
204
205 /** {@inheritDoc} */
206 public void unregisterCallback(VideoCall.Callback callback) {
207 if (callback != mCallback) {
208 return;
209 }
210
Etan Cohen89427242015-04-23 12:26:37 -0700211 mCallback = null;
Tyler Gunn75958422015-04-15 14:23:42 -0700212 try {
213 mVideoProvider.removeVideoCallback(mBinder);
214 } catch (RemoteException e) {
215 }
216 }
217
218 /** {@inheritDoc} */
Andrew Lee50aca232014-07-22 16:41:54 -0700219 public void setCamera(String cameraId) {
220 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700221 mVideoProvider.setCamera(cameraId);
Andrew Lee50aca232014-07-22 16:41:54 -0700222 } catch (RemoteException e) {
223 }
224 }
225
226 /** {@inheritDoc} */
227 public void setPreviewSurface(Surface surface) {
228 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700229 mVideoProvider.setPreviewSurface(surface);
Andrew Lee50aca232014-07-22 16:41:54 -0700230 } catch (RemoteException e) {
231 }
232 }
233
234 /** {@inheritDoc} */
235 public void setDisplaySurface(Surface surface) {
236 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700237 mVideoProvider.setDisplaySurface(surface);
Andrew Lee50aca232014-07-22 16:41:54 -0700238 } catch (RemoteException e) {
239 }
240 }
241
242 /** {@inheritDoc} */
243 public void setDeviceOrientation(int rotation) {
244 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700245 mVideoProvider.setDeviceOrientation(rotation);
Andrew Lee50aca232014-07-22 16:41:54 -0700246 } catch (RemoteException e) {
247 }
248 }
249
250 /** {@inheritDoc} */
251 public void setZoom(float value) {
252 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700253 mVideoProvider.setZoom(value);
Andrew Lee50aca232014-07-22 16:41:54 -0700254 } catch (RemoteException e) {
255 }
256 }
257
Tyler Gunn45382162015-05-06 08:52:27 -0700258 /**
259 * Sends a session modification request to the video provider.
260 * <p>
261 * The {@link InCallService} will create the {@code requestProfile} based on the current
262 * video state (i.e. {@link Call.Details#getVideoState()}). It is, however, possible that the
263 * video state maintained by the {@link InCallService} could get out of sync with what is known
264 * by the {@link android.telecom.Connection.VideoProvider}. To remove ambiguity, the
265 * {@link VideoCallImpl} passes along the pre-modify video profile to the {@code VideoProvider}
266 * to ensure it has full context of the requested change.
267 *
268 * @param requestProfile The requested video profile.
269 */
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700270 public void sendSessionModifyRequest(VideoProfile requestProfile) {
Andrew Lee50aca232014-07-22 16:41:54 -0700271 try {
Tyler Gunn45382162015-05-06 08:52:27 -0700272 VideoProfile originalProfile = new VideoProfile(mCall.getDetails().getVideoState(),
273 mVideoQuality);
274
275 mVideoProvider.sendSessionModifyRequest(originalProfile, requestProfile);
Andrew Lee50aca232014-07-22 16:41:54 -0700276 } catch (RemoteException e) {
277 }
278 }
279
280 /** {@inheritDoc} */
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700281 public void sendSessionModifyResponse(VideoProfile responseProfile) {
Andrew Lee50aca232014-07-22 16:41:54 -0700282 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700283 mVideoProvider.sendSessionModifyResponse(responseProfile);
Andrew Lee50aca232014-07-22 16:41:54 -0700284 } catch (RemoteException e) {
285 }
286 }
287
288 /** {@inheritDoc} */
289 public void requestCameraCapabilities() {
290 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700291 mVideoProvider.requestCameraCapabilities();
Andrew Lee50aca232014-07-22 16:41:54 -0700292 } catch (RemoteException e) {
293 }
294 }
295
296 /** {@inheritDoc} */
297 public void requestCallDataUsage() {
298 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700299 mVideoProvider.requestCallDataUsage();
Andrew Lee50aca232014-07-22 16:41:54 -0700300 } catch (RemoteException e) {
301 }
302 }
303
304 /** {@inheritDoc} */
305 public void setPauseImage(String uri) {
306 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700307 mVideoProvider.setPauseImage(uri);
Andrew Lee50aca232014-07-22 16:41:54 -0700308 } catch (RemoteException e) {
309 }
310 }
Rekha Kumar07366812015-03-24 16:42:31 -0700311}