ProCameraTests.cpp revision 5076182ce4bf657e7211264d0ad3861212f24aa1
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_Y16 //TODO: YUY2 instead
45
46#define TEST_FORMAT_MAIN HAL_PIXEL_FORMAT_Y8
47#define TEST_FORMAT_DEPTH HAL_PIXEL_FORMAT_Y16
48
49#define TEST_CPU_FRAME_COUNT 2
50#define TEST_CPU_HEAP_COUNT 5
51
52#if TEST_DEBUGGING
53#define dout std::cerr
54#else
55#define dout if (0) std::cerr
56#endif
57
58#define EXPECT_OK(x) EXPECT_EQ(OK, (x))
59#define ASSERT_OK(x) ASSERT_EQ(OK, (x))
60
61class ProCameraTest;
62
63enum ProEvent {
64    UNKNOWN,
65    ACQUIRED,
66    RELEASED,
67    STOLEN,
68    BUFFER_RECEIVED,
69};
70
71typedef Vector<ProEvent> EventList;
72
73class ProCameraTestThread : public Thread
74{
75public:
76    ProCameraTestThread() {
77    }
78
79    virtual bool threadLoop() {
80        mProc = ProcessState::self();
81        mProc->startThreadPool();
82
83        IPCThreadState *ptr = IPCThreadState::self();
84
85        ptr->joinThreadPool();
86
87        return false;
88    }
89
90    sp<ProcessState> mProc;
91};
92
93class ProCameraTestListener : public ProCameraListener {
94
95public:
96    status_t WaitForEvent() {
97        Mutex::Autolock cal(mConditionMutex);
98
99        {
100            Mutex::Autolock al(mListenerMutex);
101
102            if (mProEventList.size() > 0) {
103                return OK;
104            }
105        }
106
107        return mListenerCondition.waitRelative(mConditionMutex,
108                                               TEST_LISTENER_TIMEOUT);
109    }
110
111    /* Read events into out. Existing queue is flushed */
112    void ReadEvents(EventList& out) {
113        Mutex::Autolock al(mListenerMutex);
114
115        for (size_t i = 0; i < mProEventList.size(); ++i) {
116            out.push(mProEventList[i]);
117        }
118
119        mProEventList.clear();
120    }
121
122    /**
123      * Dequeue 1 event from the event queue.
124      * Returns UNKNOWN if queue is empty
125      */
126    ProEvent ReadEvent() {
127        Mutex::Autolock al(mListenerMutex);
128
129        if (mProEventList.size() == 0) {
130            return UNKNOWN;
131        }
132
133        ProEvent ev = mProEventList[0];
134        mProEventList.removeAt(0);
135
136        return ev;
137    }
138
139private:
140    void QueueEvent(ProEvent ev) {
141        {
142            Mutex::Autolock al(mListenerMutex);
143            mProEventList.push(ev);
144        }
145
146
147        mListenerCondition.broadcast();
148    }
149
150protected:
151
152    //////////////////////////////////////////////////
153    ///////// ProCameraListener //////////////////////
154    //////////////////////////////////////////////////
155
156
157    // Lock has been acquired. Write operations now available.
158    virtual void onLockAcquired() {
159        QueueEvent(ACQUIRED);
160    }
161    // Lock has been released with exclusiveUnlock
162    virtual void onLockReleased() {
163        QueueEvent(RELEASED);
164    }
165
166    // Lock has been stolen by another client.
167    virtual void onLockStolen() {
168        QueueEvent(STOLEN);
169    }
170
171    // Lock free.
172    virtual void onTriggerNotify(int32_t ext1, int32_t ext2, int32_t ext3) {
173
174        dout << "Trigger notify: " << ext1 << " " << ext2
175             << " " << ext3 << std::endl;
176    }
177
178    virtual void onBufferReceived(int streamId,
179                                  const CpuConsumer::LockedBuffer& buf) {
180
181        dout << "Buffer received on streamId = " << streamId <<
182                ", dataPtr = " << (void*)buf.data << std::endl;
183
184        QueueEvent(BUFFER_RECEIVED);
185
186    }
187    virtual void onRequestReceived(
188                                   camera_metadata* request) {
189        free_camera_metadata(request);
190    }
191
192    // TODO: remove
193
194    virtual void notify(int32_t , int32_t , int32_t ) {}
195    virtual void postData(int32_t , const sp<IMemory>& ,
196                          camera_frame_metadata_t *) {}
197    virtual void postDataTimestamp(nsecs_t , int32_t , const sp<IMemory>& ) {}
198
199
200    Vector<ProEvent> mProEventList;
201    Mutex             mListenerMutex;
202    Mutex             mConditionMutex;
203    Condition         mListenerCondition;
204};
205
206class ProCameraTest : public ::testing::Test {
207
208public:
209    ProCameraTest() {
210    }
211
212    static void SetUpTestCase() {
213        // Binder Thread Pool Initialization
214        mTestThread = new ProCameraTestThread();
215        mTestThread->run("ProCameraTestThread");
216    }
217
218    virtual void SetUp() {
219        mCamera = ProCamera::connect(CAMERA_ID);
220        ASSERT_NE((void*)NULL, mCamera.get());
221
222        mListener = new ProCameraTestListener();
223        mCamera->setListener(mListener);
224    }
225
226    virtual void TearDown() {
227        ASSERT_NE((void*)NULL, mCamera.get());
228        mCamera->disconnect();
229    }
230
231protected:
232    sp<ProCamera> mCamera;
233    sp<ProCameraTestListener> mListener;
234
235    static sp<Thread> mTestThread;
236
237    int mDisplaySecs;
238    sp<SurfaceComposerClient> mComposerClient;
239    sp<SurfaceControl> mSurfaceControl;
240
241    sp<SurfaceComposerClient> mDepthComposerClient;
242    sp<SurfaceControl> mDepthSurfaceControl;
243
244    int getSurfaceWidth() {
245        return 512;
246    }
247    int getSurfaceHeight() {
248        return 512;
249    }
250
251    void createOnScreenSurface(sp<Surface>& surface) {
252        mComposerClient = new SurfaceComposerClient;
253        ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
254
255        mSurfaceControl = mComposerClient->createSurface(
256                String8("ProCameraTest StreamingImage Surface"),
257                getSurfaceWidth(), getSurfaceHeight(),
258                PIXEL_FORMAT_RGB_888, 0);
259
260        mSurfaceControl->setPosition(640, 0);
261
262        ASSERT_TRUE(mSurfaceControl != NULL);
263        ASSERT_TRUE(mSurfaceControl->isValid());
264
265        SurfaceComposerClient::openGlobalTransaction();
266        ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7FFFFFFF));
267        ASSERT_EQ(NO_ERROR, mSurfaceControl->show());
268        SurfaceComposerClient::closeGlobalTransaction();
269
270        sp<ANativeWindow> window = mSurfaceControl->getSurface();
271        surface = mSurfaceControl->getSurface();
272
273        ASSERT_NE((void*)NULL, surface.get());
274    }
275
276    void createDepthOnScreenSurface(sp<Surface>& surface) {
277        mDepthComposerClient = new SurfaceComposerClient;
278        ASSERT_EQ(NO_ERROR, mDepthComposerClient->initCheck());
279
280        mDepthSurfaceControl = mDepthComposerClient->createSurface(
281                String8("ProCameraTest StreamingImage Surface"),
282                getSurfaceWidth(), getSurfaceHeight(),
283                PIXEL_FORMAT_RGB_888, 0);
284
285        mDepthSurfaceControl->setPosition(640, 0);
286
287        ASSERT_TRUE(mDepthSurfaceControl != NULL);
288        ASSERT_TRUE(mDepthSurfaceControl->isValid());
289
290        SurfaceComposerClient::openGlobalTransaction();
291        ASSERT_EQ(NO_ERROR, mDepthSurfaceControl->setLayer(0x7FFFFFFF));
292        ASSERT_EQ(NO_ERROR, mDepthSurfaceControl->show());
293        SurfaceComposerClient::closeGlobalTransaction();
294
295        sp<ANativeWindow> window = mDepthSurfaceControl->getSurface();
296        surface = mDepthSurfaceControl->getSurface();
297
298        ASSERT_NE((void*)NULL, surface.get());
299    }
300
301};
302
303sp<Thread> ProCameraTest::mTestThread;
304
305// test around exclusiveTryLock (immediate locking)
306TEST_F(ProCameraTest, LockingImmediate) {
307
308    if (HasFatalFailure()) {
309        return;
310    }
311
312    EXPECT_FALSE(mCamera->hasExclusiveLock());
313    EXPECT_EQ(OK, mCamera->exclusiveTryLock());
314    // at this point we definitely have the lock
315
316    EXPECT_EQ(OK, mListener->WaitForEvent());
317    EXPECT_EQ(ACQUIRED, mListener->ReadEvent());
318
319    EXPECT_TRUE(mCamera->hasExclusiveLock());
320    EXPECT_EQ(OK, mCamera->exclusiveUnlock());
321
322    EXPECT_EQ(OK, mListener->WaitForEvent());
323    EXPECT_EQ(RELEASED, mListener->ReadEvent());
324
325    EXPECT_FALSE(mCamera->hasExclusiveLock());
326}
327
328// test around exclusiveLock (locking at some future point in time)
329TEST_F(ProCameraTest, LockingAsynchronous) {
330
331    if (HasFatalFailure()) {
332        return;
333    }
334
335    // TODO: Add another procamera that has a lock here.
336    // then we can be test that the lock wont immediately be acquired
337
338    EXPECT_FALSE(mCamera->hasExclusiveLock());
339    EXPECT_EQ(OK, mCamera->exclusiveLock());
340    // at this point we may or may not have the lock
341    // we cant be sure until we get an ACQUIRED event
342
343    EXPECT_EQ(OK, mListener->WaitForEvent());
344    EXPECT_EQ(ACQUIRED, mListener->ReadEvent());
345
346    EXPECT_TRUE(mCamera->hasExclusiveLock());
347    EXPECT_EQ(OK, mCamera->exclusiveUnlock());
348
349    EXPECT_EQ(OK, mListener->WaitForEvent());
350    EXPECT_EQ(RELEASED, mListener->ReadEvent());
351
352    EXPECT_FALSE(mCamera->hasExclusiveLock());
353}
354
355// Stream directly to the screen.
356TEST_F(ProCameraTest, StreamingImageSingle) {
357    if (HasFatalFailure()) {
358        return;
359    }
360    char* displaySecsEnv = getenv("TEST_DISPLAY_SECS");
361    if (displaySecsEnv != NULL) {
362        mDisplaySecs = atoi(displaySecsEnv);
363        if (mDisplaySecs < 0) {
364            mDisplaySecs = 0;
365        }
366    } else {
367        mDisplaySecs = 0;
368    }
369
370    sp<Surface> depthSurface;
371    if (mDisplaySecs > 0) {
372        createDepthOnScreenSurface(/*out*/depthSurface);
373    }
374
375    int depthStreamId = -1;
376    EXPECT_OK(mCamera->createStream(/*width*/320, /*height*/240,
377                              TEST_FORMAT_DEPTH, depthSurface, &depthStreamId));
378    EXPECT_NE(-1, depthStreamId);
379
380    EXPECT_OK(mCamera->exclusiveTryLock());
381    /* iterate in a loop submitting requests every frame.
382     *  what kind of requests doesnt really matter, just whatever.
383     */
384
385    // it would probably be better to use CameraMetadata from camera service.
386    camera_metadata_t *request = NULL;
387    EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
388              /*out*/&request));
389    EXPECT_NE((void*)NULL, request);
390
391    /* FIXME: dont need this later, at which point the above should become an
392       ASSERT_NE*/
393    if(request == NULL) request = allocate_camera_metadata(10, 100);
394
395    // set the output streams to just this stream ID
396
397    // wow what a verbose API.
398    // i would give a loaf of bread for
399    //   metadata->updateOrInsert(keys.request.output.streams, streamId);
400    uint8_t allStreams[] = { depthStreamId };
401    size_t streamCount = sizeof(allStreams) / sizeof(allStreams[0]);
402
403    camera_metadata_entry_t entry;
404    uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS);
405    int find = find_camera_metadata_entry(request, tag, &entry);
406    if (find == -ENOENT) {
407        if (add_camera_metadata_entry(request, tag, &allStreams,
408            /*data_count*/streamCount) != OK) {
409            camera_metadata_t *tmp = allocate_camera_metadata(1000, 10000);
410            ASSERT_OK(append_camera_metadata(tmp, request));
411            free_camera_metadata(request);
412            request = tmp;
413
414            ASSERT_OK(add_camera_metadata_entry(request, tag, &allStreams,
415                /*data_count*/streamCount));
416        }
417    } else {
418        ASSERT_OK(update_camera_metadata_entry(request, entry.index,
419                &allStreams, /*data_count*/streamCount, &entry));
420    }
421
422    EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true));
423
424    dout << "will sleep now for " << mDisplaySecs << std::endl;
425    sleep(mDisplaySecs);
426
427    free_camera_metadata(request);
428
429    for (int i = 0; i < streamCount; ++i) {
430        EXPECT_OK(mCamera->deleteStream(allStreams[i]));
431    }
432    EXPECT_OK(mCamera->exclusiveUnlock());
433}
434
435// Stream directly to the screen.
436TEST_F(ProCameraTest, StreamingImageDual) {
437    if (HasFatalFailure()) {
438        return;
439    }
440    char* displaySecsEnv = getenv("TEST_DISPLAY_SECS");
441    if (displaySecsEnv != NULL) {
442        mDisplaySecs = atoi(displaySecsEnv);
443        if (mDisplaySecs < 0) {
444            mDisplaySecs = 0;
445        }
446    } else {
447        mDisplaySecs = 0;
448    }
449
450    sp<Surface> surface;
451    sp<Surface> depthSurface;
452    if (mDisplaySecs > 0) {
453        createOnScreenSurface(/*out*/surface);
454        createDepthOnScreenSurface(/*out*/depthSurface);
455    }
456
457    int streamId = -1;
458    EXPECT_OK(mCamera->createStream(/*width*/1280, /*height*/960,
459              TEST_FORMAT_MAIN, surface, &streamId));
460    EXPECT_NE(-1, streamId);
461
462    int depthStreamId = -1;
463    EXPECT_OK(mCamera->createStream(/*width*/320, /*height*/240,
464              TEST_FORMAT_DEPTH, depthSurface, &depthStreamId));
465    EXPECT_NE(-1, depthStreamId);
466
467    EXPECT_OK(mCamera->exclusiveTryLock());
468    /*
469    */
470    /* iterate in a loop submitting requests every frame.
471     *  what kind of requests doesnt really matter, just whatever.
472     */
473
474    // it would probably be better to use CameraMetadata from camera service.
475    camera_metadata_t *request = NULL;
476    EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
477              /*out*/&request));
478    EXPECT_NE((void*)NULL, request);
479
480    /*FIXME: dont need this later, at which point the above should become an
481             ASSERT_NE*/
482    if(request == NULL) request = allocate_camera_metadata(10, 100);
483
484    // set the output streams to just this stream ID
485
486    // wow what a verbose API.
487    uint8_t allStreams[] = { streamId, depthStreamId };
488    // IMPORTANT. bad things will happen if its not a uint8.
489    size_t streamCount = sizeof(allStreams) / sizeof(allStreams[0]);
490    camera_metadata_entry_t entry;
491    uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS);
492    int find = find_camera_metadata_entry(request, tag, &entry);
493    if (find == -ENOENT) {
494        if (add_camera_metadata_entry(request, tag, &allStreams,
495                                      /*data_count*/streamCount) != OK) {
496            camera_metadata_t *tmp = allocate_camera_metadata(1000, 10000);
497            ASSERT_OK(append_camera_metadata(tmp, request));
498            free_camera_metadata(request);
499            request = tmp;
500
501            ASSERT_OK(add_camera_metadata_entry(request, tag, &allStreams,
502                                                /*data_count*/streamCount));
503        }
504    } else {
505        ASSERT_OK(update_camera_metadata_entry(request, entry.index,
506                  &allStreams, /*data_count*/streamCount, &entry));
507    }
508
509    EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true));
510
511    dout << "will sleep now for " << mDisplaySecs << std::endl;
512    sleep(mDisplaySecs);
513
514    free_camera_metadata(request);
515
516    for (int i = 0; i < streamCount; ++i) {
517        EXPECT_OK(mCamera->deleteStream(allStreams[i]));
518    }
519    EXPECT_OK(mCamera->exclusiveUnlock());
520}
521
522TEST_F(ProCameraTest, CpuConsumerSingle) {
523    if (HasFatalFailure()) {
524        return;
525    }
526    int streamId = -1;
527    EXPECT_OK(mCamera->createStreamCpu(/*width*/320, /*height*/240,
528        TEST_FORMAT_DEPTH, TEST_CPU_HEAP_COUNT, &streamId));
529    EXPECT_NE(-1, streamId);
530
531    EXPECT_OK(mCamera->exclusiveTryLock());
532    EXPECT_EQ(OK, mListener->WaitForEvent());
533    EXPECT_EQ(ACQUIRED, mListener->ReadEvent());
534    /* iterate in a loop submitting requests every frame.
535     *  what kind of requests doesnt really matter, just whatever.
536     */
537
538    // it would probably be better to use CameraMetadata from camera service.
539    camera_metadata_t *request = NULL;
540    EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
541        /*out*/&request));
542    EXPECT_NE((void*)NULL, request);
543
544    /*FIXME: dont need this later, at which point the above should become an
545      ASSERT_NE*/
546    if(request == NULL) request = allocate_camera_metadata(10, 100);
547
548    // set the output streams to just this stream ID
549
550    uint8_t allStreams[] = { streamId };
551    camera_metadata_entry_t entry;
552    uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS);
553    int find = find_camera_metadata_entry(request, tag, &entry);
554    if (find == -ENOENT) {
555        if (add_camera_metadata_entry(request, tag, &allStreams,
556                /*data_count*/1) != OK) {
557            camera_metadata_t *tmp = allocate_camera_metadata(1000, 10000);
558            ASSERT_OK(append_camera_metadata(tmp, request));
559            free_camera_metadata(request);
560            request = tmp;
561
562            ASSERT_OK(add_camera_metadata_entry(request, tag, &allStreams,
563                /*data_count*/1));
564        }
565    } else {
566        ASSERT_OK(update_camera_metadata_entry(request, entry.index,
567            &allStreams, /*data_count*/1, &entry));
568    }
569
570    EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true));
571
572    // Consume a couple of frames
573    for (int i = 0; i < TEST_CPU_FRAME_COUNT; ++i) {
574        EXPECT_EQ(OK, mListener->WaitForEvent());
575        EXPECT_EQ(BUFFER_RECEIVED, mListener->ReadEvent());
576    }
577
578    // Done: clean up
579    free_camera_metadata(request);
580    EXPECT_OK(mCamera->deleteStream(streamId));
581    EXPECT_OK(mCamera->exclusiveUnlock());
582}
583
584TEST_F(ProCameraTest, CpuConsumerDual) {
585    if (HasFatalFailure()) {
586        return;
587    }
588    int streamId = -1;
589    EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960,
590                            TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT, &streamId));
591    EXPECT_NE(-1, streamId);
592
593    int depthStreamId = -1;
594    EXPECT_OK(mCamera->createStreamCpu(/*width*/320, /*height*/240,
595                     TEST_FORMAT_DEPTH, TEST_CPU_HEAP_COUNT, &depthStreamId));
596    EXPECT_NE(-1, depthStreamId);
597
598    EXPECT_OK(mCamera->exclusiveTryLock());
599    EXPECT_EQ(OK, mListener->WaitForEvent());
600    EXPECT_EQ(ACQUIRED, mListener->ReadEvent());
601    /*
602    */
603    /* iterate in a loop submitting requests every frame.
604     *  what kind of requests doesnt really matter, just whatever.
605     */
606
607    // it would probably be better to use CameraMetadata from camera service.
608    camera_metadata_t *request = NULL;
609    EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
610                                            /*out*/&request));
611    EXPECT_NE((void*)NULL, request);
612
613    if(request == NULL) request = allocate_camera_metadata(10, 100);
614
615    // set the output streams to just this stream ID
616
617    // wow what a verbose API.
618    uint8_t allStreams[] = { streamId, depthStreamId };
619    size_t streamCount = 2;
620    camera_metadata_entry_t entry;
621    uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS);
622    int find = find_camera_metadata_entry(request, tag, &entry);
623    if (find == -ENOENT) {
624        if (add_camera_metadata_entry(request, tag, &allStreams,
625                                      /*data_count*/streamCount) != OK) {
626            camera_metadata_t *tmp = allocate_camera_metadata(1000, 10000);
627            ASSERT_OK(append_camera_metadata(tmp, request));
628            free_camera_metadata(request);
629            request = tmp;
630
631            ASSERT_OK(add_camera_metadata_entry(request, tag, &allStreams,
632                                                   /*data_count*/streamCount));
633        }
634    } else {
635        ASSERT_OK(update_camera_metadata_entry(request, entry.index,
636                              &allStreams, /*data_count*/streamCount, &entry));
637    }
638
639    EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true));
640
641    // Consume a couple of frames
642    for (int i = 0; i < TEST_CPU_FRAME_COUNT; ++i) {
643        // stream id 1
644        EXPECT_EQ(OK, mListener->WaitForEvent());
645        EXPECT_EQ(BUFFER_RECEIVED, mListener->ReadEvent());
646
647        // stream id 2
648        EXPECT_EQ(OK, mListener->WaitForEvent());
649        EXPECT_EQ(BUFFER_RECEIVED, mListener->ReadEvent());
650
651        //TODO: events should be a struct with some data like the stream id
652    }
653
654    // Done: clean up
655    free_camera_metadata(request);
656    EXPECT_OK(mCamera->deleteStream(streamId));
657    EXPECT_OK(mCamera->exclusiveUnlock());
658}
659
660}
661}
662}
663}
664
665