CameraBinderTests.cpp revision 3450ba7879be6522ea46a56c5e66e5382f5dd5ba
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
17#define LOG_NDEBUG 0
18#define LOG_TAG "CameraBinderTests"
19
20#include <binder/IInterface.h>
21#include <binder/IServiceManager.h>
22#include <binder/Parcel.h>
23#include <binder/ProcessState.h>
24#include <utils/Errors.h>
25#include <utils/Log.h>
26#include <utils/List.h>
27#include <utils/String8.h>
28#include <utils/String16.h>
29#include <utils/Condition.h>
30#include <utils/Mutex.h>
31#include <system/graphics.h>
32#include <hardware/gralloc.h>
33
34#include <camera/CameraMetadata.h>
35#include <camera/ICameraService.h>
36#include <camera/ICameraServiceListener.h>
37#include <camera/camera2/CaptureRequest.h>
38#include <camera/camera2/ICameraDeviceUser.h>
39#include <camera/camera2/ICameraDeviceCallbacks.h>
40#include <camera/camera2/OutputConfiguration.h>
41
42#include <gui/BufferItemConsumer.h>
43#include <gui/IGraphicBufferProducer.h>
44#include <gui/Surface.h>
45
46#include <gtest/gtest.h>
47#include <unistd.h>
48#include <stdint.h>
49#include <utility>
50#include <vector>
51#include <map>
52#include <algorithm>
53
54using namespace android;
55
56#define ASSERT_NOT_NULL(x) \
57    ASSERT_TRUE((x) != nullptr)
58
59#define SETUP_TIMEOUT 2000000000 // ns
60#define IDLE_TIMEOUT 2000000000 // ns
61
62// Stub listener implementation
63class TestCameraServiceListener : public BnCameraServiceListener {
64    std::map<String16, TorchStatus> mCameraTorchStatuses;
65    std::map<int32_t, Status> mCameraStatuses;
66    mutable Mutex mLock;
67    mutable Condition mCondition;
68    mutable Condition mTorchCondition;
69public:
70    virtual ~TestCameraServiceListener() {};
71
72    virtual void onStatusChanged(Status status, int32_t cameraId) {
73        Mutex::Autolock l(mLock);
74        mCameraStatuses[cameraId] = status;
75        mCondition.broadcast();
76    };
77
78    virtual void onTorchStatusChanged(TorchStatus status, const String16& cameraId) {
79        Mutex::Autolock l(mLock);
80        mCameraTorchStatuses[cameraId] = status;
81        mTorchCondition.broadcast();
82    };
83
84    bool waitForNumCameras(size_t num) const {
85        Mutex::Autolock l(mLock);
86
87        if (mCameraStatuses.size() == num) {
88            return true;
89        }
90
91        while (mCameraStatuses.size() < num) {
92            if (mCondition.waitRelative(mLock, SETUP_TIMEOUT) != OK) {
93                return false;
94            }
95        }
96        return true;
97    };
98
99    bool waitForTorchState(TorchStatus status, int32_t cameraId) const {
100        Mutex::Autolock l(mLock);
101
102        const auto& iter = mCameraTorchStatuses.find(String16(String8::format("%d", cameraId)));
103        if (iter != mCameraTorchStatuses.end() && iter->second == status) {
104            return true;
105        }
106
107        bool foundStatus = false;
108        while (!foundStatus) {
109            if (mTorchCondition.waitRelative(mLock, SETUP_TIMEOUT) != OK) {
110                return false;
111            }
112            const auto& iter =
113                    mCameraTorchStatuses.find(String16(String8::format("%d", cameraId)));
114            foundStatus = (iter != mCameraTorchStatuses.end() && iter->second == status);
115        }
116        return true;
117    };
118
119    TorchStatus getTorchStatus(int32_t cameraId) const {
120        Mutex::Autolock l(mLock);
121        const auto& iter = mCameraTorchStatuses.find(String16(String8::format("%d", cameraId)));
122        if (iter == mCameraTorchStatuses.end()) {
123            return ICameraServiceListener::TORCH_STATUS_UNKNOWN;
124        }
125        return iter->second;
126    };
127
128    Status getStatus(int32_t cameraId) const {
129        Mutex::Autolock l(mLock);
130        const auto& iter = mCameraStatuses.find(cameraId);
131        if (iter == mCameraStatuses.end()) {
132            return ICameraServiceListener::STATUS_UNKNOWN;
133        }
134        return iter->second;
135    };
136};
137
138// Callback implementation
139class TestCameraDeviceCallbacks : public BnCameraDeviceCallbacks {
140public:
141    enum Status {
142        IDLE,
143        ERROR,
144        PREPARED,
145        RUNNING,
146        SENT_RESULT,
147        UNINITIALIZED
148    };
149
150protected:
151    bool mError;
152    Status mLastStatus;
153    mutable std::vector<Status> mStatusesHit;
154    mutable Mutex mLock;
155    mutable Condition mStatusCondition;
156public:
157    TestCameraDeviceCallbacks() : mError(false), mLastStatus(UNINITIALIZED) {}
158
159    virtual ~TestCameraDeviceCallbacks() {}
160
161    virtual void onDeviceError(CameraErrorCode errorCode,
162            const CaptureResultExtras& resultExtras) {
163        ALOGE("%s: onDeviceError occurred with: %d", __FUNCTION__, static_cast<int>(errorCode));
164        Mutex::Autolock l(mLock);
165        mError = true;
166        mLastStatus = ERROR;
167        mStatusesHit.push_back(mLastStatus);
168        mStatusCondition.broadcast();
169    }
170
171    virtual void onDeviceIdle() {
172        Mutex::Autolock l(mLock);
173        mLastStatus = IDLE;
174        mStatusesHit.push_back(mLastStatus);
175        mStatusCondition.broadcast();
176    }
177
178    virtual void onCaptureStarted(const CaptureResultExtras& resultExtras,
179            int64_t timestamp) {
180        Mutex::Autolock l(mLock);
181        mLastStatus = RUNNING;
182        mStatusesHit.push_back(mLastStatus);
183        mStatusCondition.broadcast();
184    }
185
186
187    virtual void onResultReceived(const CameraMetadata& metadata,
188            const CaptureResultExtras& resultExtras) {
189        Mutex::Autolock l(mLock);
190        mLastStatus = SENT_RESULT;
191        mStatusesHit.push_back(mLastStatus);
192        mStatusCondition.broadcast();
193    }
194
195    virtual void onPrepared(int streamId) {
196        Mutex::Autolock l(mLock);
197        mLastStatus = PREPARED;
198        mStatusesHit.push_back(mLastStatus);
199        mStatusCondition.broadcast();
200    }
201
202    // Test helper functions:
203
204    bool hadError() const {
205        Mutex::Autolock l(mLock);
206        return mError;
207    }
208
209    bool waitForStatus(Status status) const {
210        Mutex::Autolock l(mLock);
211        if (mLastStatus == status) {
212            return true;
213        }
214
215        while (std::find(mStatusesHit.begin(), mStatusesHit.end(), status)
216                == mStatusesHit.end()) {
217
218            if (mStatusCondition.waitRelative(mLock, IDLE_TIMEOUT) != OK) {
219                mStatusesHit.clear();
220                return false;
221            }
222        }
223        mStatusesHit.clear();
224
225        return true;
226
227    }
228
229    void clearStatus() const {
230        Mutex::Autolock l(mLock);
231        mStatusesHit.clear();
232    }
233
234    bool waitForIdle() const {
235        return waitForStatus(IDLE);
236    }
237
238};
239
240// Exercise basic binder calls for the camera service
241TEST(CameraServiceBinderTest, CheckBinderCameraService) {
242    ProcessState::self()->startThreadPool();
243    sp<IServiceManager> sm = defaultServiceManager();
244    sp<IBinder> binder = sm->getService(String16("media.camera"));
245    ASSERT_NOT_NULL(binder);
246    sp<ICameraService> service = interface_cast<ICameraService>(binder);
247
248
249    int32_t numCameras = service->getNumberOfCameras();
250    EXPECT_LE(0, numCameras);
251
252    // Check listener binder calls
253    sp<TestCameraServiceListener> listener(new TestCameraServiceListener());
254    EXPECT_EQ(OK, service->addListener(listener));
255
256    EXPECT_TRUE(listener->waitForNumCameras(numCameras));
257
258    for (int32_t i = 0; i < numCameras; i++) {
259        // We only care about binder calls for the Camera2 API.  Camera1 is deprecated.
260        status_t camera2Support = service->supportsCameraApi(i, ICameraService::API_VERSION_2);
261        if (camera2Support != OK) {
262            EXPECT_EQ(-EOPNOTSUPP, camera2Support);
263            continue;
264        }
265
266        // Check metadata binder call
267        CameraMetadata metadata;
268        EXPECT_EQ(OK, service->getCameraCharacteristics(i, &metadata));
269        EXPECT_FALSE(metadata.isEmpty());
270
271        // Make sure we're available, or skip device tests otherwise
272        ICameraServiceListener::Status s = listener->getStatus(i);
273        EXPECT_EQ(ICameraServiceListener::STATUS_AVAILABLE, s);
274        if (s != ICameraServiceListener::STATUS_AVAILABLE) {
275            continue;
276        }
277
278        // Check connect binder calls
279        sp<TestCameraDeviceCallbacks> callbacks(new TestCameraDeviceCallbacks());
280        sp<ICameraDeviceUser> device;
281        EXPECT_EQ(OK, service->connectDevice(callbacks, i, String16("meeeeeeeee!"),
282                ICameraService::USE_CALLING_UID, /*out*/device));
283        ASSERT_NE(nullptr, device.get());
284        device->disconnect();
285        EXPECT_FALSE(callbacks->hadError());
286
287        ICameraServiceListener::TorchStatus torchStatus = listener->getTorchStatus(i);
288        if (torchStatus == ICameraServiceListener::TORCH_STATUS_AVAILABLE_OFF) {
289            // Check torch calls
290            EXPECT_EQ(OK, service->setTorchMode(String16(String8::format("%d", i)),
291                    /*enabled*/true, callbacks));
292            EXPECT_TRUE(listener->waitForTorchState(
293                    ICameraServiceListener::TORCH_STATUS_AVAILABLE_ON, i));
294            EXPECT_EQ(OK, service->setTorchMode(String16(String8::format("%d", i)),
295                    /*enabled*/false, callbacks));
296            EXPECT_TRUE(listener->waitForTorchState(
297                    ICameraServiceListener::TORCH_STATUS_AVAILABLE_OFF, i));
298        }
299    }
300
301    EXPECT_EQ(OK, service->removeListener(listener));
302}
303
304// Test fixture for client focused binder tests
305class CameraClientBinderTest : public testing::Test {
306protected:
307    sp<ICameraService> service;
308    int32_t numCameras;
309    std::vector<std::pair<sp<TestCameraDeviceCallbacks>, sp<ICameraDeviceUser>>> openDeviceList;
310    sp<TestCameraServiceListener> serviceListener;
311
312    std::pair<sp<TestCameraDeviceCallbacks>, sp<ICameraDeviceUser>> openNewDevice(int deviceId) {
313
314        sp<TestCameraDeviceCallbacks> callbacks(new TestCameraDeviceCallbacks());
315        sp<ICameraDeviceUser> device;
316        {
317            SCOPED_TRACE("openNewDevice");
318            EXPECT_EQ(OK, service->connectDevice(callbacks, deviceId, String16("meeeeeeeee!"),
319                    ICameraService::USE_CALLING_UID, /*out*/device));
320        }
321        auto p = std::make_pair(callbacks, device);
322        openDeviceList.push_back(p);
323        return p;
324    }
325
326    void closeDevice(std::pair<sp<TestCameraDeviceCallbacks>, sp<ICameraDeviceUser>>& p) {
327        if (p.second.get() != nullptr) {
328            p.second->disconnect();
329            {
330                SCOPED_TRACE("closeDevice");
331                EXPECT_FALSE(p.first->hadError());
332            }
333        }
334        auto iter = std::find(openDeviceList.begin(), openDeviceList.end(), p);
335        if (iter != openDeviceList.end()) {
336            openDeviceList.erase(iter);
337        }
338    }
339
340    virtual void SetUp() {
341        ProcessState::self()->startThreadPool();
342        sp<IServiceManager> sm = defaultServiceManager();
343        sp<IBinder> binder = sm->getService(String16("media.camera"));
344        service = interface_cast<ICameraService>(binder);
345        serviceListener = new TestCameraServiceListener();
346        service->addListener(serviceListener);
347        numCameras = service->getNumberOfCameras();
348    }
349
350    virtual void TearDown() {
351        service = nullptr;
352        numCameras = 0;
353        for (auto& p : openDeviceList) {
354            closeDevice(p);
355        }
356    }
357
358};
359
360TEST_F(CameraClientBinderTest, CheckBinderCameraDeviceUser) {
361    ASSERT_NOT_NULL(service);
362
363    EXPECT_TRUE(serviceListener->waitForNumCameras(numCameras));
364    for (int32_t i = 0; i < numCameras; i++) {
365        // Make sure we're available, or skip device tests otherwise
366        ICameraServiceListener::Status s = serviceListener->getStatus(i);
367        EXPECT_EQ(ICameraServiceListener::STATUS_AVAILABLE, s);
368        if (s != ICameraServiceListener::STATUS_AVAILABLE) {
369            continue;
370        }
371
372        auto p = openNewDevice(i);
373        sp<TestCameraDeviceCallbacks> callbacks = p.first;
374        sp<ICameraDeviceUser> device = p.second;
375
376        // Setup a buffer queue; I'm just using the vendor opaque format here as that is
377        // guaranteed to be present
378        sp<IGraphicBufferProducer> gbProducer;
379        sp<IGraphicBufferConsumer> gbConsumer;
380        BufferQueue::createBufferQueue(&gbProducer, &gbConsumer);
381        sp<BufferItemConsumer> opaqueConsumer = new BufferItemConsumer(gbConsumer,
382                GRALLOC_USAGE_SW_READ_NEVER, /*maxImages*/2, /*controlledByApp*/true);
383        EXPECT_TRUE(opaqueConsumer.get() != nullptr);
384        opaqueConsumer->setName(String8("nom nom nom"));
385
386        // Set to VGA dimens for default, as that is guaranteed to be present
387        EXPECT_EQ(OK, gbConsumer->setDefaultBufferSize(640, 480));
388        EXPECT_EQ(OK, gbConsumer->setDefaultBufferFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED));
389
390        sp<Surface> surface(new Surface(gbProducer, /*controlledByApp*/false));
391
392        OutputConfiguration output(gbProducer, /*rotation*/0);
393
394        // Can we configure?
395        EXPECT_EQ(OK, device->beginConfigure());
396        status_t streamId = device->createStream(output);
397        EXPECT_LE(0, streamId);
398        EXPECT_EQ(OK, device->endConfigure());
399        EXPECT_FALSE(callbacks->hadError());
400
401        // Can we make requests?
402        CameraMetadata requestTemplate;
403        EXPECT_EQ(OK, device->createDefaultRequest(/*preview template*/1,
404                /*out*/&requestTemplate));
405        sp<CaptureRequest> request(new CaptureRequest());
406        request->mMetadata = requestTemplate;
407        request->mSurfaceList.add(surface);
408        request->mIsReprocess = false;
409        int64_t lastFrameNumber = 0;
410        int64_t lastFrameNumberPrev = 0;
411        callbacks->clearStatus();
412        int requestId = device->submitRequest(request, /*streaming*/true, /*out*/&lastFrameNumber);
413        EXPECT_TRUE(callbacks->waitForStatus(TestCameraDeviceCallbacks::SENT_RESULT));
414        EXPECT_LE(0, requestId);
415
416        // Can we stop requests?
417        EXPECT_EQ(OK, device->cancelRequest(requestId, /*out*/&lastFrameNumber));
418        EXPECT_TRUE(callbacks->waitForIdle());
419        EXPECT_FALSE(callbacks->hadError());
420
421        // Can we do it again?
422        lastFrameNumberPrev = lastFrameNumber;
423        lastFrameNumber = 0;
424        requestTemplate.clear();
425        EXPECT_EQ(OK, device->createDefaultRequest(/*preview template*/1,
426                /*out*/&requestTemplate));
427        sp<CaptureRequest> request2(new CaptureRequest());
428        request2->mMetadata = requestTemplate;
429        request2->mSurfaceList.add(surface);
430        request2->mIsReprocess = false;
431        callbacks->clearStatus();
432        int requestId2 = device->submitRequest(request2, /*streaming*/true,
433                /*out*/&lastFrameNumber);
434        EXPECT_EQ(-1, lastFrameNumber);
435        lastFrameNumber = 0;
436        EXPECT_TRUE(callbacks->waitForStatus(TestCameraDeviceCallbacks::SENT_RESULT));
437        EXPECT_LE(0, requestId2);
438        EXPECT_EQ(OK, device->cancelRequest(requestId2, /*out*/&lastFrameNumber));
439        EXPECT_TRUE(callbacks->waitForIdle());
440        EXPECT_LE(lastFrameNumberPrev, lastFrameNumber);
441        sleep(/*second*/1); // allow some time for errors to show up, if any
442        EXPECT_FALSE(callbacks->hadError());
443
444        // Can we do it with a request list?
445        lastFrameNumberPrev = lastFrameNumber;
446        lastFrameNumber = 0;
447        requestTemplate.clear();
448        CameraMetadata requestTemplate2;
449        EXPECT_EQ(OK, device->createDefaultRequest(/*preview template*/1,
450                /*out*/&requestTemplate));
451        EXPECT_EQ(OK, device->createDefaultRequest(/*preview template*/1,
452                /*out*/&requestTemplate2));
453        sp<CaptureRequest> request3(new CaptureRequest());
454        sp<CaptureRequest> request4(new CaptureRequest());
455        request3->mMetadata = requestTemplate;
456        request3->mSurfaceList.add(surface);
457        request3->mIsReprocess = false;
458        request4->mMetadata = requestTemplate2;
459        request4->mSurfaceList.add(surface);
460        request4->mIsReprocess = false;
461        List<sp<CaptureRequest>> requestList;
462        requestList.push_back(request3);
463        requestList.push_back(request4);
464
465        callbacks->clearStatus();
466        int requestId3 = device->submitRequestList(requestList, /*streaming*/false,
467                /*out*/&lastFrameNumber);
468        EXPECT_TRUE(callbacks->waitForStatus(TestCameraDeviceCallbacks::SENT_RESULT));
469        EXPECT_TRUE(callbacks->waitForIdle());
470        EXPECT_LE(lastFrameNumberPrev, lastFrameNumber);
471        sleep(/*second*/1); // allow some time for errors to show up, if any
472        EXPECT_FALSE(callbacks->hadError());
473
474        // Can we unconfigure?
475        EXPECT_EQ(OK, device->beginConfigure());
476        EXPECT_EQ(OK, device->deleteStream(streamId));
477        EXPECT_EQ(OK, device->endConfigure());
478        sleep(/*second*/1); // allow some time for errors to show up, if any
479        EXPECT_FALSE(callbacks->hadError());
480
481        closeDevice(p);
482    }
483
484};
485