CameraDeviceBinderTest.java revision 70c2207c34cf0e6b3b383b1b1500ff5385aa51a6
1/*
2 * Copyright (C) 2013 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.mediaframeworktest.integration;
18
19import android.graphics.SurfaceTexture;
20import android.hardware.camera2.CameraMetadata;
21import android.hardware.camera2.CameraProperties;
22import android.hardware.camera2.CaptureRequest;
23import android.hardware.camera2.ICameraDeviceCallbacks;
24import android.hardware.camera2.ICameraDeviceUser;
25import android.hardware.camera2.impl.CameraMetadataNative;
26import android.hardware.camera2.utils.BinderHolder;
27import android.os.RemoteException;
28import android.test.AndroidTestCase;
29import android.test.suitebuilder.annotation.SmallTest;
30import android.util.Log;
31import android.view.Surface;
32
33import static android.hardware.camera2.CameraDevice.TEMPLATE_PREVIEW;
34
35import com.android.mediaframeworktest.MediaFrameworkIntegrationTestRunner;
36
37import org.mockito.ArgumentMatcher;
38import static org.mockito.Mockito.*;
39
40public class CameraDeviceBinderTest extends AndroidTestCase {
41    private static String TAG = "CameraDeviceBinderTest";
42    // Number of streaming callbacks need to check.
43    private static int NUM_CALLBACKS_CHECKED = 10;
44    // Wait for capture result timeout value: 1500ms
45    private final static int WAIT_FOR_COMPLETE_TIMEOUT_MS = 1500;
46
47    private int mCameraId;
48    private ICameraDeviceUser mCameraUser;
49    private CameraBinderTestUtils mUtils;
50    private ICameraDeviceCallbacks.Stub mMockCb;
51    private Surface mSurface;
52    // Need hold a Surfacetexture reference during a test execution, otherwise,
53    // it could be GCed during a test, which causes camera run into bad state.
54    private SurfaceTexture mSurfaceTexture;
55
56    public CameraDeviceBinderTest() {
57    }
58
59    public class DummyCameraDeviceCallbacks extends ICameraDeviceCallbacks.Stub {
60
61        @Override
62        public void notifyCallback(int msgType, int ext1, int ext2) throws RemoteException {
63        }
64
65        @Override
66        public void onResultReceived(int frameId, CameraMetadataNative result) throws RemoteException {
67        }
68    }
69
70    class IsMetadataNotEmpty extends ArgumentMatcher<CameraMetadataNative> {
71        public boolean matches(Object obj) {
72            return !((CameraMetadataNative) obj).isEmpty();
73        }
74     }
75
76    private void createDefaultSurface() {
77        mSurfaceTexture = new SurfaceTexture(/* ignored */0);
78        mSurfaceTexture.setDefaultBufferSize(640, 480);
79        mSurface = new Surface(mSurfaceTexture);
80    }
81
82    private CaptureRequest.Builder createDefaultBuilder(boolean needStream) throws Exception {
83        CameraMetadataNative metadata = new CameraMetadataNative();
84        assertTrue(metadata.isEmpty());
85
86        int status = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW, /* out */metadata);
87        assertEquals(CameraBinderTestUtils.NO_ERROR, status);
88        assertFalse(metadata.isEmpty());
89
90        CaptureRequest.Builder request = new CaptureRequest.Builder(metadata);
91        assertFalse(request.isEmpty());
92        assertFalse(metadata.isEmpty());
93        if (needStream) {
94            int streamId = mCameraUser.createStream(/* ignored */10, /* ignored */20,
95                    /* ignored */30, mSurface);
96            assertEquals(0, streamId);
97            request.addTarget(mSurface);
98        }
99        return request;
100    }
101
102    private int submitCameraRequest(CaptureRequest request, boolean streaming) throws Exception {
103        int requestId = mCameraUser.submitRequest(request, streaming);
104        assertTrue("Request IDs should be non-negative", requestId >= 0);
105        return requestId;
106    }
107
108    @Override
109    protected void setUp() throws Exception {
110        super.setUp();
111
112        /**
113         * Workaround for mockito and JB-MR2 incompatibility
114         *
115         * Avoid java.lang.IllegalArgumentException: dexcache == null
116         * https://code.google.com/p/dexmaker/issues/detail?id=2
117         */
118        System.setProperty("dexmaker.dexcache", getContext().getCacheDir().toString());
119        mUtils = new CameraBinderTestUtils(getContext());
120
121        // This cannot be set in the constructor, since the onCreate isn't
122        // called yet
123        mCameraId = MediaFrameworkIntegrationTestRunner.mCameraId;
124
125        ICameraDeviceCallbacks.Stub dummyCallbacks = new DummyCameraDeviceCallbacks();
126
127        String clientPackageName = getContext().getPackageName();
128
129        mMockCb = spy(dummyCallbacks);
130
131        BinderHolder holder = new BinderHolder();
132        mUtils.getCameraService().connectDevice(mMockCb, mCameraId,
133                clientPackageName, CameraBinderTestUtils.USE_CALLING_UID, holder);
134        mCameraUser = ICameraDeviceUser.Stub.asInterface(holder.getBinder());
135        assertNotNull(String.format("Camera %s was null", mCameraId), mCameraUser);
136        createDefaultSurface();
137
138        Log.v(TAG, String.format("Camera %s connected", mCameraId));
139    }
140
141    @Override
142    protected void tearDown() throws Exception {
143        mCameraUser.disconnect();
144        mCameraUser = null;
145        mSurface.release();
146        mSurfaceTexture.release();
147    }
148
149    @SmallTest
150    public void testCreateDefaultRequest() throws Exception {
151        CameraMetadataNative metadata = new CameraMetadataNative();
152        assertTrue(metadata.isEmpty());
153
154        int status = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW, /* out */metadata);
155        assertEquals(CameraBinderTestUtils.NO_ERROR, status);
156        assertFalse(metadata.isEmpty());
157
158    }
159
160    @SmallTest
161    public void testCreateStream() throws Exception {
162        int streamId = mCameraUser.createStream(/* ignored */10, /* ignored */20, /* ignored */30,
163                mSurface);
164        assertEquals(0, streamId);
165
166        assertEquals(CameraBinderTestUtils.ALREADY_EXISTS,
167                mCameraUser.createStream(/* ignored */0, /* ignored */0, /* ignored */0, mSurface));
168
169        assertEquals(CameraBinderTestUtils.NO_ERROR, mCameraUser.deleteStream(streamId));
170    }
171
172    @SmallTest
173    public void testDeleteInvalidStream() throws Exception {
174        assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(-1));
175        assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(0));
176        assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(1));
177        assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(0xC0FFEE));
178    }
179
180    @SmallTest
181    public void testCreateStreamTwo() throws Exception {
182
183        // Create first stream
184        int streamId = mCameraUser.createStream(/* ignored */0, /* ignored */0, /* ignored */0,
185                mSurface);
186        assertEquals(0, streamId);
187
188        assertEquals(CameraBinderTestUtils.ALREADY_EXISTS,
189                mCameraUser.createStream(/* ignored */0, /* ignored */0, /* ignored */0, mSurface));
190
191        // Create second stream with a different surface.
192        SurfaceTexture surfaceTexture = new SurfaceTexture(/* ignored */0);
193        surfaceTexture.setDefaultBufferSize(640, 480);
194        Surface surface2 = new Surface(surfaceTexture);
195
196        int streamId2 = mCameraUser.createStream(/* ignored */0, /* ignored */0, /* ignored */0,
197                surface2);
198        assertEquals(1, streamId2);
199
200        // Clean up streams
201        assertEquals(CameraBinderTestUtils.NO_ERROR, mCameraUser.deleteStream(streamId));
202        assertEquals(CameraBinderTestUtils.NO_ERROR, mCameraUser.deleteStream(streamId2));
203    }
204
205    @SmallTest
206    public void testSubmitBadRequest() throws Exception {
207
208        CaptureRequest.Builder builder = createDefaultBuilder(/* needStream */false);
209        CaptureRequest request1 = builder.build();
210        int status = mCameraUser.submitRequest(request1, /* streaming */false);
211        assertEquals("Expected submitRequest to return BAD_VALUE " +
212                "since we had 0 surface targets set.", CameraBinderTestUtils.BAD_VALUE, status);
213
214        builder.addTarget(mSurface);
215        CaptureRequest request2 = builder.build();
216        status = mCameraUser.submitRequest(request2, /* streaming */false);
217        assertEquals("Expected submitRequest to return BAD_VALUE since " +
218                "the target surface wasn't registered with createStream.",
219                CameraBinderTestUtils.BAD_VALUE, status);
220    }
221
222    @SmallTest
223    public void testSubmitGoodRequest() throws Exception {
224
225        CaptureRequest.Builder builder = createDefaultBuilder(/* needStream */true);
226        CaptureRequest request = builder.build();
227
228        // Submit valid request twice.
229        int requestId1 = submitCameraRequest(request, /* streaming */false);
230        int requestId2 = submitCameraRequest(request, /* streaming */false);
231        assertNotSame("Request IDs should be unique for multiple requests", requestId1, requestId2);
232
233    }
234
235    @SmallTest
236    public void testSubmitStreamingRequest() throws Exception {
237
238        CaptureRequest.Builder builder = createDefaultBuilder(/* needStream */true);
239
240        CaptureRequest request = builder.build();
241
242        // Submit valid request once (non-streaming), and another time
243        // (streaming)
244        int requestId1 = submitCameraRequest(request, /* streaming */false);
245
246        int requestIdStreaming = submitCameraRequest(request, /* streaming */true);
247        assertNotSame("Request IDs should be unique for multiple requests", requestId1,
248                requestIdStreaming);
249
250        int status = mCameraUser.cancelRequest(-1);
251        assertEquals("Invalid request IDs should not be cancellable",
252                CameraBinderTestUtils.BAD_VALUE, status);
253
254        status = mCameraUser.cancelRequest(requestId1);
255        assertEquals("Non-streaming request IDs should not be cancellable",
256                CameraBinderTestUtils.BAD_VALUE, status);
257
258        status = mCameraUser.cancelRequest(requestIdStreaming);
259        assertEquals("Streaming request IDs should be cancellable", CameraBinderTestUtils.NO_ERROR,
260                status);
261
262    }
263
264    @SmallTest
265    public void testCameraInfo() throws RemoteException {
266        CameraMetadataNative info = new CameraMetadataNative();
267
268        int status = mCameraUser.getCameraInfo(/*out*/info);
269        assertEquals(CameraBinderTestUtils.NO_ERROR, status);
270
271        assertFalse(info.isEmpty());
272        assertNotNull(info.get(CameraProperties.SCALER_AVAILABLE_FORMATS));
273    }
274
275    @SmallTest
276    public void testWaitUntilIdle() throws Exception {
277        CaptureRequest.Builder builder = createDefaultBuilder(/* needStream */true);
278        int requestIdStreaming = submitCameraRequest(builder.build(), /* streaming */true);
279
280        // Test Bad case first: waitUntilIdle when there is active repeating request
281        int status = mCameraUser.waitUntilIdle();
282        assertEquals("waitUntilIdle is invalid operation when there is active repeating request",
283            CameraBinderTestUtils.INVALID_OPERATION, status);
284
285        // Test good case, waitUntilIdle when there is no active repeating request
286        status = mCameraUser.cancelRequest(requestIdStreaming);
287        assertEquals(CameraBinderTestUtils.NO_ERROR, status);
288        status = mCameraUser.waitUntilIdle();
289        assertEquals(CameraBinderTestUtils.NO_ERROR, status);
290    }
291
292    @SmallTest
293    public void testCaptureResultCallbacks() throws Exception {
294        IsMetadataNotEmpty matcher = new IsMetadataNotEmpty();
295        CaptureRequest request = createDefaultBuilder(/* needStream */true).build();
296
297        // Test both single request and streaming request.
298        int requestId1 = submitCameraRequest(request, /* streaming */false);
299        verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).times(1)).onResultReceived(
300                eq(requestId1),
301                argThat(matcher));
302
303        int streamingId = submitCameraRequest(request, /* streaming */true);
304        verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).atLeast(NUM_CALLBACKS_CHECKED))
305                .onResultReceived(
306                        eq(streamingId),
307                        argThat(matcher));
308    }
309
310    @SmallTest
311    public void testFlush() throws Exception {
312        int status;
313
314        // Initial flush should work
315        status = mCameraUser.flush();
316        assertEquals(CameraBinderTestUtils.NO_ERROR, status);
317
318        // Then set up a stream
319        CaptureRequest request = createDefaultBuilder(/* needStream */true).build();
320
321        // Flush should still be a no-op, really
322        status = mCameraUser.flush();
323        assertEquals(CameraBinderTestUtils.NO_ERROR, status);
324
325        // Submit a few capture requests
326        int requestId1 = submitCameraRequest(request, /* streaming */false);
327        int requestId2 = submitCameraRequest(request, /* streaming */false);
328        int requestId3 = submitCameraRequest(request, /* streaming */false);
329        int requestId4 = submitCameraRequest(request, /* streaming */false);
330        int requestId5 = submitCameraRequest(request, /* streaming */false);
331
332        // Then flush
333        status = mCameraUser.flush();
334        assertEquals(CameraBinderTestUtils.NO_ERROR, status);
335
336        // TODO: When errors are hooked up, count that errors + successful
337        // requests equal to 5.
338    }
339}
340