1/*
2 * Copyright (C) 2016 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 "VtsHalGraphicsMapperV2_0TargetTest"
18
19#include <VtsHalHidlTargetTestBase.h>
20#include <android-base/logging.h>
21#include <sync/sync.h>
22#include "VtsHalGraphicsMapperTestUtils.h"
23
24namespace android {
25namespace hardware {
26namespace graphics {
27namespace mapper {
28namespace V2_0 {
29namespace tests {
30namespace {
31
32using android::hardware::graphics::common::V1_0::BufferUsage;
33using android::hardware::graphics::common::V1_0::PixelFormat;
34
35class GraphicsMapperHidlTest : public ::testing::VtsHalHidlTargetTestBase {
36 protected:
37  void SetUp() override {
38      ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
39
40      mDummyDescriptorInfo.width = 64;
41      mDummyDescriptorInfo.height = 64;
42      mDummyDescriptorInfo.layerCount = 1;
43      mDummyDescriptorInfo.format = PixelFormat::RGBA_8888;
44      mDummyDescriptorInfo.usage = static_cast<uint64_t>(
45          BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
46  }
47
48  void TearDown() override {}
49
50  std::unique_ptr<Gralloc> mGralloc;
51  IMapper::BufferDescriptorInfo mDummyDescriptorInfo{};
52};
53
54/**
55 * Test IAllocator::dumpDebugInfo by calling it.
56 */
57TEST_F(GraphicsMapperHidlTest, AllocatorDumpDebugInfo) {
58    mGralloc->dumpDebugInfo();
59}
60
61/**
62 * Test IAllocator::allocate with valid buffer descriptors.
63 */
64TEST_F(GraphicsMapperHidlTest, AllocatorAllocate) {
65    BufferDescriptor descriptor;
66    ASSERT_NO_FATAL_FAILURE(
67        descriptor = mGralloc->createDescriptor(mDummyDescriptorInfo));
68
69    for (uint32_t count = 0; count < 5; count++) {
70        std::vector<const native_handle_t*> bufferHandles;
71        uint32_t stride;
72        ASSERT_NO_FATAL_FAILURE(bufferHandles = mGralloc->allocate(
73                                    descriptor, count, false, &stride));
74
75        if (count >= 1) {
76            EXPECT_LE(mDummyDescriptorInfo.width, stride)
77                << "invalid buffer stride";
78        }
79
80        for (auto bufferHandle : bufferHandles) {
81            mGralloc->freeBuffer(bufferHandle);
82        }
83    }
84}
85
86/**
87 * Test IAllocator::allocate with invalid buffer descriptors.
88 */
89TEST_F(GraphicsMapperHidlTest, AllocatorAllocateNegative) {
90    // this assumes any valid descriptor is non-empty
91    BufferDescriptor descriptor;
92    mGralloc->getAllocator()->allocate(
93        descriptor, 1, [&](const auto& tmpError, const auto&, const auto&) {
94            EXPECT_EQ(Error::BAD_DESCRIPTOR, tmpError);
95        });
96}
97
98/**
99 * Test IAllocator::allocate does not leak.
100 */
101TEST_F(GraphicsMapperHidlTest, AllocatorAllocateNoLeak) {
102    auto info = mDummyDescriptorInfo;
103    info.width = 1024;
104    info.height = 1024;
105
106    for (int i = 0; i < 2048; i++) {
107        auto bufferHandle = mGralloc->allocate(info, false);
108        mGralloc->freeBuffer(bufferHandle);
109    }
110}
111
112/**
113 * Test IMapper::createDescriptor with valid descriptor info.
114 */
115TEST_F(GraphicsMapperHidlTest, CreateDescriptorBasic) {
116    ASSERT_NO_FATAL_FAILURE(mGralloc->createDescriptor(mDummyDescriptorInfo));
117}
118
119/**
120 * Test IMapper::createDescriptor with invalid descriptor info.
121 */
122TEST_F(GraphicsMapperHidlTest, CreateDescriptorNegative) {
123    auto info = mDummyDescriptorInfo;
124    info.width = 0;
125    mGralloc->getMapper()->createDescriptor(
126        info, [&](const auto& tmpError, const auto&) {
127            EXPECT_EQ(Error::BAD_VALUE, tmpError)
128                << "createDescriptor did not fail with BAD_VALUE";
129        });
130}
131
132/**
133 * Test IMapper::importBuffer and IMapper::freeBuffer with allocated buffers.
134 */
135TEST_F(GraphicsMapperHidlTest, ImportFreeBufferBasic) {
136    const native_handle_t* bufferHandle;
137    ASSERT_NO_FATAL_FAILURE(bufferHandle =
138                                mGralloc->allocate(mDummyDescriptorInfo, true));
139    ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(bufferHandle));
140}
141
142/**
143 * Test IMapper::importBuffer and IMapper::freeBuffer with cloned buffers.
144 */
145TEST_F(GraphicsMapperHidlTest, ImportFreeBufferClone) {
146    const native_handle_t* clonedBufferHandle;
147    ASSERT_NO_FATAL_FAILURE(
148        clonedBufferHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
149
150    // A cloned handle is a raw handle. Check that we can import it multiple
151    // times.
152    const native_handle_t* importedBufferHandles[2];
153    ASSERT_NO_FATAL_FAILURE(importedBufferHandles[0] =
154                                mGralloc->importBuffer(clonedBufferHandle));
155    ASSERT_NO_FATAL_FAILURE(importedBufferHandles[1] =
156                                mGralloc->importBuffer(clonedBufferHandle));
157    ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(importedBufferHandles[0]));
158    ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(importedBufferHandles[1]));
159
160    ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(clonedBufferHandle));
161}
162
163/**
164 * Test IMapper::importBuffer and IMapper::freeBuffer cross mapper instances.
165 */
166TEST_F(GraphicsMapperHidlTest, ImportFreeBufferSingleton) {
167    const native_handle_t* rawHandle;
168    ASSERT_NO_FATAL_FAILURE(
169        rawHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
170
171    native_handle_t* importedHandle = nullptr;
172    mGralloc->getMapper()->importBuffer(
173        rawHandle, [&](const auto& tmpError, const auto& buffer) {
174            ASSERT_EQ(Error::NONE, tmpError);
175            importedHandle = static_cast<native_handle_t*>(buffer);
176        });
177
178    // free the imported handle with another mapper
179    std::unique_ptr<Gralloc> anotherGralloc;
180    ASSERT_NO_FATAL_FAILURE(anotherGralloc = std::make_unique<Gralloc>());
181    Error error = mGralloc->getMapper()->freeBuffer(importedHandle);
182    ASSERT_EQ(Error::NONE, error);
183
184    ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(rawHandle));
185}
186
187/**
188 * Test IMapper::importBuffer and IMapper::freeBuffer do not leak.
189 */
190TEST_F(GraphicsMapperHidlTest, ImportFreeBufferNoLeak) {
191    auto info = mDummyDescriptorInfo;
192    info.width = 1024;
193    info.height = 1024;
194
195    for (int i = 0; i < 2048; i++) {
196        auto bufferHandle = mGralloc->allocate(info, true);
197        mGralloc->freeBuffer(bufferHandle);
198    }
199}
200
201/**
202 * Test IMapper::importBuffer with invalid buffers.
203 */
204TEST_F(GraphicsMapperHidlTest, ImportBufferNegative) {
205    native_handle_t* invalidHandle = nullptr;
206    mGralloc->getMapper()->importBuffer(
207        invalidHandle, [&](const auto& tmpError, const auto&) {
208            EXPECT_EQ(Error::BAD_BUFFER, tmpError)
209                << "importBuffer with nullptr did not fail with BAD_BUFFER";
210        });
211
212    invalidHandle = native_handle_create(0, 0);
213    mGralloc->getMapper()->importBuffer(invalidHandle, [&](const auto& tmpError,
214                                                           const auto&) {
215        EXPECT_EQ(Error::BAD_BUFFER, tmpError)
216            << "importBuffer with invalid handle did not fail with BAD_BUFFER";
217    });
218    native_handle_delete(invalidHandle);
219}
220
221/**
222 * Test IMapper::freeBuffer with invalid buffers.
223 */
224TEST_F(GraphicsMapperHidlTest, FreeBufferNegative) {
225    native_handle_t* invalidHandle = nullptr;
226    Error error = mGralloc->getMapper()->freeBuffer(invalidHandle);
227    EXPECT_EQ(Error::BAD_BUFFER, error)
228        << "freeBuffer with nullptr did not fail with BAD_BUFFER";
229
230    invalidHandle = native_handle_create(0, 0);
231    error = mGralloc->getMapper()->freeBuffer(invalidHandle);
232    EXPECT_EQ(Error::BAD_BUFFER, error)
233        << "freeBuffer with invalid handle did not fail with BAD_BUFFER";
234    native_handle_delete(invalidHandle);
235
236    const native_handle_t* clonedBufferHandle;
237    ASSERT_NO_FATAL_FAILURE(
238        clonedBufferHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
239    error = mGralloc->getMapper()->freeBuffer(invalidHandle);
240    EXPECT_EQ(Error::BAD_BUFFER, error)
241        << "freeBuffer with un-imported handle did not fail with BAD_BUFFER";
242
243    mGralloc->freeBuffer(clonedBufferHandle);
244}
245
246/**
247 * Test IMapper::lock and IMapper::unlock.
248 */
249TEST_F(GraphicsMapperHidlTest, LockUnlockBasic) {
250    const auto& info = mDummyDescriptorInfo;
251
252    const native_handle_t* bufferHandle;
253    uint32_t stride;
254    ASSERT_NO_FATAL_FAILURE(bufferHandle =
255                                mGralloc->allocate(info, true, &stride));
256
257    // lock buffer for writing
258    const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
259                               static_cast<int32_t>(info.height)};
260    int fence = -1;
261    uint8_t* data;
262    ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(mGralloc->lock(
263                                bufferHandle, info.usage, region, fence)));
264
265    // RGBA_8888
266    size_t strideInBytes = stride * 4;
267    size_t writeInBytes = info.width * 4;
268
269    for (uint32_t y = 0; y < info.height; y++) {
270        memset(data, y, writeInBytes);
271        data += strideInBytes;
272    }
273
274    ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
275
276    // lock again for reading
277    ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(mGralloc->lock(
278                                bufferHandle, info.usage, region, fence)));
279    for (uint32_t y = 0; y < info.height; y++) {
280        for (size_t i = 0; i < writeInBytes; i++) {
281            EXPECT_EQ(static_cast<uint8_t>(y), data[i]);
282        }
283        data += strideInBytes;
284    }
285
286    ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
287    if (fence >= 0) {
288        close(fence);
289    }
290}
291
292/**
293 * Test IMapper::lockYCbCr.  This locks a YV12 buffer, and makes sure we can
294 * write to and read from it.
295 */
296TEST_F(GraphicsMapperHidlTest, LockYCbCrBasic) {
297    auto info = mDummyDescriptorInfo;
298    info.format = PixelFormat::YV12;
299
300    const native_handle_t* bufferHandle;
301    uint32_t stride;
302    ASSERT_NO_FATAL_FAILURE(bufferHandle =
303                                mGralloc->allocate(info, true, &stride));
304
305    // lock buffer for writing
306    const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
307                               static_cast<int32_t>(info.height)};
308    int fence = -1;
309    YCbCrLayout layout;
310    ASSERT_NO_FATAL_FAILURE(
311        layout = mGralloc->lockYCbCr(bufferHandle, info.usage, region, fence));
312
313    auto yData = static_cast<uint8_t*>(layout.y);
314    auto cbData = static_cast<uint8_t*>(layout.cb);
315    auto crData = static_cast<uint8_t*>(layout.cr);
316    for (uint32_t y = 0; y < info.height; y++) {
317        for (uint32_t x = 0; x < info.width; x++) {
318            auto val = static_cast<uint8_t>(info.height * y + x);
319
320            yData[layout.yStride * y + x] = val;
321            if (y % 2 == 0 && x % 2 == 0) {
322                cbData[layout.cStride * y / 2 + x / 2] = val;
323                crData[layout.cStride * y / 2 + x / 2] = val;
324            }
325        }
326    }
327
328    ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
329
330    // lock again for reading
331    ASSERT_NO_FATAL_FAILURE(
332        layout = mGralloc->lockYCbCr(bufferHandle, info.usage, region, fence));
333
334    yData = static_cast<uint8_t*>(layout.y);
335    cbData = static_cast<uint8_t*>(layout.cb);
336    crData = static_cast<uint8_t*>(layout.cr);
337    for (uint32_t y = 0; y < info.height; y++) {
338        for (uint32_t x = 0; x < info.width; x++) {
339            auto val = static_cast<uint8_t>(info.height * y + x);
340
341            EXPECT_EQ(val, yData[layout.yStride * y + x]);
342            if (y % 2 == 0 && x % 2 == 0) {
343                EXPECT_EQ(val, cbData[layout.cStride * y / 2 + x / 2]);
344                EXPECT_EQ(val, crData[layout.cStride * y / 2 + x / 2]);
345            }
346        }
347    }
348
349    ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
350    if (fence >= 0) {
351        close(fence);
352    }
353}
354
355/**
356 * Test IMapper::unlock with invalid buffers.
357 */
358TEST_F(GraphicsMapperHidlTest, UnlockNegative) {
359    native_handle_t* invalidHandle = nullptr;
360    mGralloc->getMapper()->unlock(
361        invalidHandle, [&](const auto& tmpError, const auto&) {
362            EXPECT_EQ(Error::BAD_BUFFER, tmpError)
363                << "unlock with nullptr did not fail with BAD_BUFFER";
364        });
365
366    invalidHandle = native_handle_create(0, 0);
367    mGralloc->getMapper()->unlock(
368        invalidHandle, [&](const auto& tmpError, const auto&) {
369            EXPECT_EQ(Error::BAD_BUFFER, tmpError)
370                << "unlock with invalid handle did not fail with BAD_BUFFER";
371        });
372    native_handle_delete(invalidHandle);
373
374    ASSERT_NO_FATAL_FAILURE(invalidHandle =
375                                const_cast<native_handle_t*>(mGralloc->allocate(
376                                    mDummyDescriptorInfo, false)));
377    mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError,
378                                                     const auto&) {
379        EXPECT_EQ(Error::BAD_BUFFER, tmpError)
380            << "unlock with un-imported handle did not fail with BAD_BUFFER";
381    });
382    mGralloc->freeBuffer(invalidHandle);
383
384// disabled as it fails on many existing drivers
385#if 0
386  ASSERT_NO_FATAL_FAILURE(invalidHandle = const_cast<native_handle_t*>(
387                              mGralloc->allocate(mDummyDescriptorInfo, true)));
388  mGralloc->getMapper()->unlock(
389      invalidHandle, [&](const auto& tmpError, const auto&) {
390        EXPECT_EQ(Error::BAD_BUFFER, tmpError)
391            << "unlock with unlocked handle did not fail with BAD_BUFFER";
392      });
393  mGralloc->freeBuffer(invalidHandle);
394#endif
395}
396
397}  // namespace
398}  // namespace tests
399}  // namespace V2_0
400}  // namespace mapper
401}  // namespace graphics
402}  // namespace hardware
403}  // namespace android
404
405int main(int argc, char** argv) {
406  ::testing::InitGoogleTest(&argc, argv);
407
408  int status = RUN_ALL_TESTS();
409  LOG(INFO) << "Test result = " << status;
410
411  return status;
412}
413