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