blob: bae58ff852d4ff2005039b34ad4fc4feaafa80d5 [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
Brad Ebinger0d55a302017-03-20 13:16:28 -070028import com.android.internal.annotations.VisibleForTesting;
Andrew Lee50aca232014-07-22 16:41:54 -070029import com.android.internal.os.SomeArgs;
Tyler Gunnef9f6f92014-09-12 22:16:17 -070030import com.android.internal.telecom.IVideoCallback;
31import com.android.internal.telecom.IVideoProvider;
Andrew Lee50aca232014-07-22 16:41:54 -070032
33/**
34 * Implementation of a Video Call, which allows InCallUi to communicate commands to the underlying
Ihab Awadb19a0bc2014-08-07 19:46:01 -070035 * {@link Connection.VideoProvider}, and direct callbacks from the
36 * {@link Connection.VideoProvider} to the appropriate {@link VideoCall.Listener}.
37 *
38 * {@hide}
Andrew Lee50aca232014-07-22 16:41:54 -070039 */
40public class VideoCallImpl extends VideoCall {
Andrew Lee50aca232014-07-22 16:41:54 -070041
Ihab Awadb19a0bc2014-08-07 19:46:01 -070042 private final IVideoProvider mVideoProvider;
Andrew Lee50aca232014-07-22 16:41:54 -070043 private final VideoCallListenerBinder mBinder;
Andrew Leeda80c872015-04-15 14:09:50 -070044 private VideoCall.Callback mCallback;
Tyler Gunn45382162015-05-06 08:52:27 -070045 private int mVideoQuality = VideoProfile.QUALITY_UNKNOWN;
Tyler Gunn584ba6c2015-12-08 10:53:41 -080046 private int mVideoState = VideoProfile.STATE_AUDIO_ONLY;
Tyler Gunnbf9c6fd2016-11-09 10:19:23 -080047 private final String mCallingPackageName;
Brad Ebinger0d55a302017-03-20 13:16:28 -070048
49 private int mTargetSdkVersion;
Andrew Lee50aca232014-07-22 16:41:54 -070050
51 private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
52 @Override
53 public void binderDied() {
Ihab Awadb19a0bc2014-08-07 19:46:01 -070054 mVideoProvider.asBinder().unlinkToDeath(this, 0);
Andrew Lee50aca232014-07-22 16:41:54 -070055 }
56 };
57
58 /**
Ihab Awadb19a0bc2014-08-07 19:46:01 -070059 * IVideoCallback stub implementation.
Andrew Lee50aca232014-07-22 16:41:54 -070060 */
Ihab Awadb19a0bc2014-08-07 19:46:01 -070061 private final class VideoCallListenerBinder extends IVideoCallback.Stub {
Andrew Lee50aca232014-07-22 16:41:54 -070062 @Override
Ihab Awadb19a0bc2014-08-07 19:46:01 -070063 public void receiveSessionModifyRequest(VideoProfile videoProfile) {
Tyler Gunne988cf72015-05-28 15:47:06 -070064 if (mHandler == null) {
65 return;
66 }
Andrew Lee011728f2015-04-23 15:47:06 -070067 mHandler.obtainMessage(MessageHandler.MSG_RECEIVE_SESSION_MODIFY_REQUEST,
Ihab Awadb19a0bc2014-08-07 19:46:01 -070068 videoProfile).sendToTarget();
Tyler Gunne988cf72015-05-28 15:47:06 -070069
Andrew Lee50aca232014-07-22 16:41:54 -070070 }
71
72 @Override
Ihab Awadb19a0bc2014-08-07 19:46:01 -070073 public void receiveSessionModifyResponse(int status, VideoProfile requestProfile,
74 VideoProfile responseProfile) {
Tyler Gunne988cf72015-05-28 15:47:06 -070075 if (mHandler == null) {
76 return;
77 }
Andrew Lee50aca232014-07-22 16:41:54 -070078 SomeArgs args = SomeArgs.obtain();
79 args.arg1 = status;
80 args.arg2 = requestProfile;
81 args.arg3 = responseProfile;
Andrew Lee011728f2015-04-23 15:47:06 -070082 mHandler.obtainMessage(MessageHandler.MSG_RECEIVE_SESSION_MODIFY_RESPONSE, args)
83 .sendToTarget();
Andrew Lee50aca232014-07-22 16:41:54 -070084 }
85
86 @Override
87 public void handleCallSessionEvent(int event) {
Tyler Gunne988cf72015-05-28 15:47:06 -070088 if (mHandler == null) {
89 return;
90 }
Andrew Lee011728f2015-04-23 15:47:06 -070091 mHandler.obtainMessage(MessageHandler.MSG_HANDLE_CALL_SESSION_EVENT, event)
92 .sendToTarget();
Andrew Lee50aca232014-07-22 16:41:54 -070093 }
94
95 @Override
96 public void changePeerDimensions(int width, int height) {
Tyler Gunne988cf72015-05-28 15:47:06 -070097 if (mHandler == null) {
98 return;
99 }
Andrew Lee50aca232014-07-22 16:41:54 -0700100 SomeArgs args = SomeArgs.obtain();
101 args.arg1 = width;
102 args.arg2 = height;
Andrew Lee011728f2015-04-23 15:47:06 -0700103 mHandler.obtainMessage(MessageHandler.MSG_CHANGE_PEER_DIMENSIONS, args).sendToTarget();
Andrew Lee50aca232014-07-22 16:41:54 -0700104 }
105
106 @Override
Rekha Kumar07366812015-03-24 16:42:31 -0700107 public void changeVideoQuality(int videoQuality) {
Tyler Gunne988cf72015-05-28 15:47:06 -0700108 if (mHandler == null) {
109 return;
110 }
Andrew Lee011728f2015-04-23 15:47:06 -0700111 mHandler.obtainMessage(MessageHandler.MSG_CHANGE_VIDEO_QUALITY, videoQuality, 0)
112 .sendToTarget();
Rekha Kumar07366812015-03-24 16:42:31 -0700113 }
114
115 @Override
116 public void changeCallDataUsage(long dataUsage) {
Tyler Gunne988cf72015-05-28 15:47:06 -0700117 if (mHandler == null) {
118 return;
119 }
Andrew Lee011728f2015-04-23 15:47:06 -0700120 mHandler.obtainMessage(MessageHandler.MSG_CHANGE_CALL_DATA_USAGE, dataUsage)
121 .sendToTarget();
Andrew Lee50aca232014-07-22 16:41:54 -0700122 }
123
124 @Override
Yorke Lee400470f2015-05-12 13:31:25 -0700125 public void changeCameraCapabilities(VideoProfile.CameraCapabilities cameraCapabilities) {
Tyler Gunne988cf72015-05-28 15:47:06 -0700126 if (mHandler == null) {
127 return;
128 }
Andrew Lee011728f2015-04-23 15:47:06 -0700129 mHandler.obtainMessage(MessageHandler.MSG_CHANGE_CAMERA_CAPABILITIES,
Andrew Lee50aca232014-07-22 16:41:54 -0700130 cameraCapabilities).sendToTarget();
131 }
132 }
133
134 /** Default handler used to consolidate binder method calls onto a single thread. */
Andrew Lee011728f2015-04-23 15:47:06 -0700135 private final class MessageHandler extends Handler {
136 private static final int MSG_RECEIVE_SESSION_MODIFY_REQUEST = 1;
137 private static final int MSG_RECEIVE_SESSION_MODIFY_RESPONSE = 2;
138 private static final int MSG_HANDLE_CALL_SESSION_EVENT = 3;
139 private static final int MSG_CHANGE_PEER_DIMENSIONS = 4;
140 private static final int MSG_CHANGE_CALL_DATA_USAGE = 5;
141 private static final int MSG_CHANGE_CAMERA_CAPABILITIES = 6;
142 private static final int MSG_CHANGE_VIDEO_QUALITY = 7;
143
144 public MessageHandler(Looper looper) {
145 super(looper);
146 }
147
Andrew Lee50aca232014-07-22 16:41:54 -0700148 @Override
149 public void handleMessage(Message msg) {
Andrew Leeda80c872015-04-15 14:09:50 -0700150 if (mCallback == null) {
Andrew Lee50aca232014-07-22 16:41:54 -0700151 return;
152 }
153
154 SomeArgs args;
155 switch (msg.what) {
156 case MSG_RECEIVE_SESSION_MODIFY_REQUEST:
Andrew Leeda80c872015-04-15 14:09:50 -0700157 mCallback.onSessionModifyRequestReceived((VideoProfile) msg.obj);
Andrew Lee50aca232014-07-22 16:41:54 -0700158 break;
159 case MSG_RECEIVE_SESSION_MODIFY_RESPONSE:
160 args = (SomeArgs) msg.obj;
161 try {
162 int status = (int) args.arg1;
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700163 VideoProfile requestProfile = (VideoProfile) args.arg2;
164 VideoProfile responseProfile = (VideoProfile) args.arg3;
Andrew Lee50aca232014-07-22 16:41:54 -0700165
Andrew Leeda80c872015-04-15 14:09:50 -0700166 mCallback.onSessionModifyResponseReceived(
Andrew Lee50aca232014-07-22 16:41:54 -0700167 status, requestProfile, responseProfile);
168 } finally {
169 args.recycle();
170 }
171 break;
172 case MSG_HANDLE_CALL_SESSION_EVENT:
Andrew Leeda80c872015-04-15 14:09:50 -0700173 mCallback.onCallSessionEvent((int) msg.obj);
Andrew Lee50aca232014-07-22 16:41:54 -0700174 break;
175 case MSG_CHANGE_PEER_DIMENSIONS:
176 args = (SomeArgs) msg.obj;
177 try {
178 int width = (int) args.arg1;
179 int height = (int) args.arg2;
Andrew Leeda80c872015-04-15 14:09:50 -0700180 mCallback.onPeerDimensionsChanged(width, height);
Andrew Lee50aca232014-07-22 16:41:54 -0700181 } finally {
182 args.recycle();
183 }
184 break;
185 case MSG_CHANGE_CALL_DATA_USAGE:
Andrew Leeda80c872015-04-15 14:09:50 -0700186 mCallback.onCallDataUsageChanged((long) msg.obj);
Andrew Lee50aca232014-07-22 16:41:54 -0700187 break;
188 case MSG_CHANGE_CAMERA_CAPABILITIES:
Andrew Leeda80c872015-04-15 14:09:50 -0700189 mCallback.onCameraCapabilitiesChanged(
Yorke Lee400470f2015-05-12 13:31:25 -0700190 (VideoProfile.CameraCapabilities) msg.obj);
Andrew Lee50aca232014-07-22 16:41:54 -0700191 break;
Rekha Kumar07366812015-03-24 16:42:31 -0700192 case MSG_CHANGE_VIDEO_QUALITY:
Tyler Gunn45382162015-05-06 08:52:27 -0700193 mVideoQuality = msg.arg1;
Andrew Leeda80c872015-04-15 14:09:50 -0700194 mCallback.onVideoQualityChanged(msg.arg1);
Rekha Kumar07366812015-03-24 16:42:31 -0700195 break;
Andrew Lee50aca232014-07-22 16:41:54 -0700196 default:
197 break;
198 }
199 }
200 };
201
Andrew Lee011728f2015-04-23 15:47:06 -0700202 private Handler mHandler;
203
Tyler Gunn159f35c2017-03-02 09:28:37 -0800204 VideoCallImpl(IVideoProvider videoProvider, String callingPackageName, int targetSdkVersion)
205 throws RemoteException {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700206 mVideoProvider = videoProvider;
207 mVideoProvider.asBinder().linkToDeath(mDeathRecipient, 0);
Andrew Lee50aca232014-07-22 16:41:54 -0700208
209 mBinder = new VideoCallListenerBinder();
Tyler Gunn75958422015-04-15 14:23:42 -0700210 mVideoProvider.addVideoCallback(mBinder);
Tyler Gunnbf9c6fd2016-11-09 10:19:23 -0800211 mCallingPackageName = callingPackageName;
Brad Ebinger0d55a302017-03-20 13:16:28 -0700212 setTargetSdkVersion(targetSdkVersion);
213 }
214
215 @VisibleForTesting
216 public void setTargetSdkVersion(int sdkVersion) {
217 mTargetSdkVersion = sdkVersion;
Andrew Lee50aca232014-07-22 16:41:54 -0700218 }
219
Andrew Lee011728f2015-04-23 15:47:06 -0700220 public void destroy() {
221 unregisterCallback(mCallback);
Andrew Lee50aca232014-07-22 16:41:54 -0700222 }
223
224 /** {@inheritDoc} */
Andrew Lee011728f2015-04-23 15:47:06 -0700225 public void registerCallback(VideoCall.Callback callback) {
226 registerCallback(callback, null);
227 }
228
229 /** {@inheritDoc} */
230 public void registerCallback(VideoCall.Callback callback, Handler handler) {
231 mCallback = callback;
232 if (handler == null) {
233 mHandler = new MessageHandler(Looper.getMainLooper());
234 } else {
235 mHandler = new MessageHandler(handler.getLooper());
236 }
237 }
238
239 /** {@inheritDoc} */
240 public void unregisterCallback(VideoCall.Callback callback) {
241 if (callback != mCallback) {
242 return;
243 }
244
Etan Cohen89427242015-04-23 12:26:37 -0700245 mCallback = null;
Tyler Gunn75958422015-04-15 14:23:42 -0700246 try {
247 mVideoProvider.removeVideoCallback(mBinder);
248 } catch (RemoteException e) {
249 }
250 }
251
252 /** {@inheritDoc} */
Andrew Lee50aca232014-07-22 16:41:54 -0700253 public void setCamera(String cameraId) {
254 try {
Tyler Gunnbf9c6fd2016-11-09 10:19:23 -0800255 Log.w(this, "setCamera: cameraId=%s, calling=%s", cameraId, mCallingPackageName);
Tyler Gunn159f35c2017-03-02 09:28:37 -0800256 mVideoProvider.setCamera(cameraId, mCallingPackageName, mTargetSdkVersion);
Andrew Lee50aca232014-07-22 16:41:54 -0700257 } catch (RemoteException e) {
258 }
259 }
260
261 /** {@inheritDoc} */
262 public void setPreviewSurface(Surface surface) {
263 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700264 mVideoProvider.setPreviewSurface(surface);
Andrew Lee50aca232014-07-22 16:41:54 -0700265 } catch (RemoteException e) {
266 }
267 }
268
269 /** {@inheritDoc} */
270 public void setDisplaySurface(Surface surface) {
271 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700272 mVideoProvider.setDisplaySurface(surface);
Andrew Lee50aca232014-07-22 16:41:54 -0700273 } catch (RemoteException e) {
274 }
275 }
276
277 /** {@inheritDoc} */
278 public void setDeviceOrientation(int rotation) {
279 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700280 mVideoProvider.setDeviceOrientation(rotation);
Andrew Lee50aca232014-07-22 16:41:54 -0700281 } catch (RemoteException e) {
282 }
283 }
284
285 /** {@inheritDoc} */
286 public void setZoom(float value) {
287 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700288 mVideoProvider.setZoom(value);
Andrew Lee50aca232014-07-22 16:41:54 -0700289 } catch (RemoteException e) {
290 }
291 }
292
Tyler Gunn45382162015-05-06 08:52:27 -0700293 /**
294 * Sends a session modification request to the video provider.
295 * <p>
296 * The {@link InCallService} will create the {@code requestProfile} based on the current
297 * video state (i.e. {@link Call.Details#getVideoState()}). It is, however, possible that the
298 * video state maintained by the {@link InCallService} could get out of sync with what is known
299 * by the {@link android.telecom.Connection.VideoProvider}. To remove ambiguity, the
300 * {@link VideoCallImpl} passes along the pre-modify video profile to the {@code VideoProvider}
301 * to ensure it has full context of the requested change.
302 *
303 * @param requestProfile The requested video profile.
304 */
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700305 public void sendSessionModifyRequest(VideoProfile requestProfile) {
Andrew Lee50aca232014-07-22 16:41:54 -0700306 try {
Tyler Gunn584ba6c2015-12-08 10:53:41 -0800307 VideoProfile originalProfile = new VideoProfile(mVideoState, mVideoQuality);
Tyler Gunn45382162015-05-06 08:52:27 -0700308
309 mVideoProvider.sendSessionModifyRequest(originalProfile, requestProfile);
Andrew Lee50aca232014-07-22 16:41:54 -0700310 } catch (RemoteException e) {
311 }
312 }
313
314 /** {@inheritDoc} */
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700315 public void sendSessionModifyResponse(VideoProfile responseProfile) {
Andrew Lee50aca232014-07-22 16:41:54 -0700316 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700317 mVideoProvider.sendSessionModifyResponse(responseProfile);
Andrew Lee50aca232014-07-22 16:41:54 -0700318 } catch (RemoteException e) {
319 }
320 }
321
322 /** {@inheritDoc} */
323 public void requestCameraCapabilities() {
324 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700325 mVideoProvider.requestCameraCapabilities();
Andrew Lee50aca232014-07-22 16:41:54 -0700326 } catch (RemoteException e) {
327 }
328 }
329
330 /** {@inheritDoc} */
331 public void requestCallDataUsage() {
332 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700333 mVideoProvider.requestCallDataUsage();
Andrew Lee50aca232014-07-22 16:41:54 -0700334 } catch (RemoteException e) {
335 }
336 }
337
338 /** {@inheritDoc} */
Yorke Lee32f24732015-05-12 16:18:03 -0700339 public void setPauseImage(Uri uri) {
Andrew Lee50aca232014-07-22 16:41:54 -0700340 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700341 mVideoProvider.setPauseImage(uri);
Andrew Lee50aca232014-07-22 16:41:54 -0700342 } catch (RemoteException e) {
343 }
344 }
Tyler Gunn584ba6c2015-12-08 10:53:41 -0800345
346 /**
347 * Sets the video state for the current video call.
348 * @param videoState the new video state.
349 */
350 public void setVideoState(int videoState) {
351 mVideoState = videoState;
352 }
Rekha Kumar07366812015-03-24 16:42:31 -0700353}