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