ProCameraTests.cpp revision d127c2c8a8b68dae2f8743c310c2547e8f46d967
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    RESULT_RECEIVED,
70};
71
72inline int ProEvent_Mask(ProEvent e) {
73    return (1 << static_cast<int>(e));
74}
75
76typedef Vector<ProEvent> EventList;
77
78class ProCameraTestThread : public Thread
79{
80public:
81    ProCameraTestThread() {
82    }
83
84    virtual bool threadLoop() {
85        mProc = ProcessState::self();
86        mProc->startThreadPool();
87
88        IPCThreadState *ptr = IPCThreadState::self();
89
90        ptr->joinThreadPool();
91
92        return false;
93    }
94
95    sp<ProcessState> mProc;
96};
97
98class ProCameraTestListener : public ProCameraListener {
99
100public:
101    static const int EVENT_MASK_ALL = 0xFFFFFFFF;
102
103    ProCameraTestListener() {
104        mEventMask = EVENT_MASK_ALL;
105    }
106
107    status_t WaitForEvent() {
108        Mutex::Autolock cal(mConditionMutex);
109
110        {
111            Mutex::Autolock al(mListenerMutex);
112
113            if (mProEventList.size() > 0) {
114                return OK;
115            }
116        }
117
118        return mListenerCondition.waitRelative(mConditionMutex,
119                                               TEST_LISTENER_TIMEOUT);
120    }
121
122    /* Read events into out. Existing queue is flushed */
123    void ReadEvents(EventList& out) {
124        Mutex::Autolock al(mListenerMutex);
125
126        for (size_t i = 0; i < mProEventList.size(); ++i) {
127            out.push(mProEventList[i]);
128        }
129
130        mProEventList.clear();
131    }
132
133    /**
134      * Dequeue 1 event from the event queue.
135      * Returns UNKNOWN if queue is empty
136      */
137    ProEvent ReadEvent() {
138        Mutex::Autolock al(mListenerMutex);
139
140        if (mProEventList.size() == 0) {
141            return UNKNOWN;
142        }
143
144        ProEvent ev = mProEventList[0];
145        mProEventList.removeAt(0);
146
147        return ev;
148    }
149
150    void SetEventMask(int eventMask) {
151        Mutex::Autolock al(mListenerMutex);
152        mEventMask = eventMask;
153    }
154
155private:
156    void QueueEvent(ProEvent ev) {
157        bool eventAdded = false;
158        {
159            Mutex::Autolock al(mListenerMutex);
160
161            if (ProEvent_Mask(ev) & mEventMask) {
162                mProEventList.push(ev);
163                eventAdded = true;
164            }
165        }
166
167        if (eventAdded) {
168            mListenerCondition.broadcast();
169        }
170    }
171
172protected:
173
174    //////////////////////////////////////////////////
175    ///////// ProCameraListener //////////////////////
176    //////////////////////////////////////////////////
177
178
179    // Lock has been acquired. Write operations now available.
180    virtual void onLockAcquired() {
181        QueueEvent(ACQUIRED);
182    }
183    // Lock has been released with exclusiveUnlock
184    virtual void onLockReleased() {
185        QueueEvent(RELEASED);
186    }
187
188    // Lock has been stolen by another client.
189    virtual void onLockStolen() {
190        QueueEvent(STOLEN);
191    }
192
193    // Lock free.
194    virtual void onTriggerNotify(int32_t ext1, int32_t ext2, int32_t ext3) {
195
196        dout << "Trigger notify: " << ext1 << " " << ext2
197             << " " << ext3 << std::endl;
198    }
199
200    virtual void onBufferReceived(int streamId,
201                                  const CpuConsumer::LockedBuffer& buf) {
202
203        dout << "Buffer received on streamId = " << streamId <<
204                ", dataPtr = " << (void*)buf.data << std::endl;
205
206        QueueEvent(BUFFER_RECEIVED);
207
208    }
209    virtual void onResultReceived(int32_t frameId,
210                                  camera_metadata* request) {
211        dout << "Result received frameId = " << frameId
212             << ", requestPtr = " << (void*)request << std::endl;
213        QueueEvent(RESULT_RECEIVED);
214        free_camera_metadata(request);
215    }
216
217    // TODO: remove
218
219    virtual void notify(int32_t , int32_t , int32_t ) {}
220    virtual void postData(int32_t , const sp<IMemory>& ,
221                          camera_frame_metadata_t *) {}
222    virtual void postDataTimestamp(nsecs_t , int32_t , const sp<IMemory>& ) {}
223
224
225    Vector<ProEvent> mProEventList;
226    Mutex             mListenerMutex;
227    Mutex             mConditionMutex;
228    Condition         mListenerCondition;
229    int               mEventMask;
230};
231
232class ProCameraTest : public ::testing::Test {
233
234public:
235    ProCameraTest() {
236    }
237
238    static void SetUpTestCase() {
239        // Binder Thread Pool Initialization
240        mTestThread = new ProCameraTestThread();
241        mTestThread->run("ProCameraTestThread");
242    }
243
244    virtual void SetUp() {
245        mCamera = ProCamera::connect(CAMERA_ID);
246        ASSERT_NE((void*)NULL, mCamera.get());
247
248        mListener = new ProCameraTestListener();
249        mCamera->setListener(mListener);
250    }
251
252    virtual void TearDown() {
253        ASSERT_NE((void*)NULL, mCamera.get());
254        mCamera->disconnect();
255    }
256
257protected:
258    sp<ProCamera> mCamera;
259    sp<ProCameraTestListener> mListener;
260
261    static sp<Thread> mTestThread;
262
263    int mDisplaySecs;
264    sp<SurfaceComposerClient> mComposerClient;
265    sp<SurfaceControl> mSurfaceControl;
266
267    sp<SurfaceComposerClient> mDepthComposerClient;
268    sp<SurfaceControl> mDepthSurfaceControl;
269
270    int getSurfaceWidth() {
271        return 512;
272    }
273    int getSurfaceHeight() {
274        return 512;
275    }
276
277    void createOnScreenSurface(sp<Surface>& surface) {
278        mComposerClient = new SurfaceComposerClient;
279        ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
280
281        mSurfaceControl = mComposerClient->createSurface(
282                String8("ProCameraTest StreamingImage Surface"),
283                getSurfaceWidth(), getSurfaceHeight(),
284                PIXEL_FORMAT_RGB_888, 0);
285
286        mSurfaceControl->setPosition(640, 0);
287
288        ASSERT_TRUE(mSurfaceControl != NULL);
289        ASSERT_TRUE(mSurfaceControl->isValid());
290
291        SurfaceComposerClient::openGlobalTransaction();
292        ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7FFFFFFF));
293        ASSERT_EQ(NO_ERROR, mSurfaceControl->show());
294        SurfaceComposerClient::closeGlobalTransaction();
295
296        sp<ANativeWindow> window = mSurfaceControl->getSurface();
297        surface = mSurfaceControl->getSurface();
298
299        ASSERT_NE((void*)NULL, surface.get());
300    }
301
302    void createDepthOnScreenSurface(sp<Surface>& surface) {
303        mDepthComposerClient = new SurfaceComposerClient;
304        ASSERT_EQ(NO_ERROR, mDepthComposerClient->initCheck());
305
306        mDepthSurfaceControl = mDepthComposerClient->createSurface(
307                String8("ProCameraTest StreamingImage Surface"),
308                getSurfaceWidth(), getSurfaceHeight(),
309                PIXEL_FORMAT_RGB_888, 0);
310
311        mDepthSurfaceControl->setPosition(640, 0);
312
313        ASSERT_TRUE(mDepthSurfaceControl != NULL);
314        ASSERT_TRUE(mDepthSurfaceControl->isValid());
315
316        SurfaceComposerClient::openGlobalTransaction();
317        ASSERT_EQ(NO_ERROR, mDepthSurfaceControl->setLayer(0x7FFFFFFF));
318        ASSERT_EQ(NO_ERROR, mDepthSurfaceControl->show());
319        SurfaceComposerClient::closeGlobalTransaction();
320
321        sp<ANativeWindow> window = mDepthSurfaceControl->getSurface();
322        surface = mDepthSurfaceControl->getSurface();
323
324        ASSERT_NE((void*)NULL, surface.get());
325    }
326
327    template <typename T>
328    static bool FindItem(T needle, T* array, size_t count) {
329        for (int i = 0; i < count; ++i) {
330            if (array[i] == needle) {
331                return true;
332            }
333        }
334        return false;
335    }
336
337};
338
339sp<Thread> ProCameraTest::mTestThread;
340
341TEST_F(ProCameraTest, AvailableFormats) {
342    if (HasFatalFailure()) {
343        return;
344    }
345
346    camera_metadata_t* info = mCamera->getCameraInfo(CAMERA_ID);
347    ASSERT_NE((void*)NULL, info);
348
349    camera_metadata_entry_t entry;
350    uint32_t tag = static_cast<uint32_t>(ANDROID_SCALER_AVAILABLE_FORMATS);
351    EXPECT_EQ(OK, find_camera_metadata_entry(info, tag, &entry));
352
353    EXPECT_TRUE(FindItem<int32_t>(HAL_PIXEL_FORMAT_YV12,
354                                                  entry.data.i32, entry.count));
355    EXPECT_TRUE(FindItem<int32_t>(HAL_PIXEL_FORMAT_YCrCb_420_SP,
356                                                  entry.data.i32, entry.count));
357
358    free_camera_metadata(info);
359}
360
361// test around exclusiveTryLock (immediate locking)
362TEST_F(ProCameraTest, LockingImmediate) {
363
364    if (HasFatalFailure()) {
365        return;
366    }
367
368    mListener->SetEventMask(ProEvent_Mask(ACQUIRED) |
369                            ProEvent_Mask(STOLEN)   |
370                            ProEvent_Mask(RELEASED));
371
372    EXPECT_FALSE(mCamera->hasExclusiveLock());
373    EXPECT_EQ(OK, mCamera->exclusiveTryLock());
374    // at this point we definitely have the lock
375
376    EXPECT_EQ(OK, mListener->WaitForEvent());
377    EXPECT_EQ(ACQUIRED, mListener->ReadEvent());
378
379    EXPECT_TRUE(mCamera->hasExclusiveLock());
380    EXPECT_EQ(OK, mCamera->exclusiveUnlock());
381
382    EXPECT_EQ(OK, mListener->WaitForEvent());
383    EXPECT_EQ(RELEASED, mListener->ReadEvent());
384
385    EXPECT_FALSE(mCamera->hasExclusiveLock());
386}
387
388// test around exclusiveLock (locking at some future point in time)
389TEST_F(ProCameraTest, LockingAsynchronous) {
390
391    if (HasFatalFailure()) {
392        return;
393    }
394
395
396    mListener->SetEventMask(ProEvent_Mask(ACQUIRED) |
397                            ProEvent_Mask(STOLEN)   |
398                            ProEvent_Mask(RELEASED));
399
400    // TODO: Add another procamera that has a lock here.
401    // then we can be test that the lock wont immediately be acquired
402
403    EXPECT_FALSE(mCamera->hasExclusiveLock());
404    EXPECT_EQ(OK, mCamera->exclusiveTryLock());
405    // at this point we definitely have the lock
406
407    EXPECT_EQ(OK, mListener->WaitForEvent());
408    EXPECT_EQ(ACQUIRED, mListener->ReadEvent());
409
410    EXPECT_TRUE(mCamera->hasExclusiveLock());
411    EXPECT_EQ(OK, mCamera->exclusiveUnlock());
412
413    EXPECT_EQ(OK, mListener->WaitForEvent());
414    EXPECT_EQ(RELEASED, mListener->ReadEvent());
415
416    EXPECT_FALSE(mCamera->hasExclusiveLock());
417}
418
419// Stream directly to the screen.
420TEST_F(ProCameraTest, DISABLED_StreamingImageSingle) {
421    if (HasFatalFailure()) {
422        return;
423    }
424    char* displaySecsEnv = getenv("TEST_DISPLAY_SECS");
425    if (displaySecsEnv != NULL) {
426        mDisplaySecs = atoi(displaySecsEnv);
427        if (mDisplaySecs < 0) {
428            mDisplaySecs = 0;
429        }
430    } else {
431        mDisplaySecs = 0;
432    }
433
434    sp<Surface> depthSurface;
435    if (mDisplaySecs > 0) {
436        createDepthOnScreenSurface(/*out*/depthSurface);
437    }
438
439    int depthStreamId = -1;
440    EXPECT_OK(mCamera->createStream(/*width*/320, /*height*/240,
441                              TEST_FORMAT_DEPTH, depthSurface, &depthStreamId));
442    EXPECT_NE(-1, depthStreamId);
443
444    EXPECT_OK(mCamera->exclusiveTryLock());
445    /* iterate in a loop submitting requests every frame.
446     *  what kind of requests doesnt really matter, just whatever.
447     */
448
449    // it would probably be better to use CameraMetadata from camera service.
450    camera_metadata_t *request = NULL;
451    EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
452              /*out*/&request));
453    EXPECT_NE((void*)NULL, request);
454
455    /* FIXME: dont need this later, at which point the above should become an
456       ASSERT_NE*/
457    if(request == NULL) request = allocate_camera_metadata(10, 100);
458
459    // set the output streams to just this stream ID
460
461    // wow what a verbose API.
462    // i would give a loaf of bread for
463    //   metadata->updateOrInsert(keys.request.output.streams, streamId);
464    uint8_t allStreams[] = { depthStreamId };
465    size_t streamCount = sizeof(allStreams) / sizeof(allStreams[0]);
466
467    camera_metadata_entry_t entry;
468    uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS);
469    int find = find_camera_metadata_entry(request, tag, &entry);
470    if (find == -ENOENT) {
471        if (add_camera_metadata_entry(request, tag, &allStreams,
472            /*data_count*/streamCount) != OK) {
473            camera_metadata_t *tmp = allocate_camera_metadata(1000, 10000);
474            ASSERT_OK(append_camera_metadata(tmp, request));
475            free_camera_metadata(request);
476            request = tmp;
477
478            ASSERT_OK(add_camera_metadata_entry(request, tag, &allStreams,
479                /*data_count*/streamCount));
480        }
481    } else {
482        ASSERT_OK(update_camera_metadata_entry(request, entry.index,
483                &allStreams, /*data_count*/streamCount, &entry));
484    }
485
486    EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true));
487
488    dout << "will sleep now for " << mDisplaySecs << std::endl;
489    sleep(mDisplaySecs);
490
491    free_camera_metadata(request);
492
493    for (int i = 0; i < streamCount; ++i) {
494        EXPECT_OK(mCamera->deleteStream(allStreams[i]));
495    }
496    EXPECT_OK(mCamera->exclusiveUnlock());
497}
498
499// Stream directly to the screen.
500TEST_F(ProCameraTest, DISABLED_StreamingImageDual) {
501    if (HasFatalFailure()) {
502        return;
503    }
504    char* displaySecsEnv = getenv("TEST_DISPLAY_SECS");
505    if (displaySecsEnv != NULL) {
506        mDisplaySecs = atoi(displaySecsEnv);
507        if (mDisplaySecs < 0) {
508            mDisplaySecs = 0;
509        }
510    } else {
511        mDisplaySecs = 0;
512    }
513
514    sp<Surface> surface;
515    sp<Surface> depthSurface;
516    if (mDisplaySecs > 0) {
517        createOnScreenSurface(/*out*/surface);
518        createDepthOnScreenSurface(/*out*/depthSurface);
519    }
520
521    int streamId = -1;
522    EXPECT_OK(mCamera->createStream(/*width*/1280, /*height*/960,
523              TEST_FORMAT_MAIN, surface, &streamId));
524    EXPECT_NE(-1, streamId);
525
526    int depthStreamId = -1;
527    EXPECT_OK(mCamera->createStream(/*width*/320, /*height*/240,
528              TEST_FORMAT_DEPTH, depthSurface, &depthStreamId));
529    EXPECT_NE(-1, depthStreamId);
530
531    EXPECT_OK(mCamera->exclusiveTryLock());
532    /*
533    */
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    // wow what a verbose API.
551    uint8_t allStreams[] = { streamId, depthStreamId };
552    // IMPORTANT. bad things will happen if its not a uint8.
553    size_t streamCount = sizeof(allStreams) / sizeof(allStreams[0]);
554    camera_metadata_entry_t entry;
555    uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS);
556    int find = find_camera_metadata_entry(request, tag, &entry);
557    if (find == -ENOENT) {
558        if (add_camera_metadata_entry(request, tag, &allStreams,
559                                      /*data_count*/streamCount) != OK) {
560            camera_metadata_t *tmp = allocate_camera_metadata(1000, 10000);
561            ASSERT_OK(append_camera_metadata(tmp, request));
562            free_camera_metadata(request);
563            request = tmp;
564
565            ASSERT_OK(add_camera_metadata_entry(request, tag, &allStreams,
566                                                /*data_count*/streamCount));
567        }
568    } else {
569        ASSERT_OK(update_camera_metadata_entry(request, entry.index,
570                  &allStreams, /*data_count*/streamCount, &entry));
571    }
572
573    EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true));
574
575    dout << "will sleep now for " << mDisplaySecs << std::endl;
576    sleep(mDisplaySecs);
577
578    free_camera_metadata(request);
579
580    for (int i = 0; i < streamCount; ++i) {
581        EXPECT_OK(mCamera->deleteStream(allStreams[i]));
582    }
583    EXPECT_OK(mCamera->exclusiveUnlock());
584}
585
586TEST_F(ProCameraTest, CpuConsumerSingle) {
587    if (HasFatalFailure()) {
588        return;
589    }
590
591    mListener->SetEventMask(ProEvent_Mask(BUFFER_RECEIVED));
592
593    int streamId = -1;
594    EXPECT_OK(mCamera->createStreamCpu(/*width*/320, /*height*/240,
595        TEST_FORMAT_DEPTH, TEST_CPU_HEAP_COUNT, &streamId));
596    EXPECT_NE(-1, streamId);
597
598    EXPECT_OK(mCamera->exclusiveTryLock());
599    EXPECT_EQ(OK, mListener->WaitForEvent());
600    EXPECT_EQ(ACQUIRED, mListener->ReadEvent());
601    /* iterate in a loop submitting requests every frame.
602     *  what kind of requests doesnt really matter, just whatever.
603     */
604
605    // it would probably be better to use CameraMetadata from camera service.
606    camera_metadata_t *request = NULL;
607    EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
608        /*out*/&request));
609    EXPECT_NE((void*)NULL, request);
610
611    /*FIXME: dont need this later, at which point the above should become an
612      ASSERT_NE*/
613    if(request == NULL) request = allocate_camera_metadata(10, 100);
614
615    // set the output streams to just this stream ID
616
617    uint8_t allStreams[] = { streamId };
618    camera_metadata_entry_t entry;
619    uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS);
620    int find = find_camera_metadata_entry(request, tag, &entry);
621    if (find == -ENOENT) {
622        if (add_camera_metadata_entry(request, tag, &allStreams,
623                /*data_count*/1) != OK) {
624            camera_metadata_t *tmp = allocate_camera_metadata(1000, 10000);
625            ASSERT_OK(append_camera_metadata(tmp, request));
626            free_camera_metadata(request);
627            request = tmp;
628
629            ASSERT_OK(add_camera_metadata_entry(request, tag, &allStreams,
630                /*data_count*/1));
631        }
632    } else {
633        ASSERT_OK(update_camera_metadata_entry(request, entry.index,
634            &allStreams, /*data_count*/1, &entry));
635    }
636
637    EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true));
638
639    // Consume a couple of frames
640    for (int i = 0; i < TEST_CPU_FRAME_COUNT; ++i) {
641        EXPECT_EQ(OK, mListener->WaitForEvent());
642        EXPECT_EQ(BUFFER_RECEIVED, mListener->ReadEvent());
643    }
644
645    // Done: clean up
646    free_camera_metadata(request);
647    EXPECT_OK(mCamera->deleteStream(streamId));
648    EXPECT_OK(mCamera->exclusiveUnlock());
649}
650
651TEST_F(ProCameraTest, CpuConsumerDual) {
652    if (HasFatalFailure()) {
653        return;
654    }
655
656    mListener->SetEventMask(ProEvent_Mask(BUFFER_RECEIVED));
657
658    int streamId = -1;
659    EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960,
660                            TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT, &streamId));
661    EXPECT_NE(-1, streamId);
662
663    int depthStreamId = -1;
664    EXPECT_OK(mCamera->createStreamCpu(/*width*/320, /*height*/240,
665                     TEST_FORMAT_DEPTH, TEST_CPU_HEAP_COUNT, &depthStreamId));
666    EXPECT_NE(-1, depthStreamId);
667
668    EXPECT_OK(mCamera->exclusiveTryLock());
669    /*
670    */
671    /* iterate in a loop submitting requests every frame.
672     *  what kind of requests doesnt really matter, just whatever.
673     */
674
675    // it would probably be better to use CameraMetadata from camera service.
676    camera_metadata_t *request = NULL;
677    EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
678                                            /*out*/&request));
679    EXPECT_NE((void*)NULL, request);
680
681    if(request == NULL) request = allocate_camera_metadata(10, 100);
682
683    // set the output streams to just this stream ID
684
685    // wow what a verbose API.
686    uint8_t allStreams[] = { streamId, depthStreamId };
687    size_t streamCount = 2;
688    camera_metadata_entry_t entry;
689    uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS);
690    int find = find_camera_metadata_entry(request, tag, &entry);
691    if (find == -ENOENT) {
692        if (add_camera_metadata_entry(request, tag, &allStreams,
693                                      /*data_count*/streamCount) != OK) {
694            camera_metadata_t *tmp = allocate_camera_metadata(1000, 10000);
695            ASSERT_OK(append_camera_metadata(tmp, request));
696            free_camera_metadata(request);
697            request = tmp;
698
699            ASSERT_OK(add_camera_metadata_entry(request, tag, &allStreams,
700                                                   /*data_count*/streamCount));
701        }
702    } else {
703        ASSERT_OK(update_camera_metadata_entry(request, entry.index,
704                              &allStreams, /*data_count*/streamCount, &entry));
705    }
706
707    EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true));
708
709    // Consume a couple of frames
710    for (int i = 0; i < TEST_CPU_FRAME_COUNT; ++i) {
711        // stream id 1
712        EXPECT_EQ(OK, mListener->WaitForEvent());
713        EXPECT_EQ(BUFFER_RECEIVED, mListener->ReadEvent());
714
715        // stream id 2
716        EXPECT_EQ(OK, mListener->WaitForEvent());
717        EXPECT_EQ(BUFFER_RECEIVED, mListener->ReadEvent());
718
719        //TODO: events should be a struct with some data like the stream id
720    }
721
722    // Done: clean up
723    free_camera_metadata(request);
724    EXPECT_OK(mCamera->deleteStream(streamId));
725    EXPECT_OK(mCamera->exclusiveUnlock());
726}
727
728TEST_F(ProCameraTest, ResultReceiver) {
729    if (HasFatalFailure()) {
730        return;
731    }
732
733    mListener->SetEventMask(ProEvent_Mask(RESULT_RECEIVED));
734    //FIXME: if this is run right after the previous test we get BUFFER_RECEIVED
735    // need to filter out events at read time
736
737    int streamId = -1;
738    EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960,
739                             TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT, &streamId));
740    EXPECT_NE(-1, streamId);
741
742    EXPECT_OK(mCamera->exclusiveTryLock());
743    /*
744    */
745    /* iterate in a loop submitting requests every frame.
746     *  what kind of requests doesnt really matter, just whatever.
747     */
748
749    camera_metadata_t *request = NULL;
750    EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
751                                            /*out*/&request));
752    EXPECT_NE((void*)NULL, request);
753
754    /*FIXME*/
755    if(request == NULL) request = allocate_camera_metadata(10, 100);
756
757    // set the output streams to just this stream ID
758
759    uint8_t allStreams[] = { streamId };
760    size_t streamCount = 1;
761    camera_metadata_entry_t entry;
762    uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS);
763    int find = find_camera_metadata_entry(request, tag, &entry);
764    if (find == -ENOENT) {
765        if (add_camera_metadata_entry(request, tag, &allStreams,
766                                      /*data_count*/streamCount) != OK) {
767            camera_metadata_t *tmp = allocate_camera_metadata(1000, 10000);
768            ASSERT_OK(append_camera_metadata(tmp, request));
769            free_camera_metadata(request);
770            request = tmp;
771
772            ASSERT_OK(add_camera_metadata_entry(request, tag, &allStreams,
773                                                /*data_count*/streamCount));
774        }
775    } else {
776        ASSERT_OK(update_camera_metadata_entry(request, entry.index,
777                               &allStreams, /*data_count*/streamCount, &entry));
778    }
779
780    EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true));
781
782    // Consume a couple of results
783    for (int i = 0; i < TEST_CPU_FRAME_COUNT; ++i) {
784        EXPECT_EQ(OK, mListener->WaitForEvent());
785        EXPECT_EQ(RESULT_RECEIVED, mListener->ReadEvent());
786    }
787
788    // Done: clean up
789    free_camera_metadata(request);
790    EXPECT_OK(mCamera->deleteStream(streamId));
791    EXPECT_OK(mCamera->exclusiveUnlock());
792}
793
794}
795}
796}
797}
798
799