1/*
2 * Copyright (C) 2012 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_TAG "CpuConsumer_test"
18//#define LOG_NDEBUG 0
19//#define LOG_NNDEBUG 0
20
21#ifdef LOG_NNDEBUG
22#define ALOGVV(...) ALOGV(__VA_ARGS__)
23#else
24#define ALOGVV(...) ((void)0)
25#endif
26
27#include <gtest/gtest.h>
28#include <gui/CpuConsumer.h>
29#include <gui/Surface.h>
30#include <ui/GraphicBuffer.h>
31#include <utils/String8.h>
32#include <utils/Thread.h>
33#include <utils/Mutex.h>
34#include <utils/Condition.h>
35
36#include <thread>
37#include <vector>
38#define CPU_CONSUMER_TEST_FORMAT_RAW 0
39#define CPU_CONSUMER_TEST_FORMAT_Y8 0
40#define CPU_CONSUMER_TEST_FORMAT_Y16 0
41#define CPU_CONSUMER_TEST_FORMAT_RGBA_8888 1
42
43namespace android {
44
45struct CpuConsumerTestParams {
46    uint32_t width;
47    uint32_t height;
48    int maxLockedBuffers;
49    PixelFormat format;
50};
51
52::std::ostream& operator<<(::std::ostream& os, const CpuConsumerTestParams& p) {
53    return os << "[ (" << p.width << ", " << p.height << "), B:"
54              << p.maxLockedBuffers << ", F:0x"
55              << ::std::hex << p.format << "]";
56}
57
58class CpuConsumerTest : public ::testing::TestWithParam<CpuConsumerTestParams> {
59protected:
60
61    virtual void SetUp() {
62        const ::testing::TestInfo* const test_info =
63                ::testing::UnitTest::GetInstance()->current_test_info();
64        CpuConsumerTestParams params = GetParam();
65        ALOGV("** Starting test %s (%d x %d, %d, 0x%x)",
66                test_info->name(),
67                params.width, params.height,
68                params.maxLockedBuffers, params.format);
69        sp<IGraphicBufferProducer> producer;
70        sp<IGraphicBufferConsumer> consumer;
71        BufferQueue::createBufferQueue(&producer, &consumer);
72        mCC = new CpuConsumer(consumer, params.maxLockedBuffers);
73        String8 name("CpuConsumer_Under_Test");
74        mCC->setName(name);
75        mSTC = new Surface(producer);
76        mANW = mSTC;
77    }
78
79    virtual void TearDown() {
80        mANW.clear();
81        mSTC.clear();
82        mCC.clear();
83    }
84
85    class FrameWaiter : public CpuConsumer::FrameAvailableListener {
86    public:
87        FrameWaiter():
88                mPendingFrames(0) {
89        }
90
91        void waitForFrame() {
92            Mutex::Autolock lock(mMutex);
93            while (mPendingFrames == 0) {
94                mCondition.wait(mMutex);
95            }
96            mPendingFrames--;
97        }
98
99        virtual void onFrameAvailable(const BufferItem&) {
100            Mutex::Autolock lock(mMutex);
101            mPendingFrames++;
102            mCondition.signal();
103        }
104
105        int mPendingFrames;
106        Mutex mMutex;
107        Condition mCondition;
108    };
109
110    // Note that SurfaceTexture will lose the notifications
111    // onBuffersReleased and onFrameAvailable as there is currently
112    // no way to forward the events.  This DisconnectWaiter will not let the
113    // disconnect finish until finishDisconnect() is called.  It will
114    // also block until a disconnect is called
115    class DisconnectWaiter : public BufferQueue::ConsumerListener {
116    public:
117        DisconnectWaiter () :
118            mWaitForDisconnect(false),
119            mPendingFrames(0) {
120        }
121
122        void waitForFrame() {
123            Mutex::Autolock lock(mMutex);
124            while (mPendingFrames == 0) {
125                mFrameCondition.wait(mMutex);
126            }
127            mPendingFrames--;
128        }
129
130        virtual void onFrameAvailable(const BufferItem&) {
131            Mutex::Autolock lock(mMutex);
132            mPendingFrames++;
133            mFrameCondition.signal();
134        }
135
136        virtual void onBuffersReleased() {
137            Mutex::Autolock lock(mMutex);
138            while (!mWaitForDisconnect) {
139                mDisconnectCondition.wait(mMutex);
140            }
141        }
142
143        void finishDisconnect() {
144            Mutex::Autolock lock(mMutex);
145            mWaitForDisconnect = true;
146            mDisconnectCondition.signal();
147        }
148
149    private:
150        Mutex mMutex;
151
152        bool mWaitForDisconnect;
153        Condition mDisconnectCondition;
154
155        int mPendingFrames;
156        Condition mFrameCondition;
157    };
158
159    sp<CpuConsumer> mCC;
160    sp<Surface> mSTC;
161    sp<ANativeWindow> mANW;
162};
163
164#define ASSERT_NO_ERROR(err, msg) \
165    ASSERT_EQ(NO_ERROR, err) << (msg) << strerror(-(err))
166
167void checkPixel(const CpuConsumer::LockedBuffer &buf,
168        uint32_t x, uint32_t y, uint32_t r, uint32_t g=0, uint32_t b=0) {
169    // Ignores components that don't exist for given pixel
170    switch(buf.format) {
171        case HAL_PIXEL_FORMAT_RAW16: {
172            String8 msg;
173            uint16_t *bPtr = (uint16_t*)buf.data;
174            bPtr += y * buf.stride + x;
175            // GRBG Bayer mosaic; only check the matching channel
176            switch( ((y & 1) << 1) | (x & 1) ) {
177                case 0: // G
178                case 3: // G
179                    EXPECT_EQ(g, *bPtr);
180                    break;
181                case 1: // R
182                    EXPECT_EQ(r, *bPtr);
183                    break;
184                case 2: // B
185                    EXPECT_EQ(b, *bPtr);
186                    break;
187            }
188            break;
189        }
190        // ignores g,b
191        case HAL_PIXEL_FORMAT_Y8: {
192            uint8_t *bPtr = (uint8_t*)buf.data;
193            bPtr += y * buf.stride + x;
194            EXPECT_EQ(r, *bPtr) << "at x = " << x << " y = " << y;
195            break;
196        }
197        // ignores g,b
198        case HAL_PIXEL_FORMAT_Y16: {
199            // stride is in pixels, not in bytes
200            uint16_t *bPtr = ((uint16_t*)buf.data) + y * buf.stride + x;
201
202            EXPECT_EQ(r, *bPtr) << "at x = " << x << " y = " << y;
203            break;
204        }
205        case HAL_PIXEL_FORMAT_RGBA_8888: {
206            const int bytesPerPixel = 4;
207            uint8_t *bPtr = (uint8_t*)buf.data;
208            bPtr += (y * buf.stride + x) * bytesPerPixel;
209
210            EXPECT_EQ(r, bPtr[0]) << "at x = " << x << " y = " << y;
211            EXPECT_EQ(g, bPtr[1]) << "at x = " << x << " y = " << y;
212            EXPECT_EQ(b, bPtr[2]) << "at x = " << x << " y = " << y;
213            break;
214        }
215        default: {
216            ADD_FAILURE() << "Unknown format for check:" << buf.format;
217            break;
218        }
219    }
220}
221
222// Fill a YV12 buffer with a multi-colored checkerboard pattern
223void fillYV12Buffer(uint8_t* buf, int w, int h, int stride);
224
225// Fill a Y8/Y16 buffer with a multi-colored checkerboard pattern
226template <typename T> // T == uint8_t or uint16_t
227void fillGreyscaleBuffer(T* buf, int w, int h, int stride, int bpp) {
228    const int blockWidth = w > 16 ? w / 16 : 1;
229    const int blockHeight = h > 16 ? h / 16 : 1;
230    const int yuvTexOffsetY = 0;
231
232    ASSERT_TRUE(bpp == 8 || bpp == 16);
233    ASSERT_TRUE(sizeof(T)*8 == bpp);
234
235    // stride is in pixels, not in bytes
236    int yuvTexStrideY = stride;
237    for (int x = 0; x < w; x++) {
238        for (int y = 0; y < h; y++) {
239            int parityX = (x / blockWidth) & 1;
240            int parityY = (y / blockHeight) & 1;
241            T intensity = (parityX ^ parityY) ? 63 : 191;
242            buf[yuvTexOffsetY + (y * yuvTexStrideY) + x] = intensity;
243        }
244    }
245}
246
247inline uint8_t chooseColorRgba8888(int blockX, int blockY, uint8_t channel) {
248    const int colorVariations = 3;
249    uint8_t color = ((blockX % colorVariations) + (blockY % colorVariations))
250                        % (colorVariations) == channel ? 191: 63;
251
252    return color;
253}
254
255// Fill a RGBA8888 buffer with a multi-colored checkerboard pattern
256void fillRgba8888Buffer(uint8_t* buf, int w, int h, int stride)
257{
258    const int blockWidth = w > 16 ? w / 16 : 1;
259    const int blockHeight = h > 16 ? h / 16 : 1;
260    const int bytesPerPixel = 4;
261
262    // stride is in pixels, not in bytes
263    for (int x = 0; x < w; ++x) {
264        for (int y = 0; y < h; ++y) {
265            int blockX = (x / blockWidth);
266            int blockY = (y / blockHeight);
267
268            uint8_t r = chooseColorRgba8888(blockX, blockY, 0);
269            uint8_t g = chooseColorRgba8888(blockX, blockY, 1);
270            uint8_t b = chooseColorRgba8888(blockX, blockY, 2);
271
272            buf[(y*stride + x)*bytesPerPixel + 0] = r;
273            buf[(y*stride + x)*bytesPerPixel + 1] = g;
274            buf[(y*stride + x)*bytesPerPixel + 2] = b;
275            buf[(y*stride + x)*bytesPerPixel + 3] = 255;
276        }
277    }
278}
279
280// Fill a RAW sensor buffer with a multi-colored checkerboard pattern.
281// Assumes GRBG mosaic ordering. Result should be a grid in a 2x2 pattern
282// of [ R, B; G, W]
283void fillBayerRawBuffer(uint8_t* buf, int w, int h, int stride) {
284    ALOGVV("fillBayerRawBuffer: %p with %d x %d, stride %d", buf, w, h ,stride);
285    // Blocks need to be even-width/height, aim for 8-wide otherwise
286    const int blockWidth = (w > 16 ? w / 8 : 2) & ~0x1;
287    const int blockHeight = (h > 16 ? h / 8 : 2) & ~0x1;
288    for (int y = 0; y < h; y+=2) {
289        uint16_t *bPtr1 = ((uint16_t*)buf) + stride*y;
290        uint16_t *bPtr2 = bPtr1 + stride;
291        for (int x = 0; x < w; x+=2) {
292            int blockX = (x / blockWidth ) & 1;
293            int blockY = (y / blockHeight) & 1;
294            unsigned short r = (blockX == blockY) ? 1000 : 200;
295            unsigned short g = blockY ? 1000: 200;
296            unsigned short b = blockX ? 1000: 200;
297            // GR row
298            *bPtr1++ = g;
299            *bPtr1++ = r;
300            // BG row
301            *bPtr2++ = b;
302            *bPtr2++ = g;
303        }
304    }
305
306}
307
308template<typename T> // uint8_t or uint16_t
309void checkGreyscaleBuffer(const CpuConsumer::LockedBuffer &buf) {
310    uint32_t w = buf.width;
311    uint32_t h = buf.height;
312    const int blockWidth = w > 16 ? w / 16 : 1;
313    const int blockHeight = h > 16 ? h / 16 : 1;
314
315    // Top-left square is bright
316    checkPixel(buf, 0, 0, 191);
317    checkPixel(buf, 1, 0, 191);
318    checkPixel(buf, 0, 1, 191);
319    checkPixel(buf, 1, 1, 191);
320
321    // One-right square is dark
322    checkPixel(buf, blockWidth,     0, 63);
323    checkPixel(buf, blockWidth + 1, 0, 63);
324    checkPixel(buf, blockWidth,     1, 63);
325    checkPixel(buf, blockWidth + 1, 1, 63);
326
327    // One-down square is dark
328    checkPixel(buf, 0, blockHeight, 63);
329    checkPixel(buf, 1, blockHeight, 63);
330    checkPixel(buf, 0, blockHeight + 1, 63);
331    checkPixel(buf, 1, blockHeight + 1, 63);
332
333    // One-diag square is bright
334    checkPixel(buf, blockWidth,     blockHeight, 191);
335    checkPixel(buf, blockWidth + 1, blockHeight, 191);
336    checkPixel(buf, blockWidth,     blockHeight + 1, 191);
337    checkPixel(buf, blockWidth + 1, blockHeight + 1, 191);
338
339    // Test bottom-right pixel
340    const int maxBlockX = ((w-1 + (blockWidth-1)) / blockWidth) & 0x1;
341    const int maxBlockY = ((h-1 + (blockHeight-1)) / blockHeight) & 0x1;
342    uint32_t pixelValue = ((maxBlockX % 2) == (maxBlockY % 2)) ? 191 : 63;
343    checkPixel(buf, w-1, h-1, pixelValue);
344}
345
346void checkRgba8888Buffer(const CpuConsumer::LockedBuffer &buf) {
347    uint32_t w = buf.width;
348    uint32_t h = buf.height;
349    const int blockWidth = w > 16 ? w / 16 : 1;
350    const int blockHeight = h > 16 ? h / 16 : 1;
351
352    // Top-left square is bright red
353    checkPixel(buf, 0, 0, 191, 63, 63);
354    checkPixel(buf, 1, 0, 191, 63, 63);
355    checkPixel(buf, 0, 1, 191, 63, 63);
356    checkPixel(buf, 1, 1, 191, 63, 63);
357
358    // One-right square is bright green
359    checkPixel(buf, blockWidth,     0, 63, 191, 63);
360    checkPixel(buf, blockWidth + 1, 0, 63, 191, 63);
361    checkPixel(buf, blockWidth,     1, 63, 191, 63);
362    checkPixel(buf, blockWidth + 1, 1, 63, 191, 63);
363
364    // One-down square is bright green
365    checkPixel(buf, 0, blockHeight, 63, 191, 63);
366    checkPixel(buf, 1, blockHeight, 63, 191, 63);
367    checkPixel(buf, 0, blockHeight + 1, 63, 191, 63);
368    checkPixel(buf, 1, blockHeight + 1, 63, 191, 63);
369
370    // One-diag square is bright blue
371    checkPixel(buf, blockWidth,     blockHeight, 63, 63, 191);
372    checkPixel(buf, blockWidth + 1, blockHeight, 63, 63, 191);
373    checkPixel(buf, blockWidth,     blockHeight + 1, 63, 63, 191);
374    checkPixel(buf, blockWidth + 1, blockHeight + 1, 63, 63, 191);
375
376    // Test bottom-right pixel
377    {
378        const int maxBlockX = ((w-1) / blockWidth);
379        const int maxBlockY = ((h-1) / blockHeight);
380        uint8_t r = chooseColorRgba8888(maxBlockX, maxBlockY, 0);
381        uint8_t g = chooseColorRgba8888(maxBlockX, maxBlockY, 1);
382        uint8_t b = chooseColorRgba8888(maxBlockX, maxBlockY, 2);
383        checkPixel(buf, w-1, h-1, r, g, b);
384    }
385}
386
387void checkBayerRawBuffer(const CpuConsumer::LockedBuffer &buf) {
388    uint32_t w = buf.width;
389    uint32_t h = buf.height;
390    const int blockWidth = (w > 16 ? w / 8 : 2) & ~0x1;
391    const int blockHeight = (h > 16 ? h / 8 : 2) & ~0x1;
392
393    // Top-left square is red
394    checkPixel(buf, 0, 0, 1000, 200, 200);
395    checkPixel(buf, 1, 0, 1000, 200, 200);
396    checkPixel(buf, 0, 1, 1000, 200, 200);
397    checkPixel(buf, 1, 1, 1000, 200, 200);
398
399    // One-right square is blue
400    checkPixel(buf, blockWidth,     0, 200, 200, 1000);
401    checkPixel(buf, blockWidth + 1, 0, 200, 200, 1000);
402    checkPixel(buf, blockWidth,     1, 200, 200, 1000);
403    checkPixel(buf, blockWidth + 1, 1, 200, 200, 1000);
404
405    // One-down square is green
406    checkPixel(buf, 0, blockHeight, 200, 1000, 200);
407    checkPixel(buf, 1, blockHeight, 200, 1000, 200);
408    checkPixel(buf, 0, blockHeight + 1, 200, 1000, 200);
409    checkPixel(buf, 1, blockHeight + 1, 200, 1000, 200);
410
411    // One-diag square is white
412    checkPixel(buf, blockWidth,     blockHeight, 1000, 1000, 1000);
413    checkPixel(buf, blockWidth + 1, blockHeight, 1000, 1000, 1000);
414    checkPixel(buf, blockWidth,     blockHeight + 1, 1000, 1000, 1000);
415    checkPixel(buf, blockWidth + 1, blockHeight + 1, 1000, 1000, 1000);
416
417    // Test bottom-right pixel
418    const int maxBlockX = ((w-1) / blockWidth) & 0x1;
419    const int maxBlockY = ((w-1) / blockHeight) & 0x1;
420    unsigned short maxR = (maxBlockX == maxBlockY) ? 1000 : 200;
421    unsigned short maxG = maxBlockY ? 1000: 200;
422    unsigned short maxB = maxBlockX ? 1000: 200;
423    checkPixel(buf, w-1, h-1, maxR, maxG, maxB);
424}
425
426void checkAnyBuffer(const CpuConsumer::LockedBuffer &buf, int format) {
427    switch (format) {
428        case HAL_PIXEL_FORMAT_RAW16:
429            checkBayerRawBuffer(buf);
430            break;
431        case HAL_PIXEL_FORMAT_Y8:
432            checkGreyscaleBuffer<uint8_t>(buf);
433            break;
434        case HAL_PIXEL_FORMAT_Y16:
435            checkGreyscaleBuffer<uint16_t>(buf);
436            break;
437        case HAL_PIXEL_FORMAT_RGBA_8888:
438            checkRgba8888Buffer(buf);
439            break;
440    }
441}
442
443// Configures the ANativeWindow producer-side interface based on test parameters
444void configureANW(const sp<ANativeWindow>& anw,
445        const CpuConsumerTestParams& params,
446        int maxBufferSlack) {
447    status_t err;
448    err = native_window_api_connect(anw.get(), NATIVE_WINDOW_API_CPU);
449    ASSERT_NO_ERROR(err, "connect error: ");
450
451    err = native_window_set_buffers_dimensions(anw.get(),
452            params.width, params.height);
453    ASSERT_NO_ERROR(err, "set_buffers_dimensions error: ");
454
455    err = native_window_set_buffers_format(anw.get(), params.format);
456    ASSERT_NO_ERROR(err, "set_buffers_format error: ");
457
458    err = native_window_set_usage(anw.get(),
459            GRALLOC_USAGE_SW_WRITE_OFTEN);
460    ASSERT_NO_ERROR(err, "set_usage error: ");
461
462    int minUndequeuedBuffers;
463    err = anw.get()->query(anw.get(),
464            NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
465            &minUndequeuedBuffers);
466    ASSERT_NO_ERROR(err, "query error: ");
467
468    ALOGVV("Setting buffer count to %d",
469            maxBufferSlack + 1 + minUndequeuedBuffers);
470    err = native_window_set_buffer_count(anw.get(),
471            maxBufferSlack + 1 + minUndequeuedBuffers);
472    ASSERT_NO_ERROR(err, "set_buffer_count error: ");
473
474}
475
476// Produce one frame of image data; assumes format and resolution configuration
477// is already done.
478void produceOneFrame(const sp<ANativeWindow>& anw,
479        const CpuConsumerTestParams& params,
480        int64_t timestamp, uint32_t *stride) {
481    status_t err;
482    ANativeWindowBuffer* anb;
483    ALOGVV("Dequeue buffer from %p", anw.get());
484    err = native_window_dequeue_buffer_and_wait(anw.get(), &anb);
485    ASSERT_NO_ERROR(err, "dequeueBuffer error: ");
486
487    ASSERT_TRUE(anb != NULL);
488
489    sp<GraphicBuffer> buf(GraphicBuffer::from(anb));
490
491    *stride = buf->getStride();
492    uint8_t* img = NULL;
493
494    ALOGVV("Lock buffer from %p for write", anw.get());
495    err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
496    ASSERT_NO_ERROR(err, "lock error: ");
497
498    switch (params.format) {
499        case HAL_PIXEL_FORMAT_YV12:
500            fillYV12Buffer(img, params.width, params.height, *stride);
501            break;
502        case HAL_PIXEL_FORMAT_RAW16:
503            fillBayerRawBuffer(img, params.width, params.height, buf->getStride());
504            break;
505        case HAL_PIXEL_FORMAT_Y8:
506            fillGreyscaleBuffer<uint8_t>(img, params.width, params.height,
507                                         buf->getStride(), /*bpp*/8);
508            break;
509        case HAL_PIXEL_FORMAT_Y16:
510            fillGreyscaleBuffer<uint16_t>((uint16_t*)img, params.width,
511                                          params.height, buf->getStride(),
512                                          /*bpp*/16);
513            break;
514        case HAL_PIXEL_FORMAT_RGBA_8888:
515            fillRgba8888Buffer(img, params.width, params.height, buf->getStride());
516            break;
517        default:
518            FAIL() << "Unknown pixel format under test!";
519            break;
520    }
521    ALOGVV("Unlock buffer from %p", anw.get());
522    err = buf->unlock();
523    ASSERT_NO_ERROR(err, "unlock error: ");
524
525    ALOGVV("Set timestamp to %p", anw.get());
526    err = native_window_set_buffers_timestamp(anw.get(), timestamp);
527    ASSERT_NO_ERROR(err, "set_buffers_timestamp error: ");
528
529    ALOGVV("Queue buffer to %p", anw.get());
530    err = anw->queueBuffer(anw.get(), buf->getNativeBuffer(), -1);
531    ASSERT_NO_ERROR(err, "queueBuffer error:");
532};
533
534// This test is disabled because the HAL_PIXEL_FORMAT_RAW16 format is not
535// supported on all devices.
536TEST_P(CpuConsumerTest, FromCpuSingle) {
537    status_t err;
538    CpuConsumerTestParams params = GetParam();
539
540    // Set up
541
542    ASSERT_NO_FATAL_FAILURE(configureANW(mANW, params, 1));
543
544    // Produce
545
546    const int64_t time = 12345678L;
547    uint32_t stride;
548    ASSERT_NO_FATAL_FAILURE(produceOneFrame(mANW, params, time,
549                    &stride));
550
551    // Consume
552
553    CpuConsumer::LockedBuffer b;
554    err = mCC->lockNextBuffer(&b);
555    ASSERT_NO_ERROR(err, "getNextBuffer error: ");
556
557    ASSERT_TRUE(b.data != NULL);
558    EXPECT_EQ(params.width,  b.width);
559    EXPECT_EQ(params.height, b.height);
560    EXPECT_EQ(params.format, b.format);
561    EXPECT_EQ(stride, b.stride);
562    EXPECT_EQ(time, b.timestamp);
563
564    checkAnyBuffer(b, GetParam().format);
565    mCC->unlockBuffer(b);
566}
567
568// This test is disabled because the HAL_PIXEL_FORMAT_RAW16 format is not
569// supported on all devices.
570TEST_P(CpuConsumerTest, FromCpuManyInQueue) {
571    status_t err;
572    CpuConsumerTestParams params = GetParam();
573
574    const int numInQueue = 5;
575    // Set up
576
577    ASSERT_NO_FATAL_FAILURE(configureANW(mANW, params, numInQueue));
578
579    // Produce
580
581    const int64_t time[numInQueue] = { 1L, 2L, 3L, 4L, 5L};
582    uint32_t stride[numInQueue];
583
584    for (int i = 0; i < numInQueue; i++) {
585        ALOGV("Producing frame %d", i);
586        ASSERT_NO_FATAL_FAILURE(produceOneFrame(mANW, params, time[i],
587                        &stride[i]));
588    }
589
590    // Consume
591
592    for (int i = 0; i < numInQueue; i++) {
593        ALOGV("Consuming frame %d", i);
594        CpuConsumer::LockedBuffer b;
595        err = mCC->lockNextBuffer(&b);
596        ASSERT_NO_ERROR(err, "getNextBuffer error: ");
597
598        ASSERT_TRUE(b.data != NULL);
599        EXPECT_EQ(params.width,  b.width);
600        EXPECT_EQ(params.height, b.height);
601        EXPECT_EQ(params.format, b.format);
602        EXPECT_EQ(stride[i], b.stride);
603        EXPECT_EQ(time[i], b.timestamp);
604
605        checkAnyBuffer(b, GetParam().format);
606
607        mCC->unlockBuffer(b);
608    }
609}
610
611// This test is disabled because the HAL_PIXEL_FORMAT_RAW16 format is not
612// supported on all devices.
613TEST_P(CpuConsumerTest, FromCpuLockMax) {
614    status_t err;
615    CpuConsumerTestParams params = GetParam();
616
617    // Set up
618
619    ASSERT_NO_FATAL_FAILURE(configureANW(mANW, params, params.maxLockedBuffers + 1));
620
621    // Produce
622
623    const int64_t time = 1234L;
624    uint32_t stride;
625
626    for (int i = 0; i < params.maxLockedBuffers + 1; i++) {
627        ALOGV("Producing frame %d", i);
628        ASSERT_NO_FATAL_FAILURE(produceOneFrame(mANW, params, time,
629                        &stride));
630    }
631
632    // Consume
633
634    std::vector<CpuConsumer::LockedBuffer> b(params.maxLockedBuffers);
635    for (int i = 0; i < params.maxLockedBuffers; i++) {
636        ALOGV("Locking frame %d", i);
637        err = mCC->lockNextBuffer(&b[i]);
638        ASSERT_NO_ERROR(err, "getNextBuffer error: ");
639
640        ASSERT_TRUE(b[i].data != NULL);
641        EXPECT_EQ(params.width,  b[i].width);
642        EXPECT_EQ(params.height, b[i].height);
643        EXPECT_EQ(params.format, b[i].format);
644        EXPECT_EQ(stride, b[i].stride);
645        EXPECT_EQ(time, b[i].timestamp);
646
647        checkAnyBuffer(b[i], GetParam().format);
648    }
649
650    ALOGV("Locking frame %d (too many)", params.maxLockedBuffers);
651    CpuConsumer::LockedBuffer bTooMuch;
652    err = mCC->lockNextBuffer(&bTooMuch);
653    ASSERT_TRUE(err == NOT_ENOUGH_DATA) << "Allowing too many locks";
654
655    ALOGV("Unlocking frame 0");
656    err = mCC->unlockBuffer(b[0]);
657    ASSERT_NO_ERROR(err, "Could not unlock buffer 0: ");
658
659    ALOGV("Locking frame %d (should work now)", params.maxLockedBuffers);
660    err = mCC->lockNextBuffer(&bTooMuch);
661    ASSERT_NO_ERROR(err, "Did not allow new lock after unlock");
662
663    ASSERT_TRUE(bTooMuch.data != NULL);
664    EXPECT_EQ(params.width,  bTooMuch.width);
665    EXPECT_EQ(params.height, bTooMuch.height);
666    EXPECT_EQ(params.format, bTooMuch.format);
667    EXPECT_EQ(stride, bTooMuch.stride);
668    EXPECT_EQ(time, bTooMuch.timestamp);
669
670    checkAnyBuffer(bTooMuch, GetParam().format);
671
672    ALOGV("Unlocking extra buffer");
673    err = mCC->unlockBuffer(bTooMuch);
674    ASSERT_NO_ERROR(err, "Could not unlock extra buffer: ");
675
676    ALOGV("Locking frame %d (no more available)", params.maxLockedBuffers + 1);
677    err = mCC->lockNextBuffer(&b[0]);
678    ASSERT_EQ(BAD_VALUE, err) << "Not out of buffers somehow";
679
680    for (int i = 1; i < params.maxLockedBuffers; i++) {
681        mCC->unlockBuffer(b[i]);
682    }
683}
684
685TEST_P(CpuConsumerTest, FromCpuInvalid) {
686    status_t err = mCC->lockNextBuffer(nullptr);
687    ASSERT_EQ(BAD_VALUE, err) << "lockNextBuffer did not fail";
688
689    CpuConsumer::LockedBuffer b;
690    err = mCC->unlockBuffer(b);
691    ASSERT_EQ(BAD_VALUE, err) << "unlockBuffer did not fail";
692}
693
694TEST_P(CpuConsumerTest, FromCpuMultiThread) {
695    CpuConsumerTestParams params = GetParam();
696    ASSERT_NO_FATAL_FAILURE(configureANW(mANW, params, params.maxLockedBuffers + 1));
697
698    for (int i = 0; i < 10; i++) {
699        std::atomic<int> threadReadyCount(0);
700        auto lockAndUnlock = [&]() {
701            threadReadyCount++;
702            // busy wait
703            while (threadReadyCount < params.maxLockedBuffers + 1);
704
705            CpuConsumer::LockedBuffer b;
706            status_t err = mCC->lockNextBuffer(&b);
707            if (err == NO_ERROR) {
708                usleep(1000);
709                err = mCC->unlockBuffer(b);
710                ASSERT_NO_ERROR(err, "Could not unlock buffer: ");
711            } else if (err == NOT_ENOUGH_DATA) {
712                // there are params.maxLockedBuffers+1 threads so one of the
713                // threads might get this error
714            } else {
715                FAIL() << "Could not lock buffer";
716            }
717        };
718
719        // produce buffers
720        for (int j = 0; j < params.maxLockedBuffers + 1; j++) {
721            const int64_t time = 1234L;
722            uint32_t stride;
723            ASSERT_NO_FATAL_FAILURE(produceOneFrame(mANW, params, time, &stride));
724        }
725
726        // spawn threads
727        std::vector<std::thread> threads;
728        for (int j = 0; j < params.maxLockedBuffers + 1; j++) {
729            threads.push_back(std::thread(lockAndUnlock));
730        }
731
732        // join threads
733        for (auto& thread : threads) {
734            thread.join();
735        }
736
737        // we produced N+1 buffers, but the threads might only consume N
738        CpuConsumer::LockedBuffer b;
739        if (mCC->lockNextBuffer(&b) == NO_ERROR) {
740            mCC->unlockBuffer(b);
741        }
742
743        if (HasFatalFailure()) {
744            break;
745        }
746    }
747}
748
749CpuConsumerTestParams y8TestSets[] = {
750    { 512,   512, 1, HAL_PIXEL_FORMAT_Y8},
751    { 512,   512, 3, HAL_PIXEL_FORMAT_Y8},
752    { 2608, 1960, 1, HAL_PIXEL_FORMAT_Y8},
753    { 2608, 1960, 3, HAL_PIXEL_FORMAT_Y8},
754    { 100,   100, 1, HAL_PIXEL_FORMAT_Y8},
755    { 100,   100, 3, HAL_PIXEL_FORMAT_Y8},
756};
757
758CpuConsumerTestParams y16TestSets[] = {
759    { 512,   512, 1, HAL_PIXEL_FORMAT_Y16},
760    { 512,   512, 3, HAL_PIXEL_FORMAT_Y16},
761    { 2608, 1960, 1, HAL_PIXEL_FORMAT_Y16},
762    { 2608, 1960, 3, HAL_PIXEL_FORMAT_Y16},
763    { 100,   100, 1, HAL_PIXEL_FORMAT_Y16},
764    { 100,   100, 3, HAL_PIXEL_FORMAT_Y16},
765};
766
767CpuConsumerTestParams rawTestSets[] = {
768    { 512,   512, 1, HAL_PIXEL_FORMAT_RAW16},
769    { 512,   512, 3, HAL_PIXEL_FORMAT_RAW16},
770    { 2608, 1960, 1, HAL_PIXEL_FORMAT_RAW16},
771    { 2608, 1960, 3, HAL_PIXEL_FORMAT_RAW16},
772    { 100,   100, 1, HAL_PIXEL_FORMAT_RAW16},
773    { 100,   100, 3, HAL_PIXEL_FORMAT_RAW16},
774};
775
776CpuConsumerTestParams rgba8888TestSets[] = {
777    { 512,   512, 1, HAL_PIXEL_FORMAT_RGBA_8888},
778    { 512,   512, 3, HAL_PIXEL_FORMAT_RGBA_8888},
779    { 2608, 1960, 1, HAL_PIXEL_FORMAT_RGBA_8888},
780    { 2608, 1960, 3, HAL_PIXEL_FORMAT_RGBA_8888},
781    { 100,   100, 1, HAL_PIXEL_FORMAT_RGBA_8888},
782    { 100,   100, 3, HAL_PIXEL_FORMAT_RGBA_8888},
783};
784
785#if CPU_CONSUMER_TEST_FORMAT_Y8
786INSTANTIATE_TEST_CASE_P(Y8Tests,
787        CpuConsumerTest,
788        ::testing::ValuesIn(y8TestSets));
789#endif
790
791#if CPU_CONSUMER_TEST_FORMAT_Y16
792INSTANTIATE_TEST_CASE_P(Y16Tests,
793        CpuConsumerTest,
794        ::testing::ValuesIn(y16TestSets));
795#endif
796
797#if CPU_CONSUMER_TEST_FORMAT_RAW
798INSTANTIATE_TEST_CASE_P(RawTests,
799        CpuConsumerTest,
800        ::testing::ValuesIn(rawTestSets));
801#endif
802
803#if CPU_CONSUMER_TEST_FORMAT_RGBA_8888
804INSTANTIATE_TEST_CASE_P(Rgba8888Tests,
805        CpuConsumerTest,
806        ::testing::ValuesIn(rgba8888TestSets));
807#endif
808
809
810
811} // namespace android
812