VideoProviderTest.java revision d8a27d5fc787f8839d3185f2b9137a8c2f1d68a0
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.app.AppOpsManager; 27import android.content.Context; 28import android.graphics.SurfaceTexture; 29import android.net.Uri; 30import android.os.Handler; 31import android.os.Looper; 32import android.os.UserHandle; 33import android.telecom.Connection.VideoProvider; 34import android.telecom.InCallService; 35import android.telecom.InCallService.VideoCall; 36import android.telecom.VideoCallImpl; 37import android.telecom.VideoProfile; 38import android.telecom.VideoProfile.CameraCapabilities; 39import android.test.suitebuilder.annotation.MediumTest; 40import android.view.Surface; 41 42import com.google.common.base.Predicate; 43 44import java.util.List; 45import java.util.concurrent.CountDownLatch; 46import java.util.concurrent.TimeUnit; 47 48import static android.test.MoreAsserts.assertEquals; 49import static org.mockito.Matchers.any; 50import static org.mockito.Matchers.anyInt; 51import static org.mockito.Matchers.anyLong; 52import static org.mockito.Matchers.anyString; 53import static org.mockito.Matchers.eq; 54import static org.mockito.Mockito.doAnswer; 55import static org.mockito.Mockito.doNothing; 56import static org.mockito.Mockito.doReturn; 57import static org.mockito.Mockito.doThrow; 58import static org.mockito.Mockito.times; 59import static org.mockito.Mockito.timeout; 60import static org.mockito.Mockito.mock; 61import static org.mockito.Mockito.verify; 62import static org.mockito.Mockito.when; 63 64/** 65 * Performs tests of the {@link VideoProvider} and {@link VideoCall} APIs. Ensures that requests 66 * sent from an InCallService are routed through Telecom to a VideoProvider, and that callbacks are 67 * correctly routed. 68 */ 69public class VideoProviderTest extends TelecomSystemTest { 70 private static final int ORIENTATION_0 = 0; 71 private static final int ORIENTATION_90 = 90; 72 private static final float ZOOM_LEVEL = 3.0f; 73 74 @Mock private VideoCall.Callback mVideoCallCallback; 75 private IdPair mCallIds; 76 private InCallService.VideoCall mVideoCall; 77 private VideoCallImpl mVideoCallImpl; 78 private ConnectionServiceFixture.ConnectionInfo mConnectionInfo; 79 private CountDownLatch mVerificationLock; 80 private AppOpsManager mAppOpsManager; 81 82 private Answer mVerification = new Answer() { 83 @Override 84 public Object answer(InvocationOnMock i) { 85 mVerificationLock.countDown(); 86 return null; 87 } 88 }; 89 90 @Override 91 public void setUp() throws Exception { 92 super.setUp(); 93 mContext = mComponentContextFixture.getTestDouble().getApplicationContext(); 94 mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); 95 96 mCallIds = startAndMakeActiveOutgoingCall( 97 "650-555-1212", 98 mPhoneAccountA0.getAccountHandle(), 99 mConnectionServiceFixtureA); 100 101 // Set the video provider on the connection. 102 mConnectionServiceFixtureA.sendSetVideoProvider( 103 mConnectionServiceFixtureA.mLatestConnectionId); 104 105 // Provide a mocked VideoCall.Callback to receive callbacks via. 106 mVideoCallCallback = mock(InCallService.VideoCall.Callback.class); 107 108 mVideoCall = mInCallServiceFixtureX.getCall(mCallIds.mCallId).getVideoCallImpl( 109 mInCallServiceComponentNameX.getPackageName()); 110 mVideoCallImpl = (VideoCallImpl) mVideoCall; 111 mVideoCall.registerCallback(mVideoCallCallback); 112 113 mConnectionInfo = mConnectionServiceFixtureA.mConnectionById.get(mCallIds.mConnectionId); 114 mVerificationLock = new CountDownLatch(1); 115 waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT); 116 117 doNothing().when(mContext).enforcePermission(anyString(), anyInt(), anyInt(), anyString()); 118 doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager).noteOp(anyInt(), anyInt(), 119 anyString()); 120 } 121 122 @Override 123 public void tearDown() throws Exception { 124 super.tearDown(); 125 } 126 127 /** 128 * Tests the {@link VideoCall#setCamera(String)}, {@link VideoProvider#onSetCamera(String)}, 129 * and {@link VideoCall.Callback#onCameraCapabilitiesChanged(CameraCapabilities)} 130 * APIS. 131 */ 132 @MediumTest 133 public void testCameraChange() throws Exception { 134 // Wait until the callback has been received before performing verification. 135 doAnswer(mVerification).when(mVideoCallCallback) 136 .onCameraCapabilitiesChanged(any(CameraCapabilities.class)); 137 138 // Make 2 setCamera requests. 139 mVideoCall.setCamera(MockVideoProvider.CAMERA_FRONT); 140 mVideoCall.setCamera(MockVideoProvider.CAMERA_BACK); 141 142 mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS); 143 144 // Capture the video profile reported via the callback. 145 ArgumentCaptor<CameraCapabilities> cameraCapabilitiesCaptor = 146 ArgumentCaptor.forClass(CameraCapabilities.class); 147 148 // Verify that the callback was called twice and capture the callback arguments. 149 verify(mVideoCallCallback, timeout(TEST_TIMEOUT).times(2)) 150 .onCameraCapabilitiesChanged(cameraCapabilitiesCaptor.capture()); 151 152 assertEquals(2, cameraCapabilitiesCaptor.getAllValues().size()); 153 154 List<CameraCapabilities> cameraCapabilities = cameraCapabilitiesCaptor.getAllValues(); 155 // Ensure dimensions are as expected. 156 assertEquals(MockVideoProvider.CAMERA_FRONT_DIMENSIONS, 157 cameraCapabilities.get(0).getHeight()); 158 assertEquals(MockVideoProvider.CAMERA_BACK_DIMENSIONS, 159 cameraCapabilities.get(1).getHeight()); 160 } 161 162 /** 163 * Tests the caller permission check in {@link VideoCall#setCamera(String)} to ensure a camera 164 * change from a non-permitted caller is ignored. 165 */ 166 @MediumTest 167 public void testCameraChangePermissionFail() throws Exception { 168 // Wait until the callback has been received before performing verification. 169 doAnswer(mVerification).when(mVideoCallCallback).onCallSessionEvent(anyInt()); 170 171 // ensure permission check fails. 172 doThrow(new SecurityException()).when(mContext) 173 .enforcePermission(anyString(), anyInt(), anyInt(), anyString()); 174 175 // Make a request to change the camera 176 mVideoCall.setCamera(MockVideoProvider.CAMERA_FRONT); 177 mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS); 178 179 // Capture the session event reported via the callback. 180 ArgumentCaptor<Integer> sessionEventCaptor = ArgumentCaptor.forClass(Integer.class); 181 verify(mVideoCallCallback, timeout(TEST_TIMEOUT)).onCallSessionEvent( 182 sessionEventCaptor.capture()); 183 184 assertEquals(VideoProvider.SESSION_EVENT_CAMERA_PERMISSION_ERROR, 185 sessionEventCaptor.getValue().intValue()); 186 } 187 188 /** 189 * Tests the caller app ops check in {@link VideoCall#setCamera(String)} to ensure a camera 190 * change from a non-permitted caller is ignored. 191 */ 192 @MediumTest 193 public void testCameraChangeAppOpsFail() throws Exception { 194 // Wait until the callback has been received before performing verification. 195 doAnswer(mVerification).when(mVideoCallCallback).onCallSessionEvent(anyInt()); 196 197 // ensure app ops check fails. 198 doReturn(AppOpsManager.MODE_ERRORED).when(mAppOpsManager).noteOp(anyInt(), anyInt(), 199 anyString()); 200 201 // Make a request to change the camera 202 mVideoCall.setCamera(MockVideoProvider.CAMERA_FRONT); 203 mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS); 204 205 // Capture the session event reported via the callback. 206 ArgumentCaptor<Integer> sessionEventCaptor = ArgumentCaptor.forClass(Integer.class); 207 verify(mVideoCallCallback, timeout(TEST_TIMEOUT)).onCallSessionEvent( 208 sessionEventCaptor.capture()); 209 210 assertEquals(VideoProvider.SESSION_EVENT_CAMERA_PERMISSION_ERROR, 211 sessionEventCaptor.getValue().intValue()); 212 } 213 214 /** 215 * Tests the caller user handle check in {@link VideoCall#setCamera(String)} to ensure a camera 216 * change from a background user is not permitted. 217 */ 218 @MediumTest 219 public void testCameraChangeUserFail() throws Exception { 220 // Wait until the callback has been received before performing verification. 221 doAnswer(mVerification).when(mVideoCallCallback).onCallSessionEvent(anyInt()); 222 223 // Set a fake user to be the current foreground user. 224 mTelecomSystem.getCallsManager().onUserSwitch(new UserHandle(1000)); 225 226 // Make a request to change the camera 227 mVideoCall.setCamera(MockVideoProvider.CAMERA_FRONT); 228 mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS); 229 230 // Capture the session event reported via the callback. 231 ArgumentCaptor<Integer> sessionEventCaptor = ArgumentCaptor.forClass(Integer.class); 232 verify(mVideoCallCallback, timeout(TEST_TIMEOUT)).onCallSessionEvent( 233 sessionEventCaptor.capture()); 234 235 assertEquals(VideoProvider.SESSION_EVENT_CAMERA_PERMISSION_ERROR, 236 sessionEventCaptor.getValue().intValue()); 237 } 238 239 /** 240 * Tests the caller permission check in {@link VideoCall#setCamera(String)} to ensure the 241 * caller can null out the camera, even if they do not have camera permission. 242 */ 243 @MediumTest 244 public void testCameraChangeNullNoPermission() throws Exception { 245 // Wait until the callback has been received before performing verification. 246 doAnswer(mVerification).when(mVideoCallCallback).onCallSessionEvent(anyInt()); 247 248 // ensure permission check fails. 249 doThrow(new SecurityException()).when(mContext) 250 .enforcePermission(anyString(), anyInt(), anyInt(), anyString()); 251 252 // Make a request to null the camera; we expect the permission check won't happen. 253 mVideoCall.setCamera(null); 254 mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS); 255 256 // Capture the session event reported via the callback. 257 ArgumentCaptor<Integer> sessionEventCaptor = ArgumentCaptor.forClass(Integer.class); 258 verify(mVideoCallCallback, timeout(TEST_TIMEOUT)).onCallSessionEvent( 259 sessionEventCaptor.capture()); 260 261 // See the MockVideoProvider class; for convenience when the camera is nulled we just send 262 // back a "camera ready" event. 263 assertEquals(VideoProvider.SESSION_EVENT_CAMERA_READY, 264 sessionEventCaptor.getValue().intValue()); 265 } 266 267 /** 268 * Tests the {@link VideoCall#setPreviewSurface(Surface)} and 269 * {@link VideoProvider#onSetPreviewSurface(Surface)} APIs. 270 */ 271 @MediumTest 272 public void testSetPreviewSurface() throws Exception { 273 final Surface surface = new Surface(new SurfaceTexture(1)); 274 mVideoCall.setPreviewSurface(surface); 275 276 assertTrueWithTimeout(new Predicate<Void>() { 277 @Override 278 public boolean apply(Void v) { 279 return mConnectionInfo.mockVideoProvider.getPreviewSurface() == surface; 280 } 281 }); 282 283 mVideoCall.setPreviewSurface(null); 284 285 assertTrueWithTimeout(new Predicate<Void>() { 286 @Override 287 public boolean apply(Void v) { 288 return mConnectionInfo.mockVideoProvider.getPreviewSurface() == null; 289 } 290 }); 291 } 292 293 /** 294 * Tests the {@link VideoCall#setDisplaySurface(Surface)} and 295 * {@link VideoProvider#onSetDisplaySurface(Surface)} APIs. 296 */ 297 @MediumTest 298 public void testSetDisplaySurface() throws Exception { 299 final Surface surface = new Surface(new SurfaceTexture(1)); 300 mVideoCall.setDisplaySurface(surface); 301 302 assertTrueWithTimeout(new Predicate<Void>() { 303 @Override 304 public boolean apply(Void v) { 305 return mConnectionInfo.mockVideoProvider.getDisplaySurface() == surface; 306 } 307 }); 308 309 mVideoCall.setDisplaySurface(null); 310 311 assertTrueWithTimeout(new Predicate<Void>() { 312 @Override 313 public boolean apply(Void v) { 314 return mConnectionInfo.mockVideoProvider.getDisplaySurface() == null; 315 } 316 }); 317 } 318 319 /** 320 * Tests the {@link VideoCall#setDeviceOrientation(int)} and 321 * {@link VideoProvider#onSetDeviceOrientation(int)} APIs. 322 */ 323 @MediumTest 324 public void testSetDeviceOrientation() throws Exception { 325 mVideoCall.setDeviceOrientation(ORIENTATION_0); 326 327 assertTrueWithTimeout(new Predicate<Void>() { 328 @Override 329 public boolean apply(Void v) { 330 return mConnectionInfo.mockVideoProvider.getDeviceOrientation() == ORIENTATION_0; 331 } 332 }); 333 334 mVideoCall.setDeviceOrientation(ORIENTATION_90); 335 336 assertTrueWithTimeout(new Predicate<Void>() { 337 @Override 338 public boolean apply(Void v) { 339 return mConnectionInfo.mockVideoProvider.getDeviceOrientation() == ORIENTATION_90; 340 } 341 }); 342 } 343 344 /** 345 * Tests the {@link VideoCall#setZoom(float)} and {@link VideoProvider#onSetZoom(float)} APIs. 346 */ 347 @MediumTest 348 public void testSetZoom() throws Exception { 349 mVideoCall.setZoom(ZOOM_LEVEL); 350 351 assertTrueWithTimeout(new Predicate<Void>() { 352 @Override 353 public boolean apply(Void v) { 354 return mConnectionInfo.mockVideoProvider.getZoom() == ZOOM_LEVEL; 355 } 356 }); 357 } 358 359 /** 360 * Tests the {@link VideoCall#sendSessionModifyRequest(VideoProfile)}, 361 * {@link VideoProvider#onSendSessionModifyRequest(VideoProfile, VideoProfile)}, 362 * {@link VideoProvider#receiveSessionModifyResponse(int, VideoProfile, VideoProfile)}, and 363 * {@link VideoCall.Callback#onSessionModifyResponseReceived(int, VideoProfile, VideoProfile)} 364 * APIs. 365 * 366 * Emulates a scenario where an InCallService sends a request to upgrade to video, which the 367 * peer accepts as-is. 368 */ 369 @MediumTest 370 public void testSessionModifyRequest() throws Exception { 371 VideoProfile requestProfile = new VideoProfile(VideoProfile.STATE_BIDIRECTIONAL); 372 373 // Set the starting video state on the video call impl; normally this would be set based on 374 // the original android.telecom.Call instance. 375 mVideoCallImpl.setVideoState(VideoProfile.STATE_RX_ENABLED); 376 377 doAnswer(mVerification).when(mVideoCallCallback) 378 .onSessionModifyResponseReceived(anyInt(), any(VideoProfile.class), 379 any(VideoProfile.class)); 380 381 // Send the request. 382 mVideoCall.sendSessionModifyRequest(requestProfile); 383 384 mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS); 385 386 // Capture the video profiles from the callback. 387 ArgumentCaptor<VideoProfile> fromVideoProfileCaptor = 388 ArgumentCaptor.forClass(VideoProfile.class); 389 ArgumentCaptor<VideoProfile> toVideoProfileCaptor = 390 ArgumentCaptor.forClass(VideoProfile.class); 391 392 // Verify we got a response and capture the profiles. 393 verify(mVideoCallCallback, timeout(TEST_TIMEOUT)) 394 .onSessionModifyResponseReceived(eq(VideoProvider.SESSION_MODIFY_REQUEST_SUCCESS), 395 fromVideoProfileCaptor.capture(), toVideoProfileCaptor.capture()); 396 397 assertEquals(VideoProfile.STATE_RX_ENABLED, 398 fromVideoProfileCaptor.getValue().getVideoState()); 399 assertEquals(VideoProfile.STATE_BIDIRECTIONAL, 400 toVideoProfileCaptor.getValue().getVideoState()); 401 } 402 403 /** 404 * Tests the {@link VideoCall#sendSessionModifyResponse(VideoProfile)}, 405 * and {@link VideoProvider#onSendSessionModifyResponse(VideoProfile)} APIs. 406 */ 407 @MediumTest 408 public void testSessionModifyResponse() throws Exception { 409 VideoProfile sessionModifyResponse = new VideoProfile(VideoProfile.STATE_TX_ENABLED); 410 411 mVideoCall.sendSessionModifyResponse(sessionModifyResponse); 412 413 assertTrueWithTimeout(new Predicate<Void>() { 414 @Override 415 public boolean apply(Void v) { 416 VideoProfile response = mConnectionInfo.mockVideoProvider 417 .getSessionModifyResponse(); 418 return response != null && response.getVideoState() == VideoProfile.STATE_TX_ENABLED; 419 } 420 }); 421 } 422 423 /** 424 * Tests the {@link VideoCall#requestCameraCapabilities()} ()}, 425 * {@link VideoProvider#onRequestCameraCapabilities()} ()}, and 426 * {@link VideoCall.Callback#onCameraCapabilitiesChanged(CameraCapabilities)} APIs. 427 */ 428 @MediumTest 429 public void testRequestCameraCapabilities() throws Exception { 430 // Wait until the callback has been received before performing verification. 431 doAnswer(mVerification).when(mVideoCallCallback) 432 .onCameraCapabilitiesChanged(any(CameraCapabilities.class)); 433 434 mVideoCall.requestCameraCapabilities(); 435 436 mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS); 437 438 verify(mVideoCallCallback, timeout(TEST_TIMEOUT)) 439 .onCameraCapabilitiesChanged(any(CameraCapabilities.class)); 440 } 441 442 /** 443 * Tests the {@link VideoCall#setPauseImage(Uri)}, and 444 * {@link VideoProvider#onSetPauseImage(Uri)} APIs. 445 */ 446 @MediumTest 447 public void testSetPauseImage() throws Exception { 448 final Uri testUri = Uri.fromParts("file", "test.jpg", null); 449 mVideoCall.setPauseImage(testUri); 450 451 assertTrueWithTimeout(new Predicate<Void>() { 452 @Override 453 public boolean apply(Void v) { 454 Uri pauseImage = mConnectionInfo.mockVideoProvider.getPauseImage(); 455 return pauseImage != null && pauseImage.equals(testUri); 456 } 457 }); 458 } 459 460 /** 461 * Tests the {@link VideoCall#requestCallDataUsage()}, 462 * {@link VideoProvider#onRequestConnectionDataUsage()}, and 463 * {@link VideoCall.Callback#onCallDataUsageChanged(long)} APIs. 464 */ 465 @MediumTest 466 public void testRequestDataUsage() throws Exception { 467 // Wait until the callback has been received before performing verification. 468 doAnswer(mVerification).when(mVideoCallCallback) 469 .onCallDataUsageChanged(anyLong()); 470 471 mVideoCall.requestCallDataUsage(); 472 473 mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS); 474 475 verify(mVideoCallCallback, timeout(TEST_TIMEOUT)) 476 .onCallDataUsageChanged(eq(MockVideoProvider.DATA_USAGE)); 477 } 478 479 /** 480 * Tests the {@link VideoProvider#receiveSessionModifyRequest(VideoProfile)}, 481 * {@link VideoCall.Callback#onSessionModifyRequestReceived(VideoProfile)} APIs. 482 */ 483 @MediumTest 484 public void testReceiveSessionModifyRequest() throws Exception { 485 // Wait until the callback has been received before performing verification. 486 doAnswer(mVerification).when(mVideoCallCallback) 487 .onSessionModifyRequestReceived(any(VideoProfile.class)); 488 489 mConnectionInfo.mockVideoProvider.sendMockSessionModifyRequest(); 490 491 mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS); 492 493 ArgumentCaptor<VideoProfile> requestProfileCaptor = 494 ArgumentCaptor.forClass(VideoProfile.class); 495 verify(mVideoCallCallback, timeout(TEST_TIMEOUT)) 496 .onSessionModifyRequestReceived(requestProfileCaptor.capture()); 497 assertEquals(VideoProfile.STATE_BIDIRECTIONAL, 498 requestProfileCaptor.getValue().getVideoState()); 499 } 500 501 502 /** 503 * Tests the {@link VideoProvider#handleCallSessionEvent(int)}, and 504 * {@link VideoCall.Callback#onCallSessionEvent(int)} APIs. 505 */ 506 @MediumTest 507 public void testSessionEvent() throws Exception { 508 // Wait until the callback has been received before performing verification. 509 doAnswer(mVerification).when(mVideoCallCallback) 510 .onCallSessionEvent(anyInt()); 511 512 mConnectionInfo.mockVideoProvider.sendMockSessionEvent( 513 VideoProvider.SESSION_EVENT_CAMERA_READY); 514 515 mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS); 516 517 verify(mVideoCallCallback, timeout(TEST_TIMEOUT)) 518 .onCallSessionEvent(eq(VideoProvider.SESSION_EVENT_CAMERA_READY)); 519 } 520 521 /** 522 * Tests the {@link VideoProvider#changePeerDimensions(int, int)} and 523 * {@link VideoCall.Callback#onPeerDimensionsChanged(int, int)} APIs. 524 */ 525 @MediumTest 526 public void testPeerDimensionChange() throws Exception { 527 // Wait until the callback has been received before performing verification. 528 doAnswer(mVerification).when(mVideoCallCallback) 529 .onPeerDimensionsChanged(anyInt(), anyInt()); 530 531 mConnectionInfo.mockVideoProvider.sendMockPeerDimensions(MockVideoProvider.PEER_DIMENSIONS, 532 MockVideoProvider.PEER_DIMENSIONS); 533 534 mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS); 535 536 verify(mVideoCallCallback, timeout(TEST_TIMEOUT)) 537 .onPeerDimensionsChanged(eq(MockVideoProvider.PEER_DIMENSIONS), 538 eq(MockVideoProvider.PEER_DIMENSIONS)); 539 } 540 541 /** 542 * Tests the {@link VideoProvider#changeVideoQuality(int)} and 543 * {@link VideoCall.Callback#onVideoQualityChanged(int)} APIs. 544 */ 545 @MediumTest 546 public void testVideoQualityChange() throws Exception { 547 // Wait until the callback has been received before performing verification. 548 doAnswer(mVerification).when(mVideoCallCallback) 549 .onVideoQualityChanged(anyInt()); 550 551 mConnectionInfo.mockVideoProvider.sendMockVideoQuality(VideoProfile.QUALITY_HIGH); 552 553 mVerificationLock.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS); 554 555 verify(mVideoCallCallback, timeout(TEST_TIMEOUT)) 556 .onVideoQualityChanged(eq(VideoProfile.QUALITY_HIGH)); 557 } 558} 559