ProCameraTests.cpp revision a91537e268f2b35f9f0dfdc0c4f84655c93285ae
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};
328
329sp<Thread> ProCameraTest::mTestThread;
330
331// test around exclusiveTryLock (immediate locking)
332TEST_F(ProCameraTest, LockingImmediate) {
333
334    if (HasFatalFailure()) {
335        return;
336    }
337
338    mListener->SetEventMask(ProEvent_Mask(ACQUIRED) |
339                            ProEvent_Mask(STOLEN)   |
340                            ProEvent_Mask(RELEASED));
341
342    EXPECT_FALSE(mCamera->hasExclusiveLock());
343    EXPECT_EQ(OK, mCamera->exclusiveTryLock());
344    // at this point we definitely have the lock
345
346    EXPECT_EQ(OK, mListener->WaitForEvent());
347    EXPECT_EQ(ACQUIRED, mListener->ReadEvent());
348
349    EXPECT_TRUE(mCamera->hasExclusiveLock());
350    EXPECT_EQ(OK, mCamera->exclusiveUnlock());
351
352    EXPECT_EQ(OK, mListener->WaitForEvent());
353    EXPECT_EQ(RELEASED, mListener->ReadEvent());
354
355    EXPECT_FALSE(mCamera->hasExclusiveLock());
356}
357
358// test around exclusiveLock (locking at some future point in time)
359TEST_F(ProCameraTest, LockingAsynchronous) {
360
361    if (HasFatalFailure()) {
362        return;
363    }
364
365
366    mListener->SetEventMask(ProEvent_Mask(ACQUIRED) |
367                            ProEvent_Mask(STOLEN)   |
368                            ProEvent_Mask(RELEASED));
369
370    // TODO: Add another procamera that has a lock here.
371    // then we can be test that the lock wont immediately be acquired
372
373    EXPECT_FALSE(mCamera->hasExclusiveLock());
374    EXPECT_EQ(OK, mCamera->exclusiveTryLock());
375    // at this point we definitely have the lock
376
377    EXPECT_EQ(OK, mListener->WaitForEvent());
378    EXPECT_EQ(ACQUIRED, mListener->ReadEvent());
379
380    EXPECT_TRUE(mCamera->hasExclusiveLock());
381    EXPECT_EQ(OK, mCamera->exclusiveUnlock());
382
383    EXPECT_EQ(OK, mListener->WaitForEvent());
384    EXPECT_EQ(RELEASED, mListener->ReadEvent());
385
386    EXPECT_FALSE(mCamera->hasExclusiveLock());
387}
388
389// Stream directly to the screen.
390TEST_F(ProCameraTest, DISABLED_StreamingImageSingle) {
391    if (HasFatalFailure()) {
392        return;
393    }
394    char* displaySecsEnv = getenv("TEST_DISPLAY_SECS");
395    if (displaySecsEnv != NULL) {
396        mDisplaySecs = atoi(displaySecsEnv);
397        if (mDisplaySecs < 0) {
398            mDisplaySecs = 0;
399        }
400    } else {
401        mDisplaySecs = 0;
402    }
403
404    sp<Surface> depthSurface;
405    if (mDisplaySecs > 0) {
406        createDepthOnScreenSurface(/*out*/depthSurface);
407    }
408
409    int depthStreamId = -1;
410    EXPECT_OK(mCamera->createStream(/*width*/320, /*height*/240,
411                              TEST_FORMAT_DEPTH, depthSurface, &depthStreamId));
412    EXPECT_NE(-1, depthStreamId);
413
414    EXPECT_OK(mCamera->exclusiveTryLock());
415    /* iterate in a loop submitting requests every frame.
416     *  what kind of requests doesnt really matter, just whatever.
417     */
418
419    // it would probably be better to use CameraMetadata from camera service.
420    camera_metadata_t *request = NULL;
421    EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
422              /*out*/&request));
423    EXPECT_NE((void*)NULL, request);
424
425    /* FIXME: dont need this later, at which point the above should become an
426       ASSERT_NE*/
427    if(request == NULL) request = allocate_camera_metadata(10, 100);
428
429    // set the output streams to just this stream ID
430
431    // wow what a verbose API.
432    // i would give a loaf of bread for
433    //   metadata->updateOrInsert(keys.request.output.streams, streamId);
434    uint8_t allStreams[] = { depthStreamId };
435    size_t streamCount = sizeof(allStreams) / sizeof(allStreams[0]);
436
437    camera_metadata_entry_t entry;
438    uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS);
439    int find = find_camera_metadata_entry(request, tag, &entry);
440    if (find == -ENOENT) {
441        if (add_camera_metadata_entry(request, tag, &allStreams,
442            /*data_count*/streamCount) != OK) {
443            camera_metadata_t *tmp = allocate_camera_metadata(1000, 10000);
444            ASSERT_OK(append_camera_metadata(tmp, request));
445            free_camera_metadata(request);
446            request = tmp;
447
448            ASSERT_OK(add_camera_metadata_entry(request, tag, &allStreams,
449                /*data_count*/streamCount));
450        }
451    } else {
452        ASSERT_OK(update_camera_metadata_entry(request, entry.index,
453                &allStreams, /*data_count*/streamCount, &entry));
454    }
455
456    EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true));
457
458    dout << "will sleep now for " << mDisplaySecs << std::endl;
459    sleep(mDisplaySecs);
460
461    free_camera_metadata(request);
462
463    for (int i = 0; i < streamCount; ++i) {
464        EXPECT_OK(mCamera->deleteStream(allStreams[i]));
465    }
466    EXPECT_OK(mCamera->exclusiveUnlock());
467}
468
469// Stream directly to the screen.
470TEST_F(ProCameraTest, DISABLED_StreamingImageDual) {
471    if (HasFatalFailure()) {
472        return;
473    }
474    char* displaySecsEnv = getenv("TEST_DISPLAY_SECS");
475    if (displaySecsEnv != NULL) {
476        mDisplaySecs = atoi(displaySecsEnv);
477        if (mDisplaySecs < 0) {
478            mDisplaySecs = 0;
479        }
480    } else {
481        mDisplaySecs = 0;
482    }
483
484    sp<Surface> surface;
485    sp<Surface> depthSurface;
486    if (mDisplaySecs > 0) {
487        createOnScreenSurface(/*out*/surface);
488        createDepthOnScreenSurface(/*out*/depthSurface);
489    }
490
491    int streamId = -1;
492    EXPECT_OK(mCamera->createStream(/*width*/1280, /*height*/960,
493              TEST_FORMAT_MAIN, surface, &streamId));
494    EXPECT_NE(-1, streamId);
495
496    int depthStreamId = -1;
497    EXPECT_OK(mCamera->createStream(/*width*/320, /*height*/240,
498              TEST_FORMAT_DEPTH, depthSurface, &depthStreamId));
499    EXPECT_NE(-1, depthStreamId);
500
501    EXPECT_OK(mCamera->exclusiveTryLock());
502    /*
503    */
504    /* iterate in a loop submitting requests every frame.
505     *  what kind of requests doesnt really matter, just whatever.
506     */
507
508    // it would probably be better to use CameraMetadata from camera service.
509    camera_metadata_t *request = NULL;
510    EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
511              /*out*/&request));
512    EXPECT_NE((void*)NULL, request);
513
514    /*FIXME: dont need this later, at which point the above should become an
515             ASSERT_NE*/
516    if(request == NULL) request = allocate_camera_metadata(10, 100);
517
518    // set the output streams to just this stream ID
519
520    // wow what a verbose API.
521    uint8_t allStreams[] = { streamId, depthStreamId };
522    // IMPORTANT. bad things will happen if its not a uint8.
523    size_t streamCount = sizeof(allStreams) / sizeof(allStreams[0]);
524    camera_metadata_entry_t entry;
525    uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS);
526    int find = find_camera_metadata_entry(request, tag, &entry);
527    if (find == -ENOENT) {
528        if (add_camera_metadata_entry(request, tag, &allStreams,
529                                      /*data_count*/streamCount) != OK) {
530            camera_metadata_t *tmp = allocate_camera_metadata(1000, 10000);
531            ASSERT_OK(append_camera_metadata(tmp, request));
532            free_camera_metadata(request);
533            request = tmp;
534
535            ASSERT_OK(add_camera_metadata_entry(request, tag, &allStreams,
536                                                /*data_count*/streamCount));
537        }
538    } else {
539        ASSERT_OK(update_camera_metadata_entry(request, entry.index,
540                  &allStreams, /*data_count*/streamCount, &entry));
541    }
542
543    EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true));
544
545    dout << "will sleep now for " << mDisplaySecs << std::endl;
546    sleep(mDisplaySecs);
547
548    free_camera_metadata(request);
549
550    for (int i = 0; i < streamCount; ++i) {
551        EXPECT_OK(mCamera->deleteStream(allStreams[i]));
552    }
553    EXPECT_OK(mCamera->exclusiveUnlock());
554}
555
556TEST_F(ProCameraTest, CpuConsumerSingle) {
557    if (HasFatalFailure()) {
558        return;
559    }
560
561    mListener->SetEventMask(ProEvent_Mask(BUFFER_RECEIVED));
562
563    int streamId = -1;
564    EXPECT_OK(mCamera->createStreamCpu(/*width*/320, /*height*/240,
565        TEST_FORMAT_DEPTH, TEST_CPU_HEAP_COUNT, &streamId));
566    EXPECT_NE(-1, streamId);
567
568    EXPECT_OK(mCamera->exclusiveTryLock());
569    EXPECT_EQ(OK, mListener->WaitForEvent());
570    EXPECT_EQ(ACQUIRED, mListener->ReadEvent());
571    /* iterate in a loop submitting requests every frame.
572     *  what kind of requests doesnt really matter, just whatever.
573     */
574
575    // it would probably be better to use CameraMetadata from camera service.
576    camera_metadata_t *request = NULL;
577    EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
578        /*out*/&request));
579    EXPECT_NE((void*)NULL, request);
580
581    /*FIXME: dont need this later, at which point the above should become an
582      ASSERT_NE*/
583    if(request == NULL) request = allocate_camera_metadata(10, 100);
584
585    // set the output streams to just this stream ID
586
587    uint8_t allStreams[] = { streamId };
588    camera_metadata_entry_t entry;
589    uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS);
590    int find = find_camera_metadata_entry(request, tag, &entry);
591    if (find == -ENOENT) {
592        if (add_camera_metadata_entry(request, tag, &allStreams,
593                /*data_count*/1) != OK) {
594            camera_metadata_t *tmp = allocate_camera_metadata(1000, 10000);
595            ASSERT_OK(append_camera_metadata(tmp, request));
596            free_camera_metadata(request);
597            request = tmp;
598
599            ASSERT_OK(add_camera_metadata_entry(request, tag, &allStreams,
600                /*data_count*/1));
601        }
602    } else {
603        ASSERT_OK(update_camera_metadata_entry(request, entry.index,
604            &allStreams, /*data_count*/1, &entry));
605    }
606
607    EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true));
608
609    // Consume a couple of frames
610    for (int i = 0; i < TEST_CPU_FRAME_COUNT; ++i) {
611        EXPECT_EQ(OK, mListener->WaitForEvent());
612        EXPECT_EQ(BUFFER_RECEIVED, mListener->ReadEvent());
613    }
614
615    // Done: clean up
616    free_camera_metadata(request);
617    EXPECT_OK(mCamera->deleteStream(streamId));
618    EXPECT_OK(mCamera->exclusiveUnlock());
619}
620
621TEST_F(ProCameraTest, CpuConsumerDual) {
622    if (HasFatalFailure()) {
623        return;
624    }
625
626    mListener->SetEventMask(ProEvent_Mask(BUFFER_RECEIVED));
627
628    int streamId = -1;
629    EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960,
630                            TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT, &streamId));
631    EXPECT_NE(-1, streamId);
632
633    int depthStreamId = -1;
634    EXPECT_OK(mCamera->createStreamCpu(/*width*/320, /*height*/240,
635                     TEST_FORMAT_DEPTH, TEST_CPU_HEAP_COUNT, &depthStreamId));
636    EXPECT_NE(-1, depthStreamId);
637
638    EXPECT_OK(mCamera->exclusiveTryLock());
639    /*
640    */
641    /* iterate in a loop submitting requests every frame.
642     *  what kind of requests doesnt really matter, just whatever.
643     */
644
645    // it would probably be better to use CameraMetadata from camera service.
646    camera_metadata_t *request = NULL;
647    EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
648                                            /*out*/&request));
649    EXPECT_NE((void*)NULL, request);
650
651    if(request == NULL) request = allocate_camera_metadata(10, 100);
652
653    // set the output streams to just this stream ID
654
655    // wow what a verbose API.
656    uint8_t allStreams[] = { streamId, depthStreamId };
657    size_t streamCount = 2;
658    camera_metadata_entry_t entry;
659    uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS);
660    int find = find_camera_metadata_entry(request, tag, &entry);
661    if (find == -ENOENT) {
662        if (add_camera_metadata_entry(request, tag, &allStreams,
663                                      /*data_count*/streamCount) != OK) {
664            camera_metadata_t *tmp = allocate_camera_metadata(1000, 10000);
665            ASSERT_OK(append_camera_metadata(tmp, request));
666            free_camera_metadata(request);
667            request = tmp;
668
669            ASSERT_OK(add_camera_metadata_entry(request, tag, &allStreams,
670                                                   /*data_count*/streamCount));
671        }
672    } else {
673        ASSERT_OK(update_camera_metadata_entry(request, entry.index,
674                              &allStreams, /*data_count*/streamCount, &entry));
675    }
676
677    EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true));
678
679    // Consume a couple of frames
680    for (int i = 0; i < TEST_CPU_FRAME_COUNT; ++i) {
681        // stream id 1
682        EXPECT_EQ(OK, mListener->WaitForEvent());
683        EXPECT_EQ(BUFFER_RECEIVED, mListener->ReadEvent());
684
685        // stream id 2
686        EXPECT_EQ(OK, mListener->WaitForEvent());
687        EXPECT_EQ(BUFFER_RECEIVED, mListener->ReadEvent());
688
689        //TODO: events should be a struct with some data like the stream id
690    }
691
692    // Done: clean up
693    free_camera_metadata(request);
694    EXPECT_OK(mCamera->deleteStream(streamId));
695    EXPECT_OK(mCamera->exclusiveUnlock());
696}
697
698TEST_F(ProCameraTest, ResultReceiver) {
699    if (HasFatalFailure()) {
700        return;
701    }
702
703    mListener->SetEventMask(ProEvent_Mask(RESULT_RECEIVED));
704    //FIXME: if this is run right after the previous test we get BUFFER_RECEIVED
705    // need to filter out events at read time
706
707    int streamId = -1;
708    EXPECT_OK(mCamera->createStreamCpu(/*width*/1280, /*height*/960,
709                             TEST_FORMAT_MAIN, TEST_CPU_HEAP_COUNT, &streamId));
710    EXPECT_NE(-1, streamId);
711
712    EXPECT_OK(mCamera->exclusiveTryLock());
713    /*
714    */
715    /* iterate in a loop submitting requests every frame.
716     *  what kind of requests doesnt really matter, just whatever.
717     */
718
719    camera_metadata_t *request = NULL;
720    EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
721                                            /*out*/&request));
722    EXPECT_NE((void*)NULL, request);
723
724    /*FIXME*/
725    if(request == NULL) request = allocate_camera_metadata(10, 100);
726
727    // set the output streams to just this stream ID
728
729    uint8_t allStreams[] = { streamId };
730    size_t streamCount = 1;
731    camera_metadata_entry_t entry;
732    uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS);
733    int find = find_camera_metadata_entry(request, tag, &entry);
734    if (find == -ENOENT) {
735        if (add_camera_metadata_entry(request, tag, &allStreams,
736                                      /*data_count*/streamCount) != OK) {
737            camera_metadata_t *tmp = allocate_camera_metadata(1000, 10000);
738            ASSERT_OK(append_camera_metadata(tmp, request));
739            free_camera_metadata(request);
740            request = tmp;
741
742            ASSERT_OK(add_camera_metadata_entry(request, tag, &allStreams,
743                                                /*data_count*/streamCount));
744        }
745    } else {
746        ASSERT_OK(update_camera_metadata_entry(request, entry.index,
747                               &allStreams, /*data_count*/streamCount, &entry));
748    }
749
750    EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true));
751
752    // Consume a couple of results
753    for (int i = 0; i < TEST_CPU_FRAME_COUNT; ++i) {
754        EXPECT_EQ(OK, mListener->WaitForEvent());
755        EXPECT_EQ(RESULT_RECEIVED, mListener->ReadEvent());
756    }
757
758    // Done: clean up
759    free_camera_metadata(request);
760    EXPECT_OK(mCamera->deleteStream(streamId));
761    EXPECT_OK(mCamera->exclusiveUnlock());
762}
763
764}
765}
766}
767}
768
769