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