ProCameraTests.cpp revision 69e22433b9d7df77907579f67e47a159aa57f876
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
17#include <gtest/gtest.h>
18#include <iostream>
19
20#include <binder/IPCThreadState.h>
21#include <utils/Thread.h>
22
23#include "Camera.h"
24#include "ProCamera.h"
25#include <utils/Vector.h>
26#include <utils/Mutex.h>
27#include <utils/Condition.h>
28
29#include <gui/SurfaceComposerClient.h>
30#include <gui/Surface.h>
31
32#include <system/camera_metadata.h>
33#include <hardware/camera2.h> // for CAMERA2_TEMPLATE_PREVIEW only
34
35namespace android {
36namespace camera2 {
37namespace tests {
38namespace client {
39
40#define CAMERA_ID 0
41#define TEST_DEBUGGING 0
42
43#define TEST_LISTENER_TIMEOUT 1000000000 // 1 second listener timeout
44#define TEST_FORMAT HAL_PIXEL_FORMAT_RGBA_8888 //TODO: YUY2 instead
45
46#if TEST_DEBUGGING
47#define dout std::cerr
48#else
49#define dout if (0) std::cerr
50#endif
51
52#define EXPECT_OK(x) EXPECT_EQ(OK, (x))
53#define ASSERT_OK(x) ASSERT_EQ(OK, (x))
54
55class ProCameraTest;
56
57enum LockEvent {
58    UNKNOWN,
59    ACQUIRED,
60    RELEASED,
61    STOLEN
62};
63
64typedef Vector<LockEvent> EventList;
65
66class ProCameraTestThread : public Thread
67{
68public:
69    ProCameraTestThread() {
70    }
71
72    virtual bool threadLoop() {
73        mProc = ProcessState::self();
74        mProc->startThreadPool();
75
76        IPCThreadState *ptr = IPCThreadState::self();
77
78        ptr->joinThreadPool();
79
80        return false;
81    }
82
83    sp<ProcessState> mProc;
84};
85
86class ProCameraTestListener : public ProCameraListener {
87
88public:
89    status_t WaitForEvent() {
90        Mutex::Autolock cal(mConditionMutex);
91
92        {
93            Mutex::Autolock al(mListenerMutex);
94
95            if (mLockEventList.size() > 0) {
96                return OK;
97            }
98        }
99
100        return mListenerCondition.waitRelative(mConditionMutex,
101                                               TEST_LISTENER_TIMEOUT);
102    }
103
104    /* Read events into out. Existing queue is flushed */
105    void ReadEvents(EventList& out) {
106        Mutex::Autolock al(mListenerMutex);
107
108        for (size_t i = 0; i < mLockEventList.size(); ++i) {
109            out.push(mLockEventList[i]);
110        }
111
112        mLockEventList.clear();
113    }
114
115    /**
116      * Dequeue 1 event from the event queue.
117      * Returns UNKNOWN if queue is empty
118      */
119    LockEvent ReadEvent() {
120        Mutex::Autolock al(mListenerMutex);
121
122        if (mLockEventList.size() == 0) {
123            return UNKNOWN;
124        }
125
126        LockEvent ev = mLockEventList[0];
127        mLockEventList.removeAt(0);
128
129        return ev;
130    }
131
132private:
133    void QueueEvent(LockEvent ev) {
134        {
135            Mutex::Autolock al(mListenerMutex);
136            mLockEventList.push(ev);
137        }
138
139
140        mListenerCondition.broadcast();
141    }
142
143protected:
144
145    //////////////////////////////////////////////////
146    ///////// ProCameraListener //////////////////////
147    //////////////////////////////////////////////////
148
149
150    // Lock has been acquired. Write operations now available.
151    virtual void onLockAcquired() {
152        QueueEvent(ACQUIRED);
153    }
154    // Lock has been released with exclusiveUnlock
155    virtual void onLockReleased() {
156        QueueEvent(RELEASED);
157    }
158
159    // Lock has been stolen by another client.
160    virtual void onLockStolen() {
161        QueueEvent(STOLEN);
162    }
163
164    // Lock free.
165    virtual void onTriggerNotify(int32_t ext1, int32_t ext2, int32_t ext3) {
166
167        dout << "Trigger notify: " << ext1 << " " << ext2
168             << " " << ext3 << std::endl;
169    }
170
171    // TODO: remove
172
173    virtual void notify(int32_t , int32_t , int32_t ) {}
174    virtual void postData(int32_t , const sp<IMemory>& ,
175                          camera_frame_metadata_t *) {}
176    virtual void postDataTimestamp(nsecs_t , int32_t , const sp<IMemory>& ) {}
177
178
179    Vector<LockEvent> mLockEventList;
180    Mutex             mListenerMutex;
181    Mutex             mConditionMutex;
182    Condition         mListenerCondition;
183};
184
185class ProCameraTest : public ::testing::Test {
186
187public:
188    ProCameraTest() {
189    }
190
191    static void SetUpTestCase() {
192        // Binder Thread Pool Initialization
193        mTestThread = new ProCameraTestThread();
194        mTestThread->run("ProCameraTestThread");
195    }
196
197    virtual void SetUp() {
198        mCamera = ProCamera::connect(CAMERA_ID);
199        ASSERT_NE((void*)NULL, mCamera.get());
200
201        mListener = new ProCameraTestListener();
202        mCamera->setListener(mListener);
203    }
204
205    virtual void TearDown() {
206        ASSERT_NE((void*)NULL, mCamera.get());
207        mCamera->disconnect();
208    }
209
210protected:
211    sp<ProCamera> mCamera;
212    sp<ProCameraTestListener> mListener;
213
214    static sp<Thread> mTestThread;
215
216    int mDisplaySecs;
217    sp<SurfaceComposerClient> mComposerClient;
218    sp<SurfaceControl> mSurfaceControl;
219
220    int getSurfaceWidth() {
221        return 512;
222    }
223    int getSurfaceHeight() {
224        return 512;
225    }
226
227    void createOnScreenSurface(sp<Surface>& surface) {
228        mComposerClient = new SurfaceComposerClient;
229        ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
230
231        mSurfaceControl = mComposerClient->createSurface(
232                String8("ProCameraTest StreamingImage Surface"),
233                getSurfaceWidth(), getSurfaceHeight(),
234                PIXEL_FORMAT_RGB_888, 0);
235
236        ASSERT_TRUE(mSurfaceControl != NULL);
237        ASSERT_TRUE(mSurfaceControl->isValid());
238
239        SurfaceComposerClient::openGlobalTransaction();
240        ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7FFFFFFF));
241        ASSERT_EQ(NO_ERROR, mSurfaceControl->show());
242        SurfaceComposerClient::closeGlobalTransaction();
243
244        sp<ANativeWindow> window = mSurfaceControl->getSurface();
245        surface = mSurfaceControl->getSurface();
246
247        ASSERT_NE((void*)NULL, surface.get());
248    }
249
250};
251
252sp<Thread> ProCameraTest::mTestThread;
253
254// test around exclusiveTryLock (immediate locking)
255TEST_F(ProCameraTest, LockingImmediate) {
256
257    if (HasFatalFailure()) {
258        return;
259    }
260
261    EXPECT_FALSE(mCamera->hasExclusiveLock());
262    EXPECT_EQ(OK, mCamera->exclusiveTryLock());
263    // at this point we definitely have the lock
264
265    EXPECT_EQ(OK, mListener->WaitForEvent());
266    EXPECT_EQ(ACQUIRED, mListener->ReadEvent());
267
268    EXPECT_TRUE(mCamera->hasExclusiveLock());
269    EXPECT_EQ(OK, mCamera->exclusiveUnlock());
270
271    EXPECT_EQ(OK, mListener->WaitForEvent());
272    EXPECT_EQ(RELEASED, mListener->ReadEvent());
273
274    EXPECT_FALSE(mCamera->hasExclusiveLock());
275}
276
277// test around exclusiveLock (locking at some future point in time)
278TEST_F(ProCameraTest, LockingAsynchronous) {
279
280    if (HasFatalFailure()) {
281        return;
282    }
283
284    // TODO: Add another procamera that has a lock here.
285    // then we can be test that the lock wont immediately be acquired
286
287    EXPECT_FALSE(mCamera->hasExclusiveLock());
288    EXPECT_EQ(OK, mCamera->exclusiveLock());
289    // at this point we may or may not have the lock
290    // we cant be sure until we get an ACQUIRED event
291
292    EXPECT_EQ(OK, mListener->WaitForEvent());
293    EXPECT_EQ(ACQUIRED, mListener->ReadEvent());
294
295    EXPECT_TRUE(mCamera->hasExclusiveLock());
296    EXPECT_EQ(OK, mCamera->exclusiveUnlock());
297
298    EXPECT_EQ(OK, mListener->WaitForEvent());
299    EXPECT_EQ(RELEASED, mListener->ReadEvent());
300
301    EXPECT_FALSE(mCamera->hasExclusiveLock());
302}
303
304// Stream directly to the screen.
305TEST_F(ProCameraTest, StreamingImage) {
306    if (HasFatalFailure()) {
307        return;
308    }
309    char* displaySecsEnv = getenv("TEST_DISPLAY_SECS");
310    if (displaySecsEnv != NULL) {
311        mDisplaySecs = atoi(displaySecsEnv);
312        if (mDisplaySecs < 0) {
313            mDisplaySecs = 0;
314        }
315    } else {
316        mDisplaySecs = 0;
317    }
318
319    sp<Surface> surface;
320    if (mDisplaySecs > 0) {
321        createOnScreenSurface(/*out*/surface);
322    }
323    int streamId = -1;
324    EXPECT_OK(mCamera->createStream(/*width*/640, /*height*/480, TEST_FORMAT,
325              surface, &streamId));
326    EXPECT_NE(-1, streamId);
327
328    EXPECT_OK(mCamera->exclusiveTryLock());
329    /* iterate in a loop submitting requests every frame.
330     *  what kind of requests doesnt really matter, just whatever.
331     */
332
333    // it would probably be better to use CameraMetadata from camera service.
334    camera_metadata_t *request = NULL;
335    EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
336              /*out*/&request));
337    EXPECT_NE((void*)NULL, request);
338
339    /* FIXME: dont need this later, at which point the above should become an
340       ASSERT_NE*/
341    if(request == NULL) request = allocate_camera_metadata(10, 100);
342
343    // set the output streams to just this stream ID
344
345    // wow what a verbose API.
346    // i would give a loaf of bread for
347    //   metadata->updateOrInsert(keys.request.output.streams, streamId);
348    camera_metadata_entry_t entry;
349    uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS);
350    int find = find_camera_metadata_entry(request, tag, &entry);
351    if (find == -ENOENT) {
352        if (add_camera_metadata_entry(request, tag, &streamId, /*data_count*/1)
353                != OK) {
354            camera_metadata_t *tmp = allocate_camera_metadata(1000, 10000);
355            ASSERT_OK(append_camera_metadata(tmp, request));
356            free_camera_metadata(request);
357            request = tmp;
358
359            ASSERT_OK(add_camera_metadata_entry(request, tag, &streamId,
360                /*data_count*/1));
361        }
362    } else {
363        ASSERT_OK(update_camera_metadata_entry(request, entry.index, &streamId,
364                  /*data_count*/1, &entry));
365    }
366
367    EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true));
368
369    dout << "will sleep now for " << mDisplaySecs << std::endl;
370    sleep(mDisplaySecs);
371
372    free_camera_metadata(request);
373    EXPECT_OK(mCamera->cancelStream(streamId));
374    EXPECT_OK(mCamera->exclusiveUnlock());
375}
376
377}
378}
379}
380}
381
382