VideoProviderTest.java revision 953e1af643b66df6f931d76c23bcc54147668cd4
1/* 2 * Copyright (C) 2015 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 17package com.android.server.telecom.tests; 18 19import org.mockito.ArgumentCaptor; 20import org.mockito.Mock; 21import org.mockito.Mockito; 22import org.mockito.internal.exceptions.ExceptionIncludingMockitoWarnings; 23import org.mockito.invocation.InvocationOnMock; 24import org.mockito.stubbing.Answer; 25 26import android.graphics.SurfaceTexture; 27import android.net.Uri; 28import android.telecom.Connection.VideoProvider; 29import android.telecom.InCallService; 30import android.telecom.InCallService.VideoCall; 31import android.telecom.VideoCallImpl; 32import android.telecom.VideoProfile; 33import android.telecom.VideoProfile.CameraCapabilities; 34import android.view.Surface; 35 36import com.google.common.base.Predicate; 37 38import java.util.List; 39import java.util.concurrent.CountDownLatch; 40import java.util.concurrent.TimeUnit; 41 42import static android.test.MoreAsserts.assertEquals; 43import static org.mockito.Matchers.any; 44import static org.mockito.Matchers.anyInt; 45import static org.mockito.Matchers.anyLong; 46import static org.mockito.Matchers.eq; 47import static org.mockito.Mockito.doAnswer; 48import static org.mockito.Mockito.doReturn; 49import static org.mockito.Mockito.times; 50import static org.mockito.Mockito.timeout; 51import static org.mockito.Mockito.mock; 52import static org.mockito.Mockito.verify; 53import static org.mockito.Mockito.when; 54 55/** 56 * Performs tests of the {@link VideoProvider} and {@link VideoCall} APIs. Ensures that requests 57 * sent from an InCallService are routed through Telecom to a VideoProvider, and that callbacks are 58 * correctly routed. 59 */ 60public class VideoProviderTest extends TelecomSystemTest { 61 private static final int ORIENTATION_0 = 0; 62 private static final int ORIENTATION_90 = 90; 63 private static final float ZOOM_LEVEL = 3.0f; 64 65 @Mock private VideoCall.Callback mVideoCallCallback; 66 private IdPair mCallIds; 67 private InCallService.VideoCall mVideoCall; 68 private VideoCallImpl mVideoCallImpl; 69 private ConnectionServiceFixture.ConnectionInfo mConnectionInfo; 70 private CountDownLatch mVerificationLock; 71 72 private Answer mVerification = new Answer() { 73 @Override 74 public Object answer(InvocationOnMock i) { 75 mVerificationLock.countDown(); 76 return null; 77 } 78 }; 79 80 @Override 81 public void setUp() throws Exception { 82 super.setUp(); 83 84 mCallIds = startAndMakeActiveOutgoingCall( 85 "650-555-1212", 86 mPhoneAccountA0.getAccountHandle(), 87 mConnectionServiceFixtureA); 88 89 // Set the video provider on the connection. 90 mConnectionServiceFixtureA.sendSetVideoProvider( 91 mConnectionServiceFixtureA.mLatestConnectionId); 92 93 // Provide a mocked VideoCall.Callback to receive callbacks via. 94 mVideoCallCallback = mock(InCallService.VideoCall.Callback.class); 95 96 mVideoCall = mInCallServiceFixtureX.getCall(mCallIds.mCallId).getVideoCallImpl(); 97 mVideoCallImpl = (VideoCallImpl) mVideoCall; 98 mVideoCall.registerCallback(mVideoCallCallback); 99 100 mConnectionInfo = mConnectionServiceFixtureA.mConnectionById.get(mCallIds.mConnectionId); 101 mVerificationLock = new CountDownLatch(1); 102 } 103 104 @Override 105 public void tearDown() throws Exception { 106 super.tearDown(); 107 } 108 109 /** 110 * Tests the {@link VideoCall#setCamera(String)}, {@link VideoProvider#onSetCamera(String)}, 111 * and {@link VideoCall.Callback#onCameraCapabilitiesChanged(CameraCapabilities)} 112 * APIS. 113 */ 114 public void testCameraChange() throws Exception { 115 // Wait until the callback has been received before performing verification. 116 doAnswer(mVerification).when(mVideoCallCallback) 117 .onCameraCapabilitiesChanged(any(CameraCapabilities.class)); 118 119 // Make 2 setCamera requests. 120 mVideoCall.setCamera(MockVideoProvider.CAMERA_FRONT); 121 mVideoCall.setCamera(MockVideoProvider.CAMERA_BACK); 122 123 mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS); 124 125 // Capture the video profile reported via the callback. 126 ArgumentCaptor<CameraCapabilities> cameraCapabilitiesCaptor = 127 ArgumentCaptor.forClass(CameraCapabilities.class); 128 129 // Verify that the callback was called twice and capture the callback arguments. 130 verify(mVideoCallCallback, timeout(TEST_TIMEOUT).times(2)) 131 .onCameraCapabilitiesChanged(cameraCapabilitiesCaptor.capture()); 132 133 assertEquals(2, cameraCapabilitiesCaptor.getAllValues().size()); 134 135 List<CameraCapabilities> cameraCapabilities = cameraCapabilitiesCaptor.getAllValues(); 136 // Ensure dimensions are as expected. 137 assertEquals(MockVideoProvider.CAMERA_FRONT_DIMENSIONS, 138 cameraCapabilities.get(0).getHeight()); 139 assertEquals(MockVideoProvider.CAMERA_BACK_DIMENSIONS, 140 cameraCapabilities.get(1).getHeight()); 141 } 142 143 /** 144 * Tests the {@link VideoCall#setPreviewSurface(Surface)} and 145 * {@link VideoProvider#onSetPreviewSurface(Surface)} APIs. 146 */ 147 public void testSetPreviewSurface() throws Exception { 148 final Surface surface = new Surface(new SurfaceTexture(1)); 149 mVideoCall.setPreviewSurface(surface); 150 151 assertTrueWithTimeout(new Predicate<Void>() { 152 @Override 153 public boolean apply(Void v) { 154 return mConnectionInfo.mockVideoProvider.getPreviewSurface() == surface; 155 } 156 }); 157 158 mVideoCall.setPreviewSurface(null); 159 160 assertTrueWithTimeout(new Predicate<Void>() { 161 @Override 162 public boolean apply(Void v) { 163 return mConnectionInfo.mockVideoProvider.getPreviewSurface() == null; 164 } 165 }); 166 } 167 168 /** 169 * Tests the {@link VideoCall#setDisplaySurface(Surface)} and 170 * {@link VideoProvider#onSetDisplaySurface(Surface)} APIs. 171 */ 172 public void testSetDisplaySurface() throws Exception { 173 final Surface surface = new Surface(new SurfaceTexture(1)); 174 mVideoCall.setDisplaySurface(surface); 175 176 assertTrueWithTimeout(new Predicate<Void>() { 177 @Override 178 public boolean apply(Void v) { 179 return mConnectionInfo.mockVideoProvider.getDisplaySurface() == surface; 180 } 181 }); 182 183 mVideoCall.setDisplaySurface(null); 184 185 assertTrueWithTimeout(new Predicate<Void>() { 186 @Override 187 public boolean apply(Void v) { 188 return mConnectionInfo.mockVideoProvider.getDisplaySurface() == null; 189 } 190 }); 191 } 192 193 /** 194 * Tests the {@link VideoCall#setDeviceOrientation(int)} and 195 * {@link VideoProvider#onSetDeviceOrientation(int)} APIs. 196 */ 197 public void testSetDeviceOrientation() throws Exception { 198 mVideoCall.setDeviceOrientation(ORIENTATION_0); 199 200 assertTrueWithTimeout(new Predicate<Void>() { 201 @Override 202 public boolean apply(Void v) { 203 return mConnectionInfo.mockVideoProvider.getDeviceOrientation() == ORIENTATION_0; 204 } 205 }); 206 207 mVideoCall.setDeviceOrientation(ORIENTATION_90); 208 209 assertTrueWithTimeout(new Predicate<Void>() { 210 @Override 211 public boolean apply(Void v) { 212 return mConnectionInfo.mockVideoProvider.getDeviceOrientation() == ORIENTATION_90; 213 } 214 }); 215 } 216 217 /** 218 * Tests the {@link VideoCall#setZoom(float)} and {@link VideoProvider#onSetZoom(float)} APIs. 219 */ 220 public void testSetZoom() throws Exception { 221 mVideoCall.setZoom(ZOOM_LEVEL); 222 223 assertTrueWithTimeout(new Predicate<Void>() { 224 @Override 225 public boolean apply(Void v) { 226 return mConnectionInfo.mockVideoProvider.getZoom() == ZOOM_LEVEL; 227 } 228 }); 229 } 230 231 /** 232 * Tests the {@link VideoCall#sendSessionModifyRequest(VideoProfile)}, 233 * {@link VideoProvider#onSendSessionModifyRequest(VideoProfile, VideoProfile)}, 234 * {@link VideoProvider#receiveSessionModifyResponse(int, VideoProfile, VideoProfile)}, and 235 * {@link VideoCall.Callback#onSessionModifyResponseReceived(int, VideoProfile, VideoProfile)} 236 * APIs. 237 * 238 * Emulates a scenario where an InCallService sends a request to upgrade to video, which the 239 * peer accepts as-is. 240 */ 241 public void testSessionModifyRequest() throws Exception { 242 VideoProfile requestProfile = new VideoProfile(VideoProfile.STATE_BIDIRECTIONAL); 243 244 // Set the starting video state on the video call impl; normally this would be set based on 245 // the original android.telecom.Call instance. 246 mVideoCallImpl.setVideoState(VideoProfile.STATE_RX_ENABLED); 247 248 doAnswer(mVerification).when(mVideoCallCallback) 249 .onSessionModifyResponseReceived(anyInt(), any(VideoProfile.class), 250 any(VideoProfile.class)); 251 252 // Send the request. 253 mVideoCall.sendSessionModifyRequest(requestProfile); 254 255 mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS); 256 257 // Capture the video profiles from the callback. 258 ArgumentCaptor<VideoProfile> fromVideoProfileCaptor = 259 ArgumentCaptor.forClass(VideoProfile.class); 260 ArgumentCaptor<VideoProfile> toVideoProfileCaptor = 261 ArgumentCaptor.forClass(VideoProfile.class); 262 263 // Verify we got a response and capture the profiles. 264 verify(mVideoCallCallback, timeout(TEST_TIMEOUT)) 265 .onSessionModifyResponseReceived(eq(VideoProvider.SESSION_MODIFY_REQUEST_SUCCESS), 266 fromVideoProfileCaptor.capture(), toVideoProfileCaptor.capture()); 267 268 assertEquals(VideoProfile.STATE_RX_ENABLED, 269 fromVideoProfileCaptor.getValue().getVideoState()); 270 assertEquals(VideoProfile.STATE_BIDIRECTIONAL, 271 toVideoProfileCaptor.getValue().getVideoState()); 272 } 273 274 /** 275 * Tests the {@link VideoCall#sendSessionModifyResponse(VideoProfile)}, 276 * and {@link VideoProvider#onSendSessionModifyResponse(VideoProfile)} APIs. 277 */ 278 public void testSessionModifyResponse() throws Exception { 279 VideoProfile sessionModifyResponse = new VideoProfile(VideoProfile.STATE_TX_ENABLED); 280 281 mVideoCall.sendSessionModifyResponse(sessionModifyResponse); 282 283 assertTrueWithTimeout(new Predicate<Void>() { 284 @Override 285 public boolean apply(Void v) { 286 VideoProfile response = mConnectionInfo.mockVideoProvider 287 .getSessionModifyResponse(); 288 return response != null && response.getVideoState() == VideoProfile.STATE_TX_ENABLED; 289 } 290 }); 291 } 292 293 /** 294 * Tests the {@link VideoCall#requestCameraCapabilities()} ()}, 295 * {@link VideoProvider#onRequestCameraCapabilities()} ()}, and 296 * {@link VideoCall.Callback#onCameraCapabilitiesChanged(CameraCapabilities)} APIs. 297 */ 298 public void testRequestCameraCapabilities() throws Exception { 299 // Wait until the callback has been received before performing verification. 300 doAnswer(mVerification).when(mVideoCallCallback) 301 .onCameraCapabilitiesChanged(any(CameraCapabilities.class)); 302 303 mVideoCall.requestCameraCapabilities(); 304 305 mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS); 306 307 verify(mVideoCallCallback, timeout(TEST_TIMEOUT)) 308 .onCameraCapabilitiesChanged(any(CameraCapabilities.class)); 309 } 310 311 /** 312 * Tests the {@link VideoCall#setPauseImage(Uri)}, and 313 * {@link VideoProvider#onSetPauseImage(Uri)} APIs. 314 */ 315 public void testSetPauseImage() throws Exception { 316 final Uri testUri = Uri.fromParts("file", "test.jpg", null); 317 mVideoCall.setPauseImage(testUri); 318 319 assertTrueWithTimeout(new Predicate<Void>() { 320 @Override 321 public boolean apply(Void v) { 322 Uri pauseImage = mConnectionInfo.mockVideoProvider.getPauseImage(); 323 return pauseImage != null && pauseImage.equals(testUri); 324 } 325 }); 326 } 327 328 /** 329 * Tests the {@link VideoCall#requestCallDataUsage()}, 330 * {@link VideoProvider#onRequestConnectionDataUsage()}, and 331 * {@link VideoCall.Callback#onCallDataUsageChanged(long)} APIs. 332 */ 333 public void testRequestDataUsage() throws Exception { 334 // Wait until the callback has been received before performing verification. 335 doAnswer(mVerification).when(mVideoCallCallback) 336 .onCallDataUsageChanged(anyLong()); 337 338 mVideoCall.requestCallDataUsage(); 339 340 mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS); 341 342 verify(mVideoCallCallback, timeout(TEST_TIMEOUT)) 343 .onCallDataUsageChanged(eq(MockVideoProvider.DATA_USAGE)); 344 } 345 346 /** 347 * Tests the {@link VideoProvider#receiveSessionModifyRequest(VideoProfile)}, 348 * {@link VideoCall.Callback#onSessionModifyRequestReceived(VideoProfile)} APIs. 349 */ 350 public void testReceiveSessionModifyRequest() throws Exception { 351 // Wait until the callback has been received before performing verification. 352 doAnswer(mVerification).when(mVideoCallCallback) 353 .onSessionModifyRequestReceived(any(VideoProfile.class)); 354 355 mConnectionInfo.mockVideoProvider.sendMockSessionModifyRequest(); 356 357 mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS); 358 359 ArgumentCaptor<VideoProfile> requestProfileCaptor = 360 ArgumentCaptor.forClass(VideoProfile.class); 361 verify(mVideoCallCallback, timeout(TEST_TIMEOUT)) 362 .onSessionModifyRequestReceived(requestProfileCaptor.capture()); 363 assertEquals(VideoProfile.STATE_BIDIRECTIONAL, 364 requestProfileCaptor.getValue().getVideoState()); 365 } 366 367 368 /** 369 * Tests the {@link VideoProvider#handleCallSessionEvent(int)}, and 370 * {@link VideoCall.Callback#onCallSessionEvent(int)} APIs. 371 */ 372 public void testSessionEvent() throws Exception { 373 // Wait until the callback has been received before performing verification. 374 doAnswer(mVerification).when(mVideoCallCallback) 375 .onCallSessionEvent(anyInt()); 376 377 mConnectionInfo.mockVideoProvider.sendMockSessionEvent( 378 VideoProvider.SESSION_EVENT_CAMERA_READY); 379 380 mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS); 381 382 verify(mVideoCallCallback, timeout(TEST_TIMEOUT)) 383 .onCallSessionEvent(eq(VideoProvider.SESSION_EVENT_CAMERA_READY)); 384 } 385 386 /** 387 * Tests the {@link VideoProvider#changePeerDimensions(int, int)} and 388 * {@link VideoCall.Callback#onPeerDimensionsChanged(int, int)} APIs. 389 */ 390 public void testPeerDimensionChange() throws Exception { 391 // Wait until the callback has been received before performing verification. 392 doAnswer(mVerification).when(mVideoCallCallback) 393 .onPeerDimensionsChanged(anyInt(), anyInt()); 394 395 mConnectionInfo.mockVideoProvider.sendMockPeerDimensions(MockVideoProvider.PEER_DIMENSIONS, 396 MockVideoProvider.PEER_DIMENSIONS); 397 398 mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS); 399 400 verify(mVideoCallCallback, timeout(TEST_TIMEOUT)) 401 .onPeerDimensionsChanged(eq(MockVideoProvider.PEER_DIMENSIONS), 402 eq(MockVideoProvider.PEER_DIMENSIONS)); 403 } 404 405 /** 406 * Tests the {@link VideoProvider#changeVideoQuality(int)} and 407 * {@link VideoCall.Callback#onVideoQualityChanged(int)} APIs. 408 */ 409 public void testVideoQualityChange() throws Exception { 410 // Wait until the callback has been received before performing verification. 411 doAnswer(mVerification).when(mVideoCallCallback) 412 .onVideoQualityChanged(anyInt()); 413 414 mConnectionInfo.mockVideoProvider.sendMockVideoQuality(VideoProfile.QUALITY_HIGH); 415 416 mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS); 417 418 verify(mVideoCallCallback, timeout(TEST_TIMEOUT)) 419 .onVideoQualityChanged(eq(VideoProfile.QUALITY_HIGH)); 420 } 421} 422