blob: 2c7fecb5e3c449a753d507d75ef2c451b3168a16 [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
Mathew Inwood42346d12018-08-01 11:33:05 +010019import android.annotation.UnsupportedAppUsage;
Yorke Lee32f24732015-05-12 16:18:03 -070020import android.net.Uri;
Andrew Lee50aca232014-07-22 16:41:54 -070021import android.os.Handler;
22import android.os.IBinder;
23import android.os.Looper;
24import android.os.Message;
25import android.os.RemoteException;
Tyler Gunnef9f6f92014-09-12 22:16:17 -070026import android.telecom.InCallService.VideoCall;
Andrew Lee50aca232014-07-22 16:41:54 -070027import android.view.Surface;
28
Brad Ebinger0d55a302017-03-20 13:16:28 -070029import com.android.internal.annotations.VisibleForTesting;
Andrew Lee50aca232014-07-22 16:41:54 -070030import com.android.internal.os.SomeArgs;
Tyler Gunnef9f6f92014-09-12 22:16:17 -070031import com.android.internal.telecom.IVideoCallback;
32import com.android.internal.telecom.IVideoProvider;
Andrew Lee50aca232014-07-22 16:41:54 -070033
34/**
35 * Implementation of a Video Call, which allows InCallUi to communicate commands to the underlying
Ihab Awadb19a0bc2014-08-07 19:46:01 -070036 * {@link Connection.VideoProvider}, and direct callbacks from the
37 * {@link Connection.VideoProvider} to the appropriate {@link VideoCall.Listener}.
38 *
39 * {@hide}
Andrew Lee50aca232014-07-22 16:41:54 -070040 */
41public class VideoCallImpl extends VideoCall {
Andrew Lee50aca232014-07-22 16:41:54 -070042
Ihab Awadb19a0bc2014-08-07 19:46:01 -070043 private final IVideoProvider mVideoProvider;
Andrew Lee50aca232014-07-22 16:41:54 -070044 private final VideoCallListenerBinder mBinder;
Andrew Leeda80c872015-04-15 14:09:50 -070045 private VideoCall.Callback mCallback;
Tyler Gunn45382162015-05-06 08:52:27 -070046 private int mVideoQuality = VideoProfile.QUALITY_UNKNOWN;
Tyler Gunn584ba6c2015-12-08 10:53:41 -080047 private int mVideoState = VideoProfile.STATE_AUDIO_ONLY;
Tyler Gunnbf9c6fd2016-11-09 10:19:23 -080048 private final String mCallingPackageName;
Brad Ebinger0d55a302017-03-20 13:16:28 -070049
50 private int mTargetSdkVersion;
Andrew Lee50aca232014-07-22 16:41:54 -070051
52 private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
53 @Override
54 public void binderDied() {
Ihab Awadb19a0bc2014-08-07 19:46:01 -070055 mVideoProvider.asBinder().unlinkToDeath(this, 0);
Andrew Lee50aca232014-07-22 16:41:54 -070056 }
57 };
58
59 /**
Ihab Awadb19a0bc2014-08-07 19:46:01 -070060 * IVideoCallback stub implementation.
Andrew Lee50aca232014-07-22 16:41:54 -070061 */
Ihab Awadb19a0bc2014-08-07 19:46:01 -070062 private final class VideoCallListenerBinder extends IVideoCallback.Stub {
Andrew Lee50aca232014-07-22 16:41:54 -070063 @Override
Ihab Awadb19a0bc2014-08-07 19:46:01 -070064 public void receiveSessionModifyRequest(VideoProfile videoProfile) {
Tyler Gunne988cf72015-05-28 15:47:06 -070065 if (mHandler == null) {
66 return;
67 }
Andrew Lee011728f2015-04-23 15:47:06 -070068 mHandler.obtainMessage(MessageHandler.MSG_RECEIVE_SESSION_MODIFY_REQUEST,
Ihab Awadb19a0bc2014-08-07 19:46:01 -070069 videoProfile).sendToTarget();
Tyler Gunne988cf72015-05-28 15:47:06 -070070
Andrew Lee50aca232014-07-22 16:41:54 -070071 }
72
73 @Override
Ihab Awadb19a0bc2014-08-07 19:46:01 -070074 public void receiveSessionModifyResponse(int status, VideoProfile requestProfile,
75 VideoProfile responseProfile) {
Tyler Gunne988cf72015-05-28 15:47:06 -070076 if (mHandler == null) {
77 return;
78 }
Andrew Lee50aca232014-07-22 16:41:54 -070079 SomeArgs args = SomeArgs.obtain();
80 args.arg1 = status;
81 args.arg2 = requestProfile;
82 args.arg3 = responseProfile;
Andrew Lee011728f2015-04-23 15:47:06 -070083 mHandler.obtainMessage(MessageHandler.MSG_RECEIVE_SESSION_MODIFY_RESPONSE, args)
84 .sendToTarget();
Andrew Lee50aca232014-07-22 16:41:54 -070085 }
86
87 @Override
88 public void handleCallSessionEvent(int event) {
Tyler Gunne988cf72015-05-28 15:47:06 -070089 if (mHandler == null) {
90 return;
91 }
Andrew Lee011728f2015-04-23 15:47:06 -070092 mHandler.obtainMessage(MessageHandler.MSG_HANDLE_CALL_SESSION_EVENT, event)
93 .sendToTarget();
Andrew Lee50aca232014-07-22 16:41:54 -070094 }
95
96 @Override
97 public void changePeerDimensions(int width, int height) {
Tyler Gunne988cf72015-05-28 15:47:06 -070098 if (mHandler == null) {
99 return;
100 }
Andrew Lee50aca232014-07-22 16:41:54 -0700101 SomeArgs args = SomeArgs.obtain();
102 args.arg1 = width;
103 args.arg2 = height;
Andrew Lee011728f2015-04-23 15:47:06 -0700104 mHandler.obtainMessage(MessageHandler.MSG_CHANGE_PEER_DIMENSIONS, args).sendToTarget();
Andrew Lee50aca232014-07-22 16:41:54 -0700105 }
106
107 @Override
Rekha Kumar07366812015-03-24 16:42:31 -0700108 public void changeVideoQuality(int videoQuality) {
Tyler Gunne988cf72015-05-28 15:47:06 -0700109 if (mHandler == null) {
110 return;
111 }
Andrew Lee011728f2015-04-23 15:47:06 -0700112 mHandler.obtainMessage(MessageHandler.MSG_CHANGE_VIDEO_QUALITY, videoQuality, 0)
113 .sendToTarget();
Rekha Kumar07366812015-03-24 16:42:31 -0700114 }
115
116 @Override
117 public void changeCallDataUsage(long dataUsage) {
Tyler Gunne988cf72015-05-28 15:47:06 -0700118 if (mHandler == null) {
119 return;
120 }
Andrew Lee011728f2015-04-23 15:47:06 -0700121 mHandler.obtainMessage(MessageHandler.MSG_CHANGE_CALL_DATA_USAGE, dataUsage)
122 .sendToTarget();
Andrew Lee50aca232014-07-22 16:41:54 -0700123 }
124
125 @Override
Yorke Lee400470f2015-05-12 13:31:25 -0700126 public void changeCameraCapabilities(VideoProfile.CameraCapabilities cameraCapabilities) {
Tyler Gunne988cf72015-05-28 15:47:06 -0700127 if (mHandler == null) {
128 return;
129 }
Andrew Lee011728f2015-04-23 15:47:06 -0700130 mHandler.obtainMessage(MessageHandler.MSG_CHANGE_CAMERA_CAPABILITIES,
Andrew Lee50aca232014-07-22 16:41:54 -0700131 cameraCapabilities).sendToTarget();
132 }
133 }
134
135 /** Default handler used to consolidate binder method calls onto a single thread. */
Andrew Lee011728f2015-04-23 15:47:06 -0700136 private final class MessageHandler extends Handler {
137 private static final int MSG_RECEIVE_SESSION_MODIFY_REQUEST = 1;
138 private static final int MSG_RECEIVE_SESSION_MODIFY_RESPONSE = 2;
139 private static final int MSG_HANDLE_CALL_SESSION_EVENT = 3;
140 private static final int MSG_CHANGE_PEER_DIMENSIONS = 4;
141 private static final int MSG_CHANGE_CALL_DATA_USAGE = 5;
142 private static final int MSG_CHANGE_CAMERA_CAPABILITIES = 6;
143 private static final int MSG_CHANGE_VIDEO_QUALITY = 7;
144
145 public MessageHandler(Looper looper) {
146 super(looper);
147 }
148
Andrew Lee50aca232014-07-22 16:41:54 -0700149 @Override
150 public void handleMessage(Message msg) {
Andrew Leeda80c872015-04-15 14:09:50 -0700151 if (mCallback == null) {
Andrew Lee50aca232014-07-22 16:41:54 -0700152 return;
153 }
154
155 SomeArgs args;
156 switch (msg.what) {
157 case MSG_RECEIVE_SESSION_MODIFY_REQUEST:
Andrew Leeda80c872015-04-15 14:09:50 -0700158 mCallback.onSessionModifyRequestReceived((VideoProfile) msg.obj);
Andrew Lee50aca232014-07-22 16:41:54 -0700159 break;
160 case MSG_RECEIVE_SESSION_MODIFY_RESPONSE:
161 args = (SomeArgs) msg.obj;
162 try {
163 int status = (int) args.arg1;
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700164 VideoProfile requestProfile = (VideoProfile) args.arg2;
165 VideoProfile responseProfile = (VideoProfile) args.arg3;
Andrew Lee50aca232014-07-22 16:41:54 -0700166
Andrew Leeda80c872015-04-15 14:09:50 -0700167 mCallback.onSessionModifyResponseReceived(
Andrew Lee50aca232014-07-22 16:41:54 -0700168 status, requestProfile, responseProfile);
169 } finally {
170 args.recycle();
171 }
172 break;
173 case MSG_HANDLE_CALL_SESSION_EVENT:
Andrew Leeda80c872015-04-15 14:09:50 -0700174 mCallback.onCallSessionEvent((int) msg.obj);
Andrew Lee50aca232014-07-22 16:41:54 -0700175 break;
176 case MSG_CHANGE_PEER_DIMENSIONS:
177 args = (SomeArgs) msg.obj;
178 try {
179 int width = (int) args.arg1;
180 int height = (int) args.arg2;
Andrew Leeda80c872015-04-15 14:09:50 -0700181 mCallback.onPeerDimensionsChanged(width, height);
Andrew Lee50aca232014-07-22 16:41:54 -0700182 } finally {
183 args.recycle();
184 }
185 break;
186 case MSG_CHANGE_CALL_DATA_USAGE:
Andrew Leeda80c872015-04-15 14:09:50 -0700187 mCallback.onCallDataUsageChanged((long) msg.obj);
Andrew Lee50aca232014-07-22 16:41:54 -0700188 break;
189 case MSG_CHANGE_CAMERA_CAPABILITIES:
Andrew Leeda80c872015-04-15 14:09:50 -0700190 mCallback.onCameraCapabilitiesChanged(
Yorke Lee400470f2015-05-12 13:31:25 -0700191 (VideoProfile.CameraCapabilities) msg.obj);
Andrew Lee50aca232014-07-22 16:41:54 -0700192 break;
Rekha Kumar07366812015-03-24 16:42:31 -0700193 case MSG_CHANGE_VIDEO_QUALITY:
Tyler Gunn45382162015-05-06 08:52:27 -0700194 mVideoQuality = msg.arg1;
Andrew Leeda80c872015-04-15 14:09:50 -0700195 mCallback.onVideoQualityChanged(msg.arg1);
Rekha Kumar07366812015-03-24 16:42:31 -0700196 break;
Andrew Lee50aca232014-07-22 16:41:54 -0700197 default:
198 break;
199 }
200 }
201 };
202
Andrew Lee011728f2015-04-23 15:47:06 -0700203 private Handler mHandler;
204
Tyler Gunn159f35c2017-03-02 09:28:37 -0800205 VideoCallImpl(IVideoProvider videoProvider, String callingPackageName, int targetSdkVersion)
206 throws RemoteException {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700207 mVideoProvider = videoProvider;
208 mVideoProvider.asBinder().linkToDeath(mDeathRecipient, 0);
Andrew Lee50aca232014-07-22 16:41:54 -0700209
210 mBinder = new VideoCallListenerBinder();
Tyler Gunn75958422015-04-15 14:23:42 -0700211 mVideoProvider.addVideoCallback(mBinder);
Tyler Gunnbf9c6fd2016-11-09 10:19:23 -0800212 mCallingPackageName = callingPackageName;
Brad Ebinger0d55a302017-03-20 13:16:28 -0700213 setTargetSdkVersion(targetSdkVersion);
214 }
215
216 @VisibleForTesting
217 public void setTargetSdkVersion(int sdkVersion) {
218 mTargetSdkVersion = sdkVersion;
Andrew Lee50aca232014-07-22 16:41:54 -0700219 }
220
Mathew Inwood42346d12018-08-01 11:33:05 +0100221 @UnsupportedAppUsage
Andrew Lee011728f2015-04-23 15:47:06 -0700222 public void destroy() {
223 unregisterCallback(mCallback);
Andrew Lee50aca232014-07-22 16:41:54 -0700224 }
225
226 /** {@inheritDoc} */
Andrew Lee011728f2015-04-23 15:47:06 -0700227 public void registerCallback(VideoCall.Callback callback) {
228 registerCallback(callback, null);
229 }
230
231 /** {@inheritDoc} */
232 public void registerCallback(VideoCall.Callback callback, Handler handler) {
233 mCallback = callback;
234 if (handler == null) {
235 mHandler = new MessageHandler(Looper.getMainLooper());
236 } else {
237 mHandler = new MessageHandler(handler.getLooper());
238 }
239 }
240
241 /** {@inheritDoc} */
242 public void unregisterCallback(VideoCall.Callback callback) {
243 if (callback != mCallback) {
244 return;
245 }
246
Etan Cohen89427242015-04-23 12:26:37 -0700247 mCallback = null;
Tyler Gunn75958422015-04-15 14:23:42 -0700248 try {
249 mVideoProvider.removeVideoCallback(mBinder);
250 } catch (RemoteException e) {
251 }
252 }
253
254 /** {@inheritDoc} */
Andrew Lee50aca232014-07-22 16:41:54 -0700255 public void setCamera(String cameraId) {
256 try {
Tyler Gunnbf9c6fd2016-11-09 10:19:23 -0800257 Log.w(this, "setCamera: cameraId=%s, calling=%s", cameraId, mCallingPackageName);
Tyler Gunn159f35c2017-03-02 09:28:37 -0800258 mVideoProvider.setCamera(cameraId, mCallingPackageName, mTargetSdkVersion);
Andrew Lee50aca232014-07-22 16:41:54 -0700259 } catch (RemoteException e) {
260 }
261 }
262
263 /** {@inheritDoc} */
264 public void setPreviewSurface(Surface surface) {
265 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700266 mVideoProvider.setPreviewSurface(surface);
Andrew Lee50aca232014-07-22 16:41:54 -0700267 } catch (RemoteException e) {
268 }
269 }
270
271 /** {@inheritDoc} */
272 public void setDisplaySurface(Surface surface) {
273 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700274 mVideoProvider.setDisplaySurface(surface);
Andrew Lee50aca232014-07-22 16:41:54 -0700275 } catch (RemoteException e) {
276 }
277 }
278
279 /** {@inheritDoc} */
280 public void setDeviceOrientation(int rotation) {
281 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700282 mVideoProvider.setDeviceOrientation(rotation);
Andrew Lee50aca232014-07-22 16:41:54 -0700283 } catch (RemoteException e) {
284 }
285 }
286
287 /** {@inheritDoc} */
288 public void setZoom(float value) {
289 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700290 mVideoProvider.setZoom(value);
Andrew Lee50aca232014-07-22 16:41:54 -0700291 } catch (RemoteException e) {
292 }
293 }
294
Tyler Gunn45382162015-05-06 08:52:27 -0700295 /**
296 * Sends a session modification request to the video provider.
297 * <p>
298 * The {@link InCallService} will create the {@code requestProfile} based on the current
299 * video state (i.e. {@link Call.Details#getVideoState()}). It is, however, possible that the
300 * video state maintained by the {@link InCallService} could get out of sync with what is known
301 * by the {@link android.telecom.Connection.VideoProvider}. To remove ambiguity, the
302 * {@link VideoCallImpl} passes along the pre-modify video profile to the {@code VideoProvider}
303 * to ensure it has full context of the requested change.
304 *
305 * @param requestProfile The requested video profile.
306 */
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700307 public void sendSessionModifyRequest(VideoProfile requestProfile) {
Andrew Lee50aca232014-07-22 16:41:54 -0700308 try {
Tyler Gunn584ba6c2015-12-08 10:53:41 -0800309 VideoProfile originalProfile = new VideoProfile(mVideoState, mVideoQuality);
Tyler Gunn45382162015-05-06 08:52:27 -0700310
311 mVideoProvider.sendSessionModifyRequest(originalProfile, requestProfile);
Andrew Lee50aca232014-07-22 16:41:54 -0700312 } catch (RemoteException e) {
313 }
314 }
315
316 /** {@inheritDoc} */
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700317 public void sendSessionModifyResponse(VideoProfile responseProfile) {
Andrew Lee50aca232014-07-22 16:41:54 -0700318 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700319 mVideoProvider.sendSessionModifyResponse(responseProfile);
Andrew Lee50aca232014-07-22 16:41:54 -0700320 } catch (RemoteException e) {
321 }
322 }
323
324 /** {@inheritDoc} */
325 public void requestCameraCapabilities() {
326 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700327 mVideoProvider.requestCameraCapabilities();
Andrew Lee50aca232014-07-22 16:41:54 -0700328 } catch (RemoteException e) {
329 }
330 }
331
332 /** {@inheritDoc} */
333 public void requestCallDataUsage() {
334 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700335 mVideoProvider.requestCallDataUsage();
Andrew Lee50aca232014-07-22 16:41:54 -0700336 } catch (RemoteException e) {
337 }
338 }
339
340 /** {@inheritDoc} */
Yorke Lee32f24732015-05-12 16:18:03 -0700341 public void setPauseImage(Uri uri) {
Andrew Lee50aca232014-07-22 16:41:54 -0700342 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700343 mVideoProvider.setPauseImage(uri);
Andrew Lee50aca232014-07-22 16:41:54 -0700344 } catch (RemoteException e) {
345 }
346 }
Tyler Gunn584ba6c2015-12-08 10:53:41 -0800347
348 /**
349 * Sets the video state for the current video call.
350 * @param videoState the new video state.
351 */
352 public void setVideoState(int videoState) {
353 mVideoState = videoState;
354 }
Rekha Kumar07366812015-03-24 16:42:31 -0700355}