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