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