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