1 /* 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 17 package android.telecom; 18 19 import android.os.Handler; 20 import android.os.IBinder; 21 import android.os.Looper; 22 import android.os.Message; 23 import android.os.RemoteException; 24 import android.telecom.InCallService.VideoCall; 25 import android.view.Surface; 26 27 import com.android.internal.os.SomeArgs; 28 import com.android.internal.telecom.IVideoCallback; 29 import com.android.internal.telecom.IVideoProvider; 30 31 /** 32 * Implementation of a Video Call, which allows InCallUi to communicate commands to the underlying 33 * {@link Connection.VideoProvider}, and direct callbacks from the 34 * {@link Connection.VideoProvider} to the appropriate {@link VideoCall.Listener}. 35 * 36 * {@hide} 37 */ 38 public class VideoCallImpl extends VideoCall { 39 private static final int MSG_RECEIVE_SESSION_MODIFY_REQUEST = 1; 40 private static final int MSG_RECEIVE_SESSION_MODIFY_RESPONSE = 2; 41 private static final int MSG_HANDLE_CALL_SESSION_EVENT = 3; 42 private static final int MSG_CHANGE_PEER_DIMENSIONS = 4; 43 private static final int MSG_CHANGE_CALL_DATA_USAGE = 5; 44 private static final int MSG_CHANGE_CAMERA_CAPABILITIES = 6; 45 46 private final IVideoProvider mVideoProvider; 47 private final VideoCallListenerBinder mBinder; 48 private VideoCall.Listener mVideoCallListener; 49 50 private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() { 51 @Override 52 public void binderDied() { 53 mVideoProvider.asBinder().unlinkToDeath(this, 0); 54 } 55 }; 56 57 /** 58 * IVideoCallback stub implementation. 59 */ 60 private final class VideoCallListenerBinder extends IVideoCallback.Stub { 61 @Override receiveSessionModifyRequest(VideoProfile videoProfile)62 public void receiveSessionModifyRequest(VideoProfile videoProfile) { 63 mHandler.obtainMessage(MSG_RECEIVE_SESSION_MODIFY_REQUEST, 64 videoProfile).sendToTarget(); 65 } 66 67 @Override receiveSessionModifyResponse(int status, VideoProfile requestProfile, VideoProfile responseProfile)68 public void receiveSessionModifyResponse(int status, VideoProfile requestProfile, 69 VideoProfile responseProfile) { 70 SomeArgs args = SomeArgs.obtain(); 71 args.arg1 = status; 72 args.arg2 = requestProfile; 73 args.arg3 = responseProfile; 74 mHandler.obtainMessage(MSG_RECEIVE_SESSION_MODIFY_RESPONSE, args).sendToTarget(); 75 } 76 77 @Override handleCallSessionEvent(int event)78 public void handleCallSessionEvent(int event) { 79 mHandler.obtainMessage(MSG_HANDLE_CALL_SESSION_EVENT, event).sendToTarget(); 80 } 81 82 @Override changePeerDimensions(int width, int height)83 public void changePeerDimensions(int width, int height) { 84 SomeArgs args = SomeArgs.obtain(); 85 args.arg1 = width; 86 args.arg2 = height; 87 mHandler.obtainMessage(MSG_CHANGE_PEER_DIMENSIONS, args).sendToTarget(); 88 } 89 90 @Override changeCallDataUsage(int dataUsage)91 public void changeCallDataUsage(int dataUsage) { 92 mHandler.obtainMessage(MSG_CHANGE_CALL_DATA_USAGE, dataUsage).sendToTarget(); 93 } 94 95 @Override changeCameraCapabilities(CameraCapabilities cameraCapabilities)96 public void changeCameraCapabilities(CameraCapabilities cameraCapabilities) { 97 mHandler.obtainMessage(MSG_CHANGE_CAMERA_CAPABILITIES, 98 cameraCapabilities).sendToTarget(); 99 } 100 } 101 102 /** Default handler used to consolidate binder method calls onto a single thread. */ 103 private final Handler mHandler = new Handler(Looper.getMainLooper()) { 104 @Override 105 public void handleMessage(Message msg) { 106 if (mVideoCallListener == null) { 107 return; 108 } 109 110 SomeArgs args; 111 switch (msg.what) { 112 case MSG_RECEIVE_SESSION_MODIFY_REQUEST: 113 mVideoCallListener.onSessionModifyRequestReceived((VideoProfile) msg.obj); 114 break; 115 case MSG_RECEIVE_SESSION_MODIFY_RESPONSE: 116 args = (SomeArgs) msg.obj; 117 try { 118 int status = (int) args.arg1; 119 VideoProfile requestProfile = (VideoProfile) args.arg2; 120 VideoProfile responseProfile = (VideoProfile) args.arg3; 121 122 mVideoCallListener.onSessionModifyResponseReceived( 123 status, requestProfile, responseProfile); 124 } finally { 125 args.recycle(); 126 } 127 break; 128 case MSG_HANDLE_CALL_SESSION_EVENT: 129 mVideoCallListener.onCallSessionEvent((int) msg.obj); 130 break; 131 case MSG_CHANGE_PEER_DIMENSIONS: 132 args = (SomeArgs) msg.obj; 133 try { 134 int width = (int) args.arg1; 135 int height = (int) args.arg2; 136 mVideoCallListener.onPeerDimensionsChanged(width, height); 137 } finally { 138 args.recycle(); 139 } 140 break; 141 case MSG_CHANGE_CALL_DATA_USAGE: 142 mVideoCallListener.onCallDataUsageChanged(msg.arg1); 143 break; 144 case MSG_CHANGE_CAMERA_CAPABILITIES: 145 mVideoCallListener.onCameraCapabilitiesChanged( 146 (CameraCapabilities) msg.obj); 147 break; 148 default: 149 break; 150 } 151 } 152 }; 153 154 /** {@hide} */ VideoCallImpl(IVideoProvider videoProvider)155 VideoCallImpl(IVideoProvider videoProvider) throws RemoteException { 156 mVideoProvider = videoProvider; 157 mVideoProvider.asBinder().linkToDeath(mDeathRecipient, 0); 158 159 mBinder = new VideoCallListenerBinder(); 160 mVideoProvider.setVideoCallback(mBinder); 161 } 162 163 /** {@inheritDoc} */ setVideoCallListener(VideoCall.Listener videoCallListener)164 public void setVideoCallListener(VideoCall.Listener videoCallListener) { 165 mVideoCallListener = videoCallListener; 166 } 167 168 /** {@inheritDoc} */ setCamera(String cameraId)169 public void setCamera(String cameraId) { 170 try { 171 mVideoProvider.setCamera(cameraId); 172 } catch (RemoteException e) { 173 } 174 } 175 176 /** {@inheritDoc} */ setPreviewSurface(Surface surface)177 public void setPreviewSurface(Surface surface) { 178 try { 179 mVideoProvider.setPreviewSurface(surface); 180 } catch (RemoteException e) { 181 } 182 } 183 184 /** {@inheritDoc} */ setDisplaySurface(Surface surface)185 public void setDisplaySurface(Surface surface) { 186 try { 187 mVideoProvider.setDisplaySurface(surface); 188 } catch (RemoteException e) { 189 } 190 } 191 192 /** {@inheritDoc} */ setDeviceOrientation(int rotation)193 public void setDeviceOrientation(int rotation) { 194 try { 195 mVideoProvider.setDeviceOrientation(rotation); 196 } catch (RemoteException e) { 197 } 198 } 199 200 /** {@inheritDoc} */ setZoom(float value)201 public void setZoom(float value) { 202 try { 203 mVideoProvider.setZoom(value); 204 } catch (RemoteException e) { 205 } 206 } 207 208 /** {@inheritDoc} */ sendSessionModifyRequest(VideoProfile requestProfile)209 public void sendSessionModifyRequest(VideoProfile requestProfile) { 210 try { 211 mVideoProvider.sendSessionModifyRequest(requestProfile); 212 } catch (RemoteException e) { 213 } 214 } 215 216 /** {@inheritDoc} */ sendSessionModifyResponse(VideoProfile responseProfile)217 public void sendSessionModifyResponse(VideoProfile responseProfile) { 218 try { 219 mVideoProvider.sendSessionModifyResponse(responseProfile); 220 } catch (RemoteException e) { 221 } 222 } 223 224 /** {@inheritDoc} */ requestCameraCapabilities()225 public void requestCameraCapabilities() { 226 try { 227 mVideoProvider.requestCameraCapabilities(); 228 } catch (RemoteException e) { 229 } 230 } 231 232 /** {@inheritDoc} */ requestCallDataUsage()233 public void requestCallDataUsage() { 234 try { 235 mVideoProvider.requestCallDataUsage(); 236 } catch (RemoteException e) { 237 } 238 } 239 240 /** {@inheritDoc} */ setPauseImage(String uri)241 public void setPauseImage(String uri) { 242 try { 243 mVideoProvider.setPauseImage(uri); 244 } catch (RemoteException e) { 245 } 246 } 247 }