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.hardware.CameraInfo;
20import android.hardware.ICamera;
21import android.hardware.ICameraClient;
22import android.hardware.ICameraServiceListener;
23import android.hardware.IProCameraCallbacks;
24import android.hardware.IProCameraUser;
25import android.hardware.camera2.ICameraDeviceCallbacks;
26import android.hardware.camera2.ICameraDeviceUser;
27import android.hardware.camera2.impl.CameraMetadataNative;
28import android.hardware.camera2.impl.CaptureResultExtras;
29import android.hardware.camera2.utils.BinderHolder;
30import android.hardware.camera2.utils.CameraBinderDecorator;
31import android.os.Binder;
32import android.os.IBinder;
33import android.os.RemoteException;
34import android.test.AndroidTestCase;
35import android.test.suitebuilder.annotation.SmallTest;
36import android.util.Log;
37
38/**
39 * <p>
40 * Junit / Instrumentation test case for the camera2 api
41 * </p>
42 * <p>
43 * To run only tests in this class:
44 * </p>
45 *
46 * <pre>
47 * adb shell am instrument \
48 *   -e class com.android.mediaframeworktest.integration.CameraBinderTest \
49 *   -w com.android.mediaframeworktest/.MediaFrameworkIntegrationTestRunner
50 * </pre>
51 */
52public class CameraBinderTest extends AndroidTestCase {
53    private static final int MAX_PARAMETERS_LENGTH = 100;
54
55    static String TAG = "CameraBinderTest";
56
57    // From ICameraService.h
58    private static final int API_VERSION_1 = 1;
59    private static final int API_VERSION_2 = 2;
60
61    protected CameraBinderTestUtils mUtils;
62
63    public CameraBinderTest() {
64    }
65
66    @Override
67    protected void setUp() throws Exception {
68        super.setUp();
69
70        mUtils = new CameraBinderTestUtils(getContext());
71    }
72
73    @SmallTest
74    public void testNumberOfCameras() throws Exception {
75
76        int numCameras = mUtils.getCameraService().getNumberOfCameras();
77        assertTrue("At least this many cameras: " + mUtils.getGuessedNumCameras(),
78                numCameras >= mUtils.getGuessedNumCameras());
79        Log.v(TAG, "Number of cameras " + numCameras);
80    }
81
82    @SmallTest
83    public void testCameraInfo() throws Exception {
84        for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
85
86            CameraInfo info = new CameraInfo();
87            info.info.facing = -1;
88            info.info.orientation = -1;
89
90            assertTrue(
91                    "Camera service returned info for camera " + cameraId,
92                    mUtils.getCameraService().getCameraInfo(cameraId, info) ==
93                    CameraBinderTestUtils.NO_ERROR);
94            assertTrue("Facing was not set for camera " + cameraId, info.info.facing != -1);
95            assertTrue("Orientation was not set for camera " + cameraId,
96                    info.info.orientation != -1);
97
98            Log.v(TAG, "Camera " + cameraId + " info: facing " + info.info.facing
99                    + ", orientation " + info.info.orientation);
100        }
101    }
102
103    @SmallTest
104    public void testGetLegacyParameters() throws Exception {
105        for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
106
107            String[] parameters = new String[1];
108            assertEquals("Camera service returned parameters for camera " + cameraId,
109                    CameraBinderTestUtils.NO_ERROR,
110                    mUtils.getCameraService().getLegacyParameters(cameraId, /*out*/parameters));
111            assertNotNull(parameters[0]);
112            assertTrue("Parameters should have at least one character in it",
113                    parameters[0].length() > 0);
114
115            int end = parameters[0].length();
116            if (end > MAX_PARAMETERS_LENGTH) {
117                end = MAX_PARAMETERS_LENGTH;
118            }
119
120            Log.v(TAG, "Camera " + cameraId + " parameters: " + parameters[0].substring(0, end));
121        }
122    }
123
124    /** The camera2 api is only supported on HAL3.2+ devices */
125    @SmallTest
126    public void testSupportsCamera2Api() throws Exception {
127        for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
128
129            int res = mUtils.getCameraService().supportsCameraApi(cameraId, API_VERSION_2);
130
131            if (res != CameraBinderTestUtils.NO_ERROR && res != CameraBinderTestUtils.EOPNOTSUPP) {
132                fail("Camera service returned bad value when queried if it supports camera2 api: "
133                        + res + " for camera ID " + cameraId);
134            }
135
136            boolean supports = res == CameraBinderTestUtils.NO_ERROR;
137            Log.v(TAG, "Camera " + cameraId + " supports api2: " + supports);
138        }
139    }
140
141    /** The camera1 api is supported on *all* devices regardless of HAL version */
142    @SmallTest
143    public void testSupportsCamera1Api() throws Exception {
144        for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
145
146            int res = mUtils.getCameraService().supportsCameraApi(cameraId, API_VERSION_1);
147            assertEquals(
148                    "Camera service returned bad value when queried if it supports camera1 api: "
149                    + res + " for camera ID " + cameraId, CameraBinderTestUtils.NO_ERROR, res);
150        }
151    }
152
153    static abstract class DummyBase extends Binder implements android.os.IInterface {
154        @Override
155        public IBinder asBinder() {
156            return this;
157        }
158    }
159
160    static class DummyCameraClient extends DummyBase implements ICameraClient {
161    }
162
163    @SmallTest
164    public void testConnect() throws Exception {
165        for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
166
167            ICameraClient dummyCallbacks = new DummyCameraClient();
168
169            String clientPackageName = getContext().getPackageName();
170
171            BinderHolder holder = new BinderHolder();
172            CameraBinderDecorator.newInstance(mUtils.getCameraService())
173                    .connect(dummyCallbacks, cameraId, clientPackageName,
174                    CameraBinderTestUtils.USE_CALLING_UID, holder);
175            ICamera cameraUser = ICamera.Stub.asInterface(holder.getBinder());
176            assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
177
178            Log.v(TAG, String.format("Camera %s connected", cameraId));
179
180            cameraUser.disconnect();
181        }
182    }
183
184    static class DummyProCameraCallbacks extends DummyBase implements IProCameraCallbacks {
185    }
186
187    @SmallTest
188    public void testConnectPro() throws Exception {
189        for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
190
191            IProCameraCallbacks dummyCallbacks = new DummyProCameraCallbacks();
192
193            String clientPackageName = getContext().getPackageName();
194
195            BinderHolder holder = new BinderHolder();
196            CameraBinderDecorator.newInstance(mUtils.getCameraService())
197                    .connectPro(dummyCallbacks, cameraId,
198                    clientPackageName, CameraBinderTestUtils.USE_CALLING_UID, holder);
199            IProCameraUser cameraUser = IProCameraUser.Stub.asInterface(holder.getBinder());
200            assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
201
202            Log.v(TAG, String.format("Camera %s connected", cameraId));
203
204            cameraUser.disconnect();
205        }
206    }
207
208    @SmallTest
209    public void testConnectLegacy() throws Exception {
210        final int CAMERA_HAL_API_VERSION_1_0 = 0x100;
211        for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
212            ICamera cameraUser = null;
213            ICameraClient dummyCallbacks = new DummyCameraClient();
214
215            String clientPackageName = getContext().getPackageName();
216
217            BinderHolder holder = new BinderHolder();
218
219            try {
220                CameraBinderDecorator.newInstance(mUtils.getCameraService())
221                        .connectLegacy(dummyCallbacks, cameraId, CAMERA_HAL_API_VERSION_1_0,
222                        clientPackageName,
223                        CameraBinderTestUtils.USE_CALLING_UID, holder);
224                cameraUser = ICamera.Stub.asInterface(holder.getBinder());
225                assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
226
227                Log.v(TAG, String.format("Camera %s connected as HAL1 legacy device", cameraId));
228            } catch (RuntimeException e) {
229                // Not all camera device support openLegacy.
230                Log.i(TAG, "Unable to open camera as HAL1 legacy camera device " + e);
231            } finally {
232                if (cameraUser != null) {
233                    cameraUser.disconnect();
234                }
235            }
236        }
237    }
238
239    static class DummyCameraDeviceCallbacks extends ICameraDeviceCallbacks.Stub {
240
241        /*
242         * (non-Javadoc)
243         * @see
244         * android.hardware.camera2.ICameraDeviceCallbacks#onCameraError(int,
245         * android.hardware.camera2.CaptureResultExtras)
246         */
247        @Override
248        public void onDeviceError(int errorCode, CaptureResultExtras resultExtras)
249                throws RemoteException {
250            // TODO Auto-generated method stub
251
252        }
253
254        /*
255         * (non-Javadoc)
256         * @see
257         * android.hardware.camera2.ICameraDeviceCallbacks#onCaptureStarted(
258         * android.hardware.camera2.CaptureResultExtras, long)
259         */
260        @Override
261        public void onCaptureStarted(CaptureResultExtras resultExtras, long timestamp)
262                throws RemoteException {
263            // TODO Auto-generated method stub
264
265        }
266
267        /*
268         * (non-Javadoc)
269         * @see
270         * android.hardware.camera2.ICameraDeviceCallbacks#onResultReceived(
271         * android.hardware.camera2.impl.CameraMetadataNative,
272         * android.hardware.camera2.CaptureResultExtras)
273         */
274        @Override
275        public void onResultReceived(CameraMetadataNative result, CaptureResultExtras resultExtras)
276                throws RemoteException {
277            // TODO Auto-generated method stub
278
279        }
280
281        /*
282         * (non-Javadoc)
283         * @see android.hardware.camera2.ICameraDeviceCallbacks#onCameraIdle()
284         */
285        @Override
286        public void onDeviceIdle() throws RemoteException {
287            // TODO Auto-generated method stub
288
289        }
290    }
291
292    @SmallTest
293    public void testConnectDevice() throws Exception {
294        for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
295
296            ICameraDeviceCallbacks dummyCallbacks = new DummyCameraDeviceCallbacks();
297
298            String clientPackageName = getContext().getPackageName();
299
300            BinderHolder holder = new BinderHolder();
301            CameraBinderDecorator.newInstance(mUtils.getCameraService())
302                    .connectDevice(dummyCallbacks, cameraId,
303                    clientPackageName, CameraBinderTestUtils.USE_CALLING_UID, holder);
304            ICameraDeviceUser cameraUser = ICameraDeviceUser.Stub.asInterface(holder.getBinder());
305            assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
306
307            Log.v(TAG, String.format("Camera %s connected", cameraId));
308
309            cameraUser.disconnect();
310        }
311    }
312
313    static class DummyCameraServiceListener extends ICameraServiceListener.Stub {
314        @Override
315        public void onStatusChanged(int status, int cameraId)
316                throws RemoteException {
317            Log.v(TAG, String.format("Camera %d has status changed to 0x%x", cameraId, status));
318        }
319    }
320
321    /**
322     * <pre>
323     * adb shell am instrument \
324     *   -e class 'com.android.mediaframeworktest.integration.CameraBinderTest#testAddRemoveListeners' \
325     *   -w com.android.mediaframeworktest/.MediaFrameworkIntegrationTestRunner
326     * </pre>
327     */
328    @SmallTest
329    public void testAddRemoveListeners() throws Exception {
330        for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
331
332            ICameraServiceListener listener = new DummyCameraServiceListener();
333
334            assertTrue(
335                    "Listener was removed before added",
336                    mUtils.getCameraService().removeListener(listener) ==
337                    CameraBinderTestUtils.BAD_VALUE);
338
339            assertTrue("Listener was not added",
340                    mUtils.getCameraService().addListener(listener) ==
341                    CameraBinderTestUtils.NO_ERROR);
342            assertTrue(
343                    "Listener was wrongly added again",
344                    mUtils.getCameraService().addListener(listener) ==
345                    CameraBinderTestUtils.ALREADY_EXISTS);
346
347            assertTrue(
348                    "Listener was not removed",
349                    mUtils.getCameraService().removeListener(listener) ==
350                    CameraBinderTestUtils.NO_ERROR);
351            assertTrue(
352                    "Listener was wrongly removed again",
353                    mUtils.getCameraService().removeListener(listener) ==
354                    CameraBinderTestUtils.BAD_VALUE);
355        }
356    }
357}
358