blob: 429a434992c569c8ea249a726c96041d292d96f0 [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;
Tyler Gunn159f35c2017-03-02 09:28:37 -080047 private final int mTargetSdkVersion;
Andrew Lee50aca232014-07-22 16:41:54 -070048
49 private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
50 @Override
51 public void binderDied() {
Ihab Awadb19a0bc2014-08-07 19:46:01 -070052 mVideoProvider.asBinder().unlinkToDeath(this, 0);
Andrew Lee50aca232014-07-22 16:41:54 -070053 }
54 };
55
56 /**
Ihab Awadb19a0bc2014-08-07 19:46:01 -070057 * IVideoCallback stub implementation.
Andrew Lee50aca232014-07-22 16:41:54 -070058 */
Ihab Awadb19a0bc2014-08-07 19:46:01 -070059 private final class VideoCallListenerBinder extends IVideoCallback.Stub {
Andrew Lee50aca232014-07-22 16:41:54 -070060 @Override
Ihab Awadb19a0bc2014-08-07 19:46:01 -070061 public void receiveSessionModifyRequest(VideoProfile videoProfile) {
Tyler Gunne988cf72015-05-28 15:47:06 -070062 if (mHandler == null) {
63 return;
64 }
Andrew Lee011728f2015-04-23 15:47:06 -070065 mHandler.obtainMessage(MessageHandler.MSG_RECEIVE_SESSION_MODIFY_REQUEST,
Ihab Awadb19a0bc2014-08-07 19:46:01 -070066 videoProfile).sendToTarget();
Tyler Gunne988cf72015-05-28 15:47:06 -070067
Andrew Lee50aca232014-07-22 16:41:54 -070068 }
69
70 @Override
Ihab Awadb19a0bc2014-08-07 19:46:01 -070071 public void receiveSessionModifyResponse(int status, VideoProfile requestProfile,
72 VideoProfile responseProfile) {
Tyler Gunne988cf72015-05-28 15:47:06 -070073 if (mHandler == null) {
74 return;
75 }
Andrew Lee50aca232014-07-22 16:41:54 -070076 SomeArgs args = SomeArgs.obtain();
77 args.arg1 = status;
78 args.arg2 = requestProfile;
79 args.arg3 = responseProfile;
Andrew Lee011728f2015-04-23 15:47:06 -070080 mHandler.obtainMessage(MessageHandler.MSG_RECEIVE_SESSION_MODIFY_RESPONSE, args)
81 .sendToTarget();
Andrew Lee50aca232014-07-22 16:41:54 -070082 }
83
84 @Override
85 public void handleCallSessionEvent(int event) {
Tyler Gunne988cf72015-05-28 15:47:06 -070086 if (mHandler == null) {
87 return;
88 }
Andrew Lee011728f2015-04-23 15:47:06 -070089 mHandler.obtainMessage(MessageHandler.MSG_HANDLE_CALL_SESSION_EVENT, event)
90 .sendToTarget();
Andrew Lee50aca232014-07-22 16:41:54 -070091 }
92
93 @Override
94 public void changePeerDimensions(int width, int height) {
Tyler Gunne988cf72015-05-28 15:47:06 -070095 if (mHandler == null) {
96 return;
97 }
Andrew Lee50aca232014-07-22 16:41:54 -070098 SomeArgs args = SomeArgs.obtain();
99 args.arg1 = width;
100 args.arg2 = height;
Andrew Lee011728f2015-04-23 15:47:06 -0700101 mHandler.obtainMessage(MessageHandler.MSG_CHANGE_PEER_DIMENSIONS, args).sendToTarget();
Andrew Lee50aca232014-07-22 16:41:54 -0700102 }
103
104 @Override
Rekha Kumar07366812015-03-24 16:42:31 -0700105 public void changeVideoQuality(int videoQuality) {
Tyler Gunne988cf72015-05-28 15:47:06 -0700106 if (mHandler == null) {
107 return;
108 }
Andrew Lee011728f2015-04-23 15:47:06 -0700109 mHandler.obtainMessage(MessageHandler.MSG_CHANGE_VIDEO_QUALITY, videoQuality, 0)
110 .sendToTarget();
Rekha Kumar07366812015-03-24 16:42:31 -0700111 }
112
113 @Override
114 public void changeCallDataUsage(long dataUsage) {
Tyler Gunne988cf72015-05-28 15:47:06 -0700115 if (mHandler == null) {
116 return;
117 }
Andrew Lee011728f2015-04-23 15:47:06 -0700118 mHandler.obtainMessage(MessageHandler.MSG_CHANGE_CALL_DATA_USAGE, dataUsage)
119 .sendToTarget();
Andrew Lee50aca232014-07-22 16:41:54 -0700120 }
121
122 @Override
Yorke Lee400470f2015-05-12 13:31:25 -0700123 public void changeCameraCapabilities(VideoProfile.CameraCapabilities cameraCapabilities) {
Tyler Gunne988cf72015-05-28 15:47:06 -0700124 if (mHandler == null) {
125 return;
126 }
Andrew Lee011728f2015-04-23 15:47:06 -0700127 mHandler.obtainMessage(MessageHandler.MSG_CHANGE_CAMERA_CAPABILITIES,
Andrew Lee50aca232014-07-22 16:41:54 -0700128 cameraCapabilities).sendToTarget();
129 }
130 }
131
132 /** Default handler used to consolidate binder method calls onto a single thread. */
Andrew Lee011728f2015-04-23 15:47:06 -0700133 private final class MessageHandler extends Handler {
134 private static final int MSG_RECEIVE_SESSION_MODIFY_REQUEST = 1;
135 private static final int MSG_RECEIVE_SESSION_MODIFY_RESPONSE = 2;
136 private static final int MSG_HANDLE_CALL_SESSION_EVENT = 3;
137 private static final int MSG_CHANGE_PEER_DIMENSIONS = 4;
138 private static final int MSG_CHANGE_CALL_DATA_USAGE = 5;
139 private static final int MSG_CHANGE_CAMERA_CAPABILITIES = 6;
140 private static final int MSG_CHANGE_VIDEO_QUALITY = 7;
141
142 public MessageHandler(Looper looper) {
143 super(looper);
144 }
145
Andrew Lee50aca232014-07-22 16:41:54 -0700146 @Override
147 public void handleMessage(Message msg) {
Andrew Leeda80c872015-04-15 14:09:50 -0700148 if (mCallback == null) {
Andrew Lee50aca232014-07-22 16:41:54 -0700149 return;
150 }
151
152 SomeArgs args;
153 switch (msg.what) {
154 case MSG_RECEIVE_SESSION_MODIFY_REQUEST:
Andrew Leeda80c872015-04-15 14:09:50 -0700155 mCallback.onSessionModifyRequestReceived((VideoProfile) msg.obj);
Andrew Lee50aca232014-07-22 16:41:54 -0700156 break;
157 case MSG_RECEIVE_SESSION_MODIFY_RESPONSE:
158 args = (SomeArgs) msg.obj;
159 try {
160 int status = (int) args.arg1;
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700161 VideoProfile requestProfile = (VideoProfile) args.arg2;
162 VideoProfile responseProfile = (VideoProfile) args.arg3;
Andrew Lee50aca232014-07-22 16:41:54 -0700163
Andrew Leeda80c872015-04-15 14:09:50 -0700164 mCallback.onSessionModifyResponseReceived(
Andrew Lee50aca232014-07-22 16:41:54 -0700165 status, requestProfile, responseProfile);
166 } finally {
167 args.recycle();
168 }
169 break;
170 case MSG_HANDLE_CALL_SESSION_EVENT:
Andrew Leeda80c872015-04-15 14:09:50 -0700171 mCallback.onCallSessionEvent((int) msg.obj);
Andrew Lee50aca232014-07-22 16:41:54 -0700172 break;
173 case MSG_CHANGE_PEER_DIMENSIONS:
174 args = (SomeArgs) msg.obj;
175 try {
176 int width = (int) args.arg1;
177 int height = (int) args.arg2;
Andrew Leeda80c872015-04-15 14:09:50 -0700178 mCallback.onPeerDimensionsChanged(width, height);
Andrew Lee50aca232014-07-22 16:41:54 -0700179 } finally {
180 args.recycle();
181 }
182 break;
183 case MSG_CHANGE_CALL_DATA_USAGE:
Andrew Leeda80c872015-04-15 14:09:50 -0700184 mCallback.onCallDataUsageChanged((long) msg.obj);
Andrew Lee50aca232014-07-22 16:41:54 -0700185 break;
186 case MSG_CHANGE_CAMERA_CAPABILITIES:
Andrew Leeda80c872015-04-15 14:09:50 -0700187 mCallback.onCameraCapabilitiesChanged(
Yorke Lee400470f2015-05-12 13:31:25 -0700188 (VideoProfile.CameraCapabilities) msg.obj);
Andrew Lee50aca232014-07-22 16:41:54 -0700189 break;
Rekha Kumar07366812015-03-24 16:42:31 -0700190 case MSG_CHANGE_VIDEO_QUALITY:
Tyler Gunn45382162015-05-06 08:52:27 -0700191 mVideoQuality = msg.arg1;
Andrew Leeda80c872015-04-15 14:09:50 -0700192 mCallback.onVideoQualityChanged(msg.arg1);
Rekha Kumar07366812015-03-24 16:42:31 -0700193 break;
Andrew Lee50aca232014-07-22 16:41:54 -0700194 default:
195 break;
196 }
197 }
198 };
199
Andrew Lee011728f2015-04-23 15:47:06 -0700200 private Handler mHandler;
201
Tyler Gunn159f35c2017-03-02 09:28:37 -0800202 VideoCallImpl(IVideoProvider videoProvider, String callingPackageName, int targetSdkVersion)
203 throws RemoteException {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700204 mVideoProvider = videoProvider;
205 mVideoProvider.asBinder().linkToDeath(mDeathRecipient, 0);
Andrew Lee50aca232014-07-22 16:41:54 -0700206
207 mBinder = new VideoCallListenerBinder();
Tyler Gunn75958422015-04-15 14:23:42 -0700208 mVideoProvider.addVideoCallback(mBinder);
Tyler Gunnbf9c6fd2016-11-09 10:19:23 -0800209 mCallingPackageName = callingPackageName;
Tyler Gunn159f35c2017-03-02 09:28:37 -0800210 mTargetSdkVersion = targetSdkVersion;
Andrew Lee50aca232014-07-22 16:41:54 -0700211 }
212
Andrew Lee011728f2015-04-23 15:47:06 -0700213 public void destroy() {
214 unregisterCallback(mCallback);
Andrew Lee50aca232014-07-22 16:41:54 -0700215 }
216
217 /** {@inheritDoc} */
Andrew Lee011728f2015-04-23 15:47:06 -0700218 public void registerCallback(VideoCall.Callback callback) {
219 registerCallback(callback, null);
220 }
221
222 /** {@inheritDoc} */
223 public void registerCallback(VideoCall.Callback callback, Handler handler) {
224 mCallback = callback;
225 if (handler == null) {
226 mHandler = new MessageHandler(Looper.getMainLooper());
227 } else {
228 mHandler = new MessageHandler(handler.getLooper());
229 }
230 }
231
232 /** {@inheritDoc} */
233 public void unregisterCallback(VideoCall.Callback callback) {
234 if (callback != mCallback) {
235 return;
236 }
237
Etan Cohen89427242015-04-23 12:26:37 -0700238 mCallback = null;
Tyler Gunn75958422015-04-15 14:23:42 -0700239 try {
240 mVideoProvider.removeVideoCallback(mBinder);
241 } catch (RemoteException e) {
242 }
243 }
244
245 /** {@inheritDoc} */
Andrew Lee50aca232014-07-22 16:41:54 -0700246 public void setCamera(String cameraId) {
247 try {
Tyler Gunnbf9c6fd2016-11-09 10:19:23 -0800248 Log.w(this, "setCamera: cameraId=%s, calling=%s", cameraId, mCallingPackageName);
Tyler Gunn159f35c2017-03-02 09:28:37 -0800249 mVideoProvider.setCamera(cameraId, mCallingPackageName, mTargetSdkVersion);
Andrew Lee50aca232014-07-22 16:41:54 -0700250 } catch (RemoteException e) {
251 }
252 }
253
254 /** {@inheritDoc} */
255 public void setPreviewSurface(Surface surface) {
256 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700257 mVideoProvider.setPreviewSurface(surface);
Andrew Lee50aca232014-07-22 16:41:54 -0700258 } catch (RemoteException e) {
259 }
260 }
261
262 /** {@inheritDoc} */
263 public void setDisplaySurface(Surface surface) {
264 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700265 mVideoProvider.setDisplaySurface(surface);
Andrew Lee50aca232014-07-22 16:41:54 -0700266 } catch (RemoteException e) {
267 }
268 }
269
270 /** {@inheritDoc} */
271 public void setDeviceOrientation(int rotation) {
272 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700273 mVideoProvider.setDeviceOrientation(rotation);
Andrew Lee50aca232014-07-22 16:41:54 -0700274 } catch (RemoteException e) {
275 }
276 }
277
278 /** {@inheritDoc} */
279 public void setZoom(float value) {
280 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700281 mVideoProvider.setZoom(value);
Andrew Lee50aca232014-07-22 16:41:54 -0700282 } catch (RemoteException e) {
283 }
284 }
285
Tyler Gunn45382162015-05-06 08:52:27 -0700286 /**
287 * Sends a session modification request to the video provider.
288 * <p>
289 * The {@link InCallService} will create the {@code requestProfile} based on the current
290 * video state (i.e. {@link Call.Details#getVideoState()}). It is, however, possible that the
291 * video state maintained by the {@link InCallService} could get out of sync with what is known
292 * by the {@link android.telecom.Connection.VideoProvider}. To remove ambiguity, the
293 * {@link VideoCallImpl} passes along the pre-modify video profile to the {@code VideoProvider}
294 * to ensure it has full context of the requested change.
295 *
296 * @param requestProfile The requested video profile.
297 */
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700298 public void sendSessionModifyRequest(VideoProfile requestProfile) {
Andrew Lee50aca232014-07-22 16:41:54 -0700299 try {
Tyler Gunn584ba6c2015-12-08 10:53:41 -0800300 VideoProfile originalProfile = new VideoProfile(mVideoState, mVideoQuality);
Tyler Gunn45382162015-05-06 08:52:27 -0700301
302 mVideoProvider.sendSessionModifyRequest(originalProfile, requestProfile);
Andrew Lee50aca232014-07-22 16:41:54 -0700303 } catch (RemoteException e) {
304 }
305 }
306
307 /** {@inheritDoc} */
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700308 public void sendSessionModifyResponse(VideoProfile responseProfile) {
Andrew Lee50aca232014-07-22 16:41:54 -0700309 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700310 mVideoProvider.sendSessionModifyResponse(responseProfile);
Andrew Lee50aca232014-07-22 16:41:54 -0700311 } catch (RemoteException e) {
312 }
313 }
314
315 /** {@inheritDoc} */
316 public void requestCameraCapabilities() {
317 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700318 mVideoProvider.requestCameraCapabilities();
Andrew Lee50aca232014-07-22 16:41:54 -0700319 } catch (RemoteException e) {
320 }
321 }
322
323 /** {@inheritDoc} */
324 public void requestCallDataUsage() {
325 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700326 mVideoProvider.requestCallDataUsage();
Andrew Lee50aca232014-07-22 16:41:54 -0700327 } catch (RemoteException e) {
328 }
329 }
330
331 /** {@inheritDoc} */
Yorke Lee32f24732015-05-12 16:18:03 -0700332 public void setPauseImage(Uri uri) {
Andrew Lee50aca232014-07-22 16:41:54 -0700333 try {
Ihab Awadb19a0bc2014-08-07 19:46:01 -0700334 mVideoProvider.setPauseImage(uri);
Andrew Lee50aca232014-07-22 16:41:54 -0700335 } catch (RemoteException e) {
336 }
337 }
Tyler Gunn584ba6c2015-12-08 10:53:41 -0800338
339 /**
340 * Sets the video state for the current video call.
341 * @param videoState the new video state.
342 */
343 public void setVideoState(int videoState) {
344 mVideoState = videoState;
345 }
Rekha Kumar07366812015-03-24 16:42:31 -0700346}