blob: d8ede5c2131642ed5b51f7fb0e8fab2f2dbd15af [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
Yorke Lee32f24732015-05-12 16:18:03 -070019import android.net.Uri;
Andrew Lee50aca232014-07-22 16:41:54 -070020import android.os.Handler;
21import android.os.IBinder;
22import android.os.Looper;
23import android.os.Message;
24import android.os.RemoteException;
Tyler Gunnef9f6f92014-09-12 22:16:17 -070025import android.telecom.InCallService.VideoCall;
Andrew Lee50aca232014-07-22 16:41:54 -070026import android.view.Surface;
27
28import com.android.internal.os.SomeArgs;
Tyler Gunnef9f6f92014-09-12 22:16:17 -070029import com.android.internal.telecom.IVideoCallback;
30import com.android.internal.telecom.IVideoProvider;
Andrew Lee50aca232014-07-22 16:41:54 -070031
32/**
33 * Implementation of a Video Call, which allows InCallUi to communicate commands to the underlying
Ihab Awadb19a0bc2014-08-07 19:46:01 -070034 * {@link Connection.VideoProvider}, and direct callbacks from the
35 * {@link Connection.VideoProvider} to the appropriate {@link VideoCall.Listener}.
36 *
37 * {@hide}
Andrew Lee50aca232014-07-22 16:41:54 -070038 */
39public class VideoCallImpl extends VideoCall {
Andrew Lee50aca232014-07-22 16:41:54 -070040
Ihab Awadb19a0bc2014-08-07 19:46:01 -070041 private final IVideoProvider mVideoProvider;
Andrew Lee50aca232014-07-22 16:41:54 -070042 private final VideoCallListenerBinder mBinder;
Andrew Leeda80c872015-04-15 14:09:50 -070043 private VideoCall.Callback mCallback;
Tyler Gunn45382162015-05-06 08:52:27 -070044 private int mVideoQuality = VideoProfile.QUALITY_UNKNOWN;
Tyler Gunn584ba6c2015-12-08 10:53:41 -080045 private int mVideoState = VideoProfile.STATE_AUDIO_ONLY;
Tyler Gunnbf9c6fd2016-11-09 10:19:23 -080046 private final String mCallingPackageName;
Andrew Lee50aca232014-07-22 16:41:54 -070047
48 private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
49 @Override
50 public void binderDied() {
Ihab Awadb19a0bc2014-08-07 19:46:01 -070051 mVideoProvider.asBinder().unlinkToDeath(this, 0);
Andrew Lee50aca232014-07-22 16:41:54 -070052 }
53 };
54
55 /**
Ihab Awadb19a0bc2014-08-07 19:46:01 -070056 * IVideoCallback stub implementation.
Andrew Lee50aca232014-07-22 16:41:54 -070057 */
Ihab Awadb19a0bc2014-08-07 19:46:01 -070058 private final class VideoCallListenerBinder extends IVideoCallback.Stub {
Andrew Lee50aca232014-07-22 16:41:54 -070059 @Override
Ihab Awadb19a0bc2014-08-07 19:46:01 -070060 public void receiveSessionModifyRequest(VideoProfile videoProfile) {
Tyler Gunne988cf72015-05-28 15:47:06 -070061 if (mHandler == null) {
62 return;
63 }
Andrew Lee011728f2015-04-23 15:47:06 -070064 mHandler.obtainMessage(MessageHandler.MSG_RECEIVE_SESSION_MODIFY_REQUEST,
Ihab Awadb19a0bc2014-08-07 19:46:01 -070065 videoProfile).sendToTarget();
Tyler Gunne988cf72015-05-28 15:47:06 -070066
Andrew Lee50aca232014-07-22 16:41:54 -070067 }
68
69 @Override
Ihab Awadb19a0bc2014-08-07 19:46:01 -070070 public void receiveSessionModifyResponse(int status, VideoProfile requestProfile,
71 VideoProfile responseProfile) {
Tyler Gunne988cf72015-05-28 15:47:06 -070072 if (mHandler == null) {
73 return;
74 }
Andrew Lee50aca232014-07-22 16:41:54 -070075 SomeArgs args = SomeArgs.obtain();
76 args.arg1 = status;
77 args.arg2 = requestProfile;
78 args.arg3 = responseProfile;
Andrew Lee011728f2015-04-23 15:47:06 -070079 mHandler.obtainMessage(MessageHandler.MSG_RECEIVE_SESSION_MODIFY_RESPONSE, args)
80 .sendToTarget();
Andrew Lee50aca232014-07-22 16:41:54 -070081 }
82
83 @Override
84 public void handleCallSessionEvent(int event) {
Tyler Gunne988cf72015-05-28 15:47:06 -070085 if (mHandler == null) {
86 return;
87 }
Andrew Lee011728f2015-04-23 15:47:06 -070088 mHandler.obtainMessage(MessageHandler.MSG_HANDLE_CALL_SESSION_EVENT, event)
89 .sendToTarget();
Andrew Lee50aca232014-07-22 16:41:54 -070090 }
91
92 @Override
93 public void changePeerDimensions(int width, int height) {
Tyler Gunne988cf72015-05-28 15:47:06 -070094 if (mHandler == null) {
95 return;
96 }
Andrew Lee50aca232014-07-22 16:41:54 -070097 SomeArgs args = SomeArgs.obtain();
98 args.arg1 = width;
99 args.arg2 = height;
Andrew Lee011728f2015-04-23 15:47:06 -0700100 mHandler.obtainMessage(MessageHandler.MSG_CHANGE_PEER_DIMENSIONS, args).sendToTarget();
Andrew Lee50aca232014-07-22 16:41:54 -0700101 }
102
103 @Override
Rekha Kumar07366812015-03-24 16:42:31 -0700104 public void changeVideoQuality(int videoQuality) {
Tyler Gunne988cf72015-05-28 15:47:06 -0700105 if (mHandler == null) {
106 return;
107 }
Andrew Lee011728f2015-04-23 15:47:06 -0700108 mHandler.obtainMessage(MessageHandler.MSG_CHANGE_VIDEO_QUALITY, videoQuality, 0)
109 .sendToTarget();
Rekha Kumar07366812015-03-24 16:42:31 -0700110 }
111
112 @Override
113 public void changeCallDataUsage(long dataUsage) {
Tyler Gunne988cf72015-05-28 15:47:06 -0700114 if (mHandler == null) {
115 return;
116 }
Andrew Lee011728f2015-04-23 15:47:06 -0700117 mHandler.obtainMessage(MessageHandler.MSG_CHANGE_CALL_DATA_USAGE, dataUsage)
118 .sendToTarget();
Andrew Lee50aca232014-07-22 16:41:54 -0700119 }
120
121 @Override
Yorke Lee400470f2015-05-12 13:31:25 -0700122 public void changeCameraCapabilities(VideoProfile.CameraCapabilities cameraCapabilities) {
Tyler Gunne988cf72015-05-28 15:47:06 -0700123 if (mHandler == null) {
124 return;
125 }
Andrew Lee011728f2015-04-23 15:47:06 -0700126 mHandler.obtainMessage(MessageHandler.MSG_CHANGE_CAMERA_CAPABILITIES,
Andrew Lee50aca232014-07-22 16:41:54 -0700127 cameraCapabilities).sendToTarget();
128 }
129 }
130
131 /** Default handler used to consolidate binder method calls onto a single thread. */
Andrew Lee011728f2015-04-23 15:47:06 -0700132 private final class MessageHandler extends Handler {
133 private static final int MSG_RECEIVE_SESSION_MODIFY_REQUEST = 1;
134 private static final int MSG_RECEIVE_SESSION_MODIFY_RESPONSE = 2;
135 private static final int MSG_HANDLE_CALL_SESSION_EVENT = 3;
136 private static final int MSG_CHANGE_PEER_DIMENSIONS = 4;
137 private static final int MSG_CHANGE_CALL_DATA_USAGE = 5;
138 private static final int MSG_CHANGE_CAMERA_CAPABILITIES = 6;
139 private static final int MSG_CHANGE_VIDEO_QUALITY = 7;
140
141 public MessageHandler(Looper looper) {
142 super(looper);
143 }
144
Andrew Lee50aca232014-07-22 16:41:54 -0700145 @Override
146 public void handleMessage(Message msg) {
Andrew Leeda80c872015-04-15 14:09:50 -0700147 if (mCallback == null) {
Andrew Lee50aca232014-07-22 16:41:54 -0700148 return;
149 }
150
151 SomeArgs args;
152 switch (msg.what) {
153 case MSG_RECEIVE_SESSION_MODIFY_REQUEST:
Andrew Leeda80c872015-04-15 14:09:50 -0700154 mCallback.onSessionModifyRequestReceived((VideoProfile) msg.obj);
Andrew Lee50aca232014-07-22 16:41:54 -0700155 break;
156 case MSG_RECEIVE_SESSION_MODIFY_RESPONSE:
157 args = (SomeArgs) msg.obj;
158 try {
159 int status = (int) args.arg1;
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700160 VideoProfile requestProfile = (VideoProfile) args.arg2;
161 VideoProfile responseProfile = (VideoProfile) args.arg3;
Andrew Lee50aca232014-07-22 16:41:54 -0700162
Andrew Leeda80c872015-04-15 14:09:50 -0700163 mCallback.onSessionModifyResponseReceived(
Andrew Lee50aca232014-07-22 16:41:54 -0700164 status, requestProfile, responseProfile);
165 } finally {
166 args.recycle();
167 }
168 break;
169 case MSG_HANDLE_CALL_SESSION_EVENT:
Andrew Leeda80c872015-04-15 14:09:50 -0700170 mCallback.onCallSessionEvent((int) msg.obj);
Andrew Lee50aca232014-07-22 16:41:54 -0700171 break;
172 case MSG_CHANGE_PEER_DIMENSIONS:
173 args = (SomeArgs) msg.obj;
174 try {
175 int width = (int) args.arg1;
176 int height = (int) args.arg2;
Andrew Leeda80c872015-04-15 14:09:50 -0700177 mCallback.onPeerDimensionsChanged(width, height);
Andrew Lee50aca232014-07-22 16:41:54 -0700178 } finally {
179 args.recycle();
180 }
181 break;
182 case MSG_CHANGE_CALL_DATA_USAGE:
Andrew Leeda80c872015-04-15 14:09:50 -0700183 mCallback.onCallDataUsageChanged((long) msg.obj);
Andrew Lee50aca232014-07-22 16:41:54 -0700184 break;
185 case MSG_CHANGE_CAMERA_CAPABILITIES:
Andrew Leeda80c872015-04-15 14:09:50 -0700186 mCallback.onCameraCapabilitiesChanged(
Yorke Lee400470f2015-05-12 13:31:25 -0700187 (VideoProfile.CameraCapabilities) msg.obj);
Andrew Lee50aca232014-07-22 16:41:54 -0700188 break;
Rekha Kumar07366812015-03-24 16:42:31 -0700189 case MSG_CHANGE_VIDEO_QUALITY:
Tyler Gunn45382162015-05-06 08:52:27 -0700190 mVideoQuality = msg.arg1;
Andrew Leeda80c872015-04-15 14:09:50 -0700191 mCallback.onVideoQualityChanged(msg.arg1);
Rekha Kumar07366812015-03-24 16:42:31 -0700192 break;
Andrew Lee50aca232014-07-22 16:41:54 -0700193 default:
194 break;
195 }
196 }
197 };
198
Andrew Lee011728f2015-04-23 15:47:06 -0700199 private Handler mHandler;
200
Tyler Gunnbf9c6fd2016-11-09 10:19:23 -0800201 VideoCallImpl(IVideoProvider videoProvider, String callingPackageName) throws RemoteException {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700202 mVideoProvider = videoProvider;
203 mVideoProvider.asBinder().linkToDeath(mDeathRecipient, 0);
Andrew Lee50aca232014-07-22 16:41:54 -0700204
205 mBinder = new VideoCallListenerBinder();
Tyler Gunn75958422015-04-15 14:23:42 -0700206 mVideoProvider.addVideoCallback(mBinder);
Tyler Gunnbf9c6fd2016-11-09 10:19:23 -0800207 mCallingPackageName = callingPackageName;
Andrew Lee50aca232014-07-22 16:41:54 -0700208 }
209
Andrew Lee011728f2015-04-23 15:47:06 -0700210 public void destroy() {
211 unregisterCallback(mCallback);
Andrew Lee50aca232014-07-22 16:41:54 -0700212 }
213
214 /** {@inheritDoc} */
Andrew Lee011728f2015-04-23 15:47:06 -0700215 public void registerCallback(VideoCall.Callback callback) {
216 registerCallback(callback, null);
217 }
218
219 /** {@inheritDoc} */
220 public void registerCallback(VideoCall.Callback callback, Handler handler) {
221 mCallback = callback;
222 if (handler == null) {
223 mHandler = new MessageHandler(Looper.getMainLooper());
224 } else {
225 mHandler = new MessageHandler(handler.getLooper());
226 }
227 }
228
229 /** {@inheritDoc} */
230 public void unregisterCallback(VideoCall.Callback callback) {
231 if (callback != mCallback) {
232 return;
233 }
234
Etan Cohen89427242015-04-23 12:26:37 -0700235 mCallback = null;
Tyler Gunn75958422015-04-15 14:23:42 -0700236 try {
237 mVideoProvider.removeVideoCallback(mBinder);
238 } catch (RemoteException e) {
239 }
240 }
241
242 /** {@inheritDoc} */
Andrew Lee50aca232014-07-22 16:41:54 -0700243 public void setCamera(String cameraId) {
244 try {
Tyler Gunnbf9c6fd2016-11-09 10:19:23 -0800245 Log.w(this, "setCamera: cameraId=%s, calling=%s", cameraId, mCallingPackageName);
246 mVideoProvider.setCamera(cameraId, mCallingPackageName);
Andrew Lee50aca232014-07-22 16:41:54 -0700247 } catch (RemoteException e) {
248 }
249 }
250
251 /** {@inheritDoc} */
252 public void setPreviewSurface(Surface surface) {
253 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700254 mVideoProvider.setPreviewSurface(surface);
Andrew Lee50aca232014-07-22 16:41:54 -0700255 } catch (RemoteException e) {
256 }
257 }
258
259 /** {@inheritDoc} */
260 public void setDisplaySurface(Surface surface) {
261 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700262 mVideoProvider.setDisplaySurface(surface);
Andrew Lee50aca232014-07-22 16:41:54 -0700263 } catch (RemoteException e) {
264 }
265 }
266
267 /** {@inheritDoc} */
268 public void setDeviceOrientation(int rotation) {
269 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700270 mVideoProvider.setDeviceOrientation(rotation);
Andrew Lee50aca232014-07-22 16:41:54 -0700271 } catch (RemoteException e) {
272 }
273 }
274
275 /** {@inheritDoc} */
276 public void setZoom(float value) {
277 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700278 mVideoProvider.setZoom(value);
Andrew Lee50aca232014-07-22 16:41:54 -0700279 } catch (RemoteException e) {
280 }
281 }
282
Tyler Gunn45382162015-05-06 08:52:27 -0700283 /**
284 * Sends a session modification request to the video provider.
285 * <p>
286 * The {@link InCallService} will create the {@code requestProfile} based on the current
287 * video state (i.e. {@link Call.Details#getVideoState()}). It is, however, possible that the
288 * video state maintained by the {@link InCallService} could get out of sync with what is known
289 * by the {@link android.telecom.Connection.VideoProvider}. To remove ambiguity, the
290 * {@link VideoCallImpl} passes along the pre-modify video profile to the {@code VideoProvider}
291 * to ensure it has full context of the requested change.
292 *
293 * @param requestProfile The requested video profile.
294 */
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700295 public void sendSessionModifyRequest(VideoProfile requestProfile) {
Andrew Lee50aca232014-07-22 16:41:54 -0700296 try {
Tyler Gunn584ba6c2015-12-08 10:53:41 -0800297 VideoProfile originalProfile = new VideoProfile(mVideoState, mVideoQuality);
Tyler Gunn45382162015-05-06 08:52:27 -0700298
299 mVideoProvider.sendSessionModifyRequest(originalProfile, requestProfile);
Andrew Lee50aca232014-07-22 16:41:54 -0700300 } catch (RemoteException e) {
301 }
302 }
303
304 /** {@inheritDoc} */
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700305 public void sendSessionModifyResponse(VideoProfile responseProfile) {
Andrew Lee50aca232014-07-22 16:41:54 -0700306 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700307 mVideoProvider.sendSessionModifyResponse(responseProfile);
Andrew Lee50aca232014-07-22 16:41:54 -0700308 } catch (RemoteException e) {
309 }
310 }
311
312 /** {@inheritDoc} */
313 public void requestCameraCapabilities() {
314 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700315 mVideoProvider.requestCameraCapabilities();
Andrew Lee50aca232014-07-22 16:41:54 -0700316 } catch (RemoteException e) {
317 }
318 }
319
320 /** {@inheritDoc} */
321 public void requestCallDataUsage() {
322 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700323 mVideoProvider.requestCallDataUsage();
Andrew Lee50aca232014-07-22 16:41:54 -0700324 } catch (RemoteException e) {
325 }
326 }
327
328 /** {@inheritDoc} */
Yorke Lee32f24732015-05-12 16:18:03 -0700329 public void setPauseImage(Uri uri) {
Andrew Lee50aca232014-07-22 16:41:54 -0700330 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700331 mVideoProvider.setPauseImage(uri);
Andrew Lee50aca232014-07-22 16:41:54 -0700332 } catch (RemoteException e) {
333 }
334 }
Tyler Gunn584ba6c2015-12-08 10:53:41 -0800335
336 /**
337 * Sets the video state for the current video call.
338 * @param videoState the new video state.
339 */
340 public void setVideoState(int videoState) {
341 mVideoState = videoState;
342 }
Rekha Kumar07366812015-03-24 16:42:31 -0700343}