blob: cb74012e2b817c421a1b92fa2205afa58be3974b [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;
Tyler Gunn17933eb2019-03-05 13:58:45 -080021import android.os.Build;
Andrew Lee50aca232014-07-22 16:41:54 -070022import android.os.Handler;
23import android.os.IBinder;
24import android.os.Looper;
25import android.os.Message;
26import android.os.RemoteException;
Tyler Gunnef9f6f92014-09-12 22:16:17 -070027import android.telecom.InCallService.VideoCall;
Andrew Lee50aca232014-07-22 16:41:54 -070028import android.view.Surface;
29
Brad Ebinger0d55a302017-03-20 13:16:28 -070030import com.android.internal.annotations.VisibleForTesting;
Andrew Lee50aca232014-07-22 16:41:54 -070031import com.android.internal.os.SomeArgs;
Tyler Gunnef9f6f92014-09-12 22:16:17 -070032import com.android.internal.telecom.IVideoCallback;
33import com.android.internal.telecom.IVideoProvider;
Andrew Lee50aca232014-07-22 16:41:54 -070034
35/**
36 * Implementation of a Video Call, which allows InCallUi to communicate commands to the underlying
Ihab Awadb19a0bc2014-08-07 19:46:01 -070037 * {@link Connection.VideoProvider}, and direct callbacks from the
38 * {@link Connection.VideoProvider} to the appropriate {@link VideoCall.Listener}.
39 *
40 * {@hide}
Andrew Lee50aca232014-07-22 16:41:54 -070041 */
42public class VideoCallImpl extends VideoCall {
Andrew Lee50aca232014-07-22 16:41:54 -070043
Ihab Awadb19a0bc2014-08-07 19:46:01 -070044 private final IVideoProvider mVideoProvider;
Andrew Lee50aca232014-07-22 16:41:54 -070045 private final VideoCallListenerBinder mBinder;
Andrew Leeda80c872015-04-15 14:09:50 -070046 private VideoCall.Callback mCallback;
Tyler Gunn45382162015-05-06 08:52:27 -070047 private int mVideoQuality = VideoProfile.QUALITY_UNKNOWN;
Tyler Gunn584ba6c2015-12-08 10:53:41 -080048 private int mVideoState = VideoProfile.STATE_AUDIO_ONLY;
Tyler Gunnbf9c6fd2016-11-09 10:19:23 -080049 private final String mCallingPackageName;
Brad Ebinger0d55a302017-03-20 13:16:28 -070050
51 private int mTargetSdkVersion;
Andrew Lee50aca232014-07-22 16:41:54 -070052
53 private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
54 @Override
55 public void binderDied() {
Ihab Awadb19a0bc2014-08-07 19:46:01 -070056 mVideoProvider.asBinder().unlinkToDeath(this, 0);
Andrew Lee50aca232014-07-22 16:41:54 -070057 }
58 };
59
60 /**
Ihab Awadb19a0bc2014-08-07 19:46:01 -070061 * IVideoCallback stub implementation.
Andrew Lee50aca232014-07-22 16:41:54 -070062 */
Ihab Awadb19a0bc2014-08-07 19:46:01 -070063 private final class VideoCallListenerBinder extends IVideoCallback.Stub {
Andrew Lee50aca232014-07-22 16:41:54 -070064 @Override
Ihab Awadb19a0bc2014-08-07 19:46:01 -070065 public void receiveSessionModifyRequest(VideoProfile videoProfile) {
Tyler Gunne988cf72015-05-28 15:47:06 -070066 if (mHandler == null) {
67 return;
68 }
Andrew Lee011728f2015-04-23 15:47:06 -070069 mHandler.obtainMessage(MessageHandler.MSG_RECEIVE_SESSION_MODIFY_REQUEST,
Ihab Awadb19a0bc2014-08-07 19:46:01 -070070 videoProfile).sendToTarget();
Tyler Gunne988cf72015-05-28 15:47:06 -070071
Andrew Lee50aca232014-07-22 16:41:54 -070072 }
73
74 @Override
Ihab Awadb19a0bc2014-08-07 19:46:01 -070075 public void receiveSessionModifyResponse(int status, VideoProfile requestProfile,
76 VideoProfile responseProfile) {
Tyler Gunne988cf72015-05-28 15:47:06 -070077 if (mHandler == null) {
78 return;
79 }
Andrew Lee50aca232014-07-22 16:41:54 -070080 SomeArgs args = SomeArgs.obtain();
81 args.arg1 = status;
82 args.arg2 = requestProfile;
83 args.arg3 = responseProfile;
Andrew Lee011728f2015-04-23 15:47:06 -070084 mHandler.obtainMessage(MessageHandler.MSG_RECEIVE_SESSION_MODIFY_RESPONSE, args)
85 .sendToTarget();
Andrew Lee50aca232014-07-22 16:41:54 -070086 }
87
88 @Override
89 public void handleCallSessionEvent(int event) {
Tyler Gunne988cf72015-05-28 15:47:06 -070090 if (mHandler == null) {
91 return;
92 }
Andrew Lee011728f2015-04-23 15:47:06 -070093 mHandler.obtainMessage(MessageHandler.MSG_HANDLE_CALL_SESSION_EVENT, event)
94 .sendToTarget();
Andrew Lee50aca232014-07-22 16:41:54 -070095 }
96
97 @Override
98 public void changePeerDimensions(int width, int height) {
Tyler Gunne988cf72015-05-28 15:47:06 -070099 if (mHandler == null) {
100 return;
101 }
Andrew Lee50aca232014-07-22 16:41:54 -0700102 SomeArgs args = SomeArgs.obtain();
103 args.arg1 = width;
104 args.arg2 = height;
Andrew Lee011728f2015-04-23 15:47:06 -0700105 mHandler.obtainMessage(MessageHandler.MSG_CHANGE_PEER_DIMENSIONS, args).sendToTarget();
Andrew Lee50aca232014-07-22 16:41:54 -0700106 }
107
108 @Override
Rekha Kumar07366812015-03-24 16:42:31 -0700109 public void changeVideoQuality(int videoQuality) {
Tyler Gunne988cf72015-05-28 15:47:06 -0700110 if (mHandler == null) {
111 return;
112 }
Andrew Lee011728f2015-04-23 15:47:06 -0700113 mHandler.obtainMessage(MessageHandler.MSG_CHANGE_VIDEO_QUALITY, videoQuality, 0)
114 .sendToTarget();
Rekha Kumar07366812015-03-24 16:42:31 -0700115 }
116
117 @Override
118 public void changeCallDataUsage(long dataUsage) {
Tyler Gunne988cf72015-05-28 15:47:06 -0700119 if (mHandler == null) {
120 return;
121 }
Andrew Lee011728f2015-04-23 15:47:06 -0700122 mHandler.obtainMessage(MessageHandler.MSG_CHANGE_CALL_DATA_USAGE, dataUsage)
123 .sendToTarget();
Andrew Lee50aca232014-07-22 16:41:54 -0700124 }
125
126 @Override
Yorke Lee400470f2015-05-12 13:31:25 -0700127 public void changeCameraCapabilities(VideoProfile.CameraCapabilities cameraCapabilities) {
Tyler Gunne988cf72015-05-28 15:47:06 -0700128 if (mHandler == null) {
129 return;
130 }
Andrew Lee011728f2015-04-23 15:47:06 -0700131 mHandler.obtainMessage(MessageHandler.MSG_CHANGE_CAMERA_CAPABILITIES,
Andrew Lee50aca232014-07-22 16:41:54 -0700132 cameraCapabilities).sendToTarget();
133 }
134 }
135
136 /** Default handler used to consolidate binder method calls onto a single thread. */
Andrew Lee011728f2015-04-23 15:47:06 -0700137 private final class MessageHandler extends Handler {
138 private static final int MSG_RECEIVE_SESSION_MODIFY_REQUEST = 1;
139 private static final int MSG_RECEIVE_SESSION_MODIFY_RESPONSE = 2;
140 private static final int MSG_HANDLE_CALL_SESSION_EVENT = 3;
141 private static final int MSG_CHANGE_PEER_DIMENSIONS = 4;
142 private static final int MSG_CHANGE_CALL_DATA_USAGE = 5;
143 private static final int MSG_CHANGE_CAMERA_CAPABILITIES = 6;
144 private static final int MSG_CHANGE_VIDEO_QUALITY = 7;
145
146 public MessageHandler(Looper looper) {
147 super(looper);
148 }
149
Andrew Lee50aca232014-07-22 16:41:54 -0700150 @Override
151 public void handleMessage(Message msg) {
Andrew Leeda80c872015-04-15 14:09:50 -0700152 if (mCallback == null) {
Andrew Lee50aca232014-07-22 16:41:54 -0700153 return;
154 }
155
156 SomeArgs args;
157 switch (msg.what) {
158 case MSG_RECEIVE_SESSION_MODIFY_REQUEST:
Andrew Leeda80c872015-04-15 14:09:50 -0700159 mCallback.onSessionModifyRequestReceived((VideoProfile) msg.obj);
Andrew Lee50aca232014-07-22 16:41:54 -0700160 break;
161 case MSG_RECEIVE_SESSION_MODIFY_RESPONSE:
162 args = (SomeArgs) msg.obj;
163 try {
164 int status = (int) args.arg1;
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700165 VideoProfile requestProfile = (VideoProfile) args.arg2;
166 VideoProfile responseProfile = (VideoProfile) args.arg3;
Andrew Lee50aca232014-07-22 16:41:54 -0700167
Andrew Leeda80c872015-04-15 14:09:50 -0700168 mCallback.onSessionModifyResponseReceived(
Andrew Lee50aca232014-07-22 16:41:54 -0700169 status, requestProfile, responseProfile);
170 } finally {
171 args.recycle();
172 }
173 break;
174 case MSG_HANDLE_CALL_SESSION_EVENT:
Andrew Leeda80c872015-04-15 14:09:50 -0700175 mCallback.onCallSessionEvent((int) msg.obj);
Andrew Lee50aca232014-07-22 16:41:54 -0700176 break;
177 case MSG_CHANGE_PEER_DIMENSIONS:
178 args = (SomeArgs) msg.obj;
179 try {
180 int width = (int) args.arg1;
181 int height = (int) args.arg2;
Andrew Leeda80c872015-04-15 14:09:50 -0700182 mCallback.onPeerDimensionsChanged(width, height);
Andrew Lee50aca232014-07-22 16:41:54 -0700183 } finally {
184 args.recycle();
185 }
186 break;
187 case MSG_CHANGE_CALL_DATA_USAGE:
Andrew Leeda80c872015-04-15 14:09:50 -0700188 mCallback.onCallDataUsageChanged((long) msg.obj);
Andrew Lee50aca232014-07-22 16:41:54 -0700189 break;
190 case MSG_CHANGE_CAMERA_CAPABILITIES:
Andrew Leeda80c872015-04-15 14:09:50 -0700191 mCallback.onCameraCapabilitiesChanged(
Yorke Lee400470f2015-05-12 13:31:25 -0700192 (VideoProfile.CameraCapabilities) msg.obj);
Andrew Lee50aca232014-07-22 16:41:54 -0700193 break;
Rekha Kumar07366812015-03-24 16:42:31 -0700194 case MSG_CHANGE_VIDEO_QUALITY:
Tyler Gunn45382162015-05-06 08:52:27 -0700195 mVideoQuality = msg.arg1;
Andrew Leeda80c872015-04-15 14:09:50 -0700196 mCallback.onVideoQualityChanged(msg.arg1);
Rekha Kumar07366812015-03-24 16:42:31 -0700197 break;
Andrew Lee50aca232014-07-22 16:41:54 -0700198 default:
199 break;
200 }
201 }
202 };
203
Andrew Lee011728f2015-04-23 15:47:06 -0700204 private Handler mHandler;
205
Tyler Gunn159f35c2017-03-02 09:28:37 -0800206 VideoCallImpl(IVideoProvider videoProvider, String callingPackageName, int targetSdkVersion)
207 throws RemoteException {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700208 mVideoProvider = videoProvider;
209 mVideoProvider.asBinder().linkToDeath(mDeathRecipient, 0);
Andrew Lee50aca232014-07-22 16:41:54 -0700210
211 mBinder = new VideoCallListenerBinder();
Tyler Gunn75958422015-04-15 14:23:42 -0700212 mVideoProvider.addVideoCallback(mBinder);
Tyler Gunnbf9c6fd2016-11-09 10:19:23 -0800213 mCallingPackageName = callingPackageName;
Brad Ebinger0d55a302017-03-20 13:16:28 -0700214 setTargetSdkVersion(targetSdkVersion);
215 }
216
217 @VisibleForTesting
218 public void setTargetSdkVersion(int sdkVersion) {
219 mTargetSdkVersion = sdkVersion;
Andrew Lee50aca232014-07-22 16:41:54 -0700220 }
221
Tyler Gunn17933eb2019-03-05 13:58:45 -0800222 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 127403196)
Andrew Lee011728f2015-04-23 15:47:06 -0700223 public void destroy() {
224 unregisterCallback(mCallback);
Andrew Lee50aca232014-07-22 16:41:54 -0700225 }
226
227 /** {@inheritDoc} */
Andrew Lee011728f2015-04-23 15:47:06 -0700228 public void registerCallback(VideoCall.Callback callback) {
229 registerCallback(callback, null);
230 }
231
232 /** {@inheritDoc} */
233 public void registerCallback(VideoCall.Callback callback, Handler handler) {
234 mCallback = callback;
235 if (handler == null) {
236 mHandler = new MessageHandler(Looper.getMainLooper());
237 } else {
238 mHandler = new MessageHandler(handler.getLooper());
239 }
240 }
241
242 /** {@inheritDoc} */
243 public void unregisterCallback(VideoCall.Callback callback) {
244 if (callback != mCallback) {
245 return;
246 }
247
Etan Cohen89427242015-04-23 12:26:37 -0700248 mCallback = null;
Tyler Gunn75958422015-04-15 14:23:42 -0700249 try {
250 mVideoProvider.removeVideoCallback(mBinder);
251 } catch (RemoteException e) {
252 }
253 }
254
255 /** {@inheritDoc} */
Andrew Lee50aca232014-07-22 16:41:54 -0700256 public void setCamera(String cameraId) {
257 try {
Tyler Gunnbf9c6fd2016-11-09 10:19:23 -0800258 Log.w(this, "setCamera: cameraId=%s, calling=%s", cameraId, mCallingPackageName);
Tyler Gunn159f35c2017-03-02 09:28:37 -0800259 mVideoProvider.setCamera(cameraId, mCallingPackageName, mTargetSdkVersion);
Andrew Lee50aca232014-07-22 16:41:54 -0700260 } catch (RemoteException e) {
261 }
262 }
263
264 /** {@inheritDoc} */
265 public void setPreviewSurface(Surface surface) {
266 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700267 mVideoProvider.setPreviewSurface(surface);
Andrew Lee50aca232014-07-22 16:41:54 -0700268 } catch (RemoteException e) {
269 }
270 }
271
272 /** {@inheritDoc} */
273 public void setDisplaySurface(Surface surface) {
274 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700275 mVideoProvider.setDisplaySurface(surface);
Andrew Lee50aca232014-07-22 16:41:54 -0700276 } catch (RemoteException e) {
277 }
278 }
279
280 /** {@inheritDoc} */
281 public void setDeviceOrientation(int rotation) {
282 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700283 mVideoProvider.setDeviceOrientation(rotation);
Andrew Lee50aca232014-07-22 16:41:54 -0700284 } catch (RemoteException e) {
285 }
286 }
287
288 /** {@inheritDoc} */
289 public void setZoom(float value) {
290 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700291 mVideoProvider.setZoom(value);
Andrew Lee50aca232014-07-22 16:41:54 -0700292 } catch (RemoteException e) {
293 }
294 }
295
Tyler Gunn45382162015-05-06 08:52:27 -0700296 /**
297 * Sends a session modification request to the video provider.
298 * <p>
299 * The {@link InCallService} will create the {@code requestProfile} based on the current
300 * video state (i.e. {@link Call.Details#getVideoState()}). It is, however, possible that the
301 * video state maintained by the {@link InCallService} could get out of sync with what is known
302 * by the {@link android.telecom.Connection.VideoProvider}. To remove ambiguity, the
303 * {@link VideoCallImpl} passes along the pre-modify video profile to the {@code VideoProvider}
304 * to ensure it has full context of the requested change.
305 *
306 * @param requestProfile The requested video profile.
307 */
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700308 public void sendSessionModifyRequest(VideoProfile requestProfile) {
Andrew Lee50aca232014-07-22 16:41:54 -0700309 try {
Tyler Gunn584ba6c2015-12-08 10:53:41 -0800310 VideoProfile originalProfile = new VideoProfile(mVideoState, mVideoQuality);
Tyler Gunn45382162015-05-06 08:52:27 -0700311
312 mVideoProvider.sendSessionModifyRequest(originalProfile, requestProfile);
Andrew Lee50aca232014-07-22 16:41:54 -0700313 } catch (RemoteException e) {
314 }
315 }
316
317 /** {@inheritDoc} */
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700318 public void sendSessionModifyResponse(VideoProfile responseProfile) {
Andrew Lee50aca232014-07-22 16:41:54 -0700319 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700320 mVideoProvider.sendSessionModifyResponse(responseProfile);
Andrew Lee50aca232014-07-22 16:41:54 -0700321 } catch (RemoteException e) {
322 }
323 }
324
325 /** {@inheritDoc} */
326 public void requestCameraCapabilities() {
327 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700328 mVideoProvider.requestCameraCapabilities();
Andrew Lee50aca232014-07-22 16:41:54 -0700329 } catch (RemoteException e) {
330 }
331 }
332
333 /** {@inheritDoc} */
334 public void requestCallDataUsage() {
335 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700336 mVideoProvider.requestCallDataUsage();
Andrew Lee50aca232014-07-22 16:41:54 -0700337 } catch (RemoteException e) {
338 }
339 }
340
341 /** {@inheritDoc} */
Yorke Lee32f24732015-05-12 16:18:03 -0700342 public void setPauseImage(Uri uri) {
Andrew Lee50aca232014-07-22 16:41:54 -0700343 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700344 mVideoProvider.setPauseImage(uri);
Andrew Lee50aca232014-07-22 16:41:54 -0700345 } catch (RemoteException e) {
346 }
347 }
Tyler Gunn584ba6c2015-12-08 10:53:41 -0800348
349 /**
350 * Sets the video state for the current video call.
351 * @param videoState the new video state.
352 */
353 public void setVideoState(int videoState) {
354 mVideoState = videoState;
355 }
Rekha Kumar07366812015-03-24 16:42:31 -0700356}