1 /* 2 * Copyright 2018 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 <media/NdkImageReader.h> 19 #include <media/NdkImage.h> 20 #include <private/media/NdkImage.h> 21 #include <mediautils/AImageReaderUtils.h> 22 #include <gui/IGraphicBufferProducer.h> 23 #include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h> 24 #include <NdkImageReaderPriv.h> 25 #include <vndk/hardware_buffer.h> 26 #include <memory> 27 28 namespace android { 29 30 using HGraphicBufferProducer = hardware::graphics::bufferqueue::V1_0:: 31 IGraphicBufferProducer; 32 using hardware::graphics::bufferqueue::V1_0::utils::H2BGraphicBufferProducer; 33 using aimg::AImageReader_getHGBPFromHandle; 34 35 typedef IGraphicBufferProducer::QueueBufferInput QueueBufferInput; 36 typedef IGraphicBufferProducer::QueueBufferOutput QueueBufferOutput; 37 38 static constexpr uint64_t kImageBufferUsage = 39 AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN; 40 static constexpr int kImageWidth = 640; 41 static constexpr int kImageHeight = 480; 42 static constexpr int kImageFormat = AIMAGE_FORMAT_RGBA_8888; 43 static constexpr int kMaxImages = 1; 44 45 static constexpr int64_t kQueueBufferInputTimeStamp = 1384888611; 46 static constexpr bool kQueueBufferInputIsAutoTimeStamp = false; 47 static constexpr android_dataspace kQueueBufferInputDataspace = HAL_DATASPACE_UNKNOWN; 48 static const Rect kQueueBufferInputRect = Rect(kImageWidth, kImageHeight); 49 static constexpr int kQueueBufferInputScalingMode = 0; 50 static constexpr int kQueueBufferInputTransform = 0; 51 static const sp<Fence> kQueueBufferInputFence = Fence::NO_FENCE; 52 53 static constexpr int kOnImageAvailableWaitUs = 100 * 1000; 54 55 class AImageReaderWindowHandleTest : public ::testing::Test { 56 public: 57 void SetUp() override { 58 AImageReader_newWithUsage(kImageWidth, kImageHeight, kImageFormat, 59 kImageBufferUsage , kMaxImages, &imageReader_); 60 media_status_t ret = AMEDIA_ERROR_UNKNOWN; 61 ASSERT_NE(imageReader_, nullptr); 62 ret = AImageReader_setImageListener(imageReader_, 63 &imageReaderAvailableCb_); 64 ASSERT_EQ(ret, AMEDIA_OK); 65 ret = AImageReader_setBufferRemovedListener(imageReader_, 66 &imageReaderDetachedCb_); 67 ASSERT_EQ(ret, AMEDIA_OK); 68 } 69 void TearDown() override { 70 if (imageReader_) { 71 AImageReader_delete(imageReader_); 72 } 73 } 74 75 void HandleImageAvailable() { 76 AImage *outImage = nullptr; 77 media_status_t ret = AMEDIA_OK; 78 auto imageDeleter = [](AImage *img) { AImage_delete(img); }; 79 std::unique_ptr<AImage, decltype(imageDeleter)> img(nullptr, imageDeleter); 80 81 // Test that the image can be acquired. 82 ret = AImageReader_acquireNextImage(imageReader_, &outImage); 83 ASSERT_EQ(ret, AMEDIA_OK); 84 img.reset(outImage); 85 ASSERT_NE(img, nullptr); 86 87 // Test that we can get a handle to the image's hardware buffer and a 88 // native handle to it. 89 AHardwareBuffer *hardwareBuffer = nullptr; 90 ret = AImage_getHardwareBuffer(img.get(), &hardwareBuffer); 91 ASSERT_EQ(ret, AMEDIA_OK); 92 ASSERT_NE(hardwareBuffer, nullptr); 93 const native_handle_t *nh = AHardwareBuffer_getNativeHandle(hardwareBuffer); 94 ASSERT_NE(nh, nullptr); 95 std::unique_lock<std::mutex> lock(imageAvailableMutex_); 96 imageAvailable_ = true; 97 imageCondVar_.notify_one(); 98 } 99 100 static void onImageAvailable(void *context, AImageReader *reader) { 101 (void)reader; 102 AImageReaderWindowHandleTest *thisContext = 103 reinterpret_cast<AImageReaderWindowHandleTest *>(context); 104 thisContext->HandleImageAvailable(); 105 } 106 107 static void onBufferRemoved(void *, AImageReader *, AHardwareBuffer *) { 108 } 109 110 AImageReader *imageReader_ = nullptr; 111 AImageReader_ImageListener imageReaderAvailableCb_{this, onImageAvailable}; 112 AImageReader_BufferRemovedListener imageReaderDetachedCb_{this, onBufferRemoved}; 113 std::mutex imageAvailableMutex_; 114 std::condition_variable imageCondVar_; 115 bool imageAvailable_ = false; 116 }; 117 118 static void fillRGBA8Buffer(uint8_t* buf, int w, int h, int stride) { 119 const size_t PIXEL_SIZE = 4; 120 for (int x = 0; x < w; x++) { 121 for (int y = 0; y < h; y++) { 122 off_t offset = (y * stride + x) * PIXEL_SIZE; 123 for (int c = 0; c < 4; c++) { 124 int parityX = (x / (1 << (c+2))) & 1; 125 int parityY = (y / (1 << (c+2))) & 1; 126 buf[offset + c] = (parityX ^ parityY) ? 231 : 35; 127 } 128 } 129 } 130 } 131 132 TEST_F(AImageReaderWindowHandleTest, CreateWindowNativeHandle) { 133 // Check that we can create a native_handle_t corresponding to the 134 // AImageReader. 135 native_handle_t *nh = nullptr; 136 AImageReader_getWindowNativeHandle(imageReader_, &nh); 137 ASSERT_NE(nh, nullptr); 138 139 // Check that there are only ints in the handle. 140 ASSERT_EQ(nh->numFds, 0); 141 ASSERT_NE(nh->numInts, 0); 142 143 // Check that the HGBP can be retrieved from the handle. 144 sp<HGraphicBufferProducer> hgbp = AImageReader_getHGBPFromHandle(nh); 145 ASSERT_NE(hgbp, nullptr); 146 sp<IGraphicBufferProducer> igbp = new H2BGraphicBufferProducer(hgbp); 147 int dequeuedSlot = -1; 148 sp<Fence> dequeuedFence; 149 IGraphicBufferProducer::QueueBufferOutput output; 150 ASSERT_EQ(OK, igbp->connect(nullptr, NATIVE_WINDOW_API_CPU, false, &output)); 151 152 // Test that we can dequeue a buffer. 153 ASSERT_EQ(OK, 154 ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION & 155 (igbp->dequeueBuffer(&dequeuedSlot, &dequeuedFence, 156 kImageWidth, kImageHeight, 157 kImageFormat, kImageBufferUsage, 158 nullptr, nullptr))); 159 EXPECT_LE(0, dequeuedSlot); 160 EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, dequeuedSlot); 161 162 sp<GraphicBuffer> dequeuedBuffer; 163 igbp->requestBuffer(dequeuedSlot, &dequeuedBuffer); 164 uint8_t* img = nullptr; 165 ASSERT_EQ(NO_ERROR, dequeuedBuffer->lock(kImageBufferUsage, (void**)(&img))); 166 167 // Write in some dummy image data. 168 fillRGBA8Buffer(img, dequeuedBuffer->getWidth(), dequeuedBuffer->getHeight(), 169 dequeuedBuffer->getStride()); 170 ASSERT_EQ(NO_ERROR, dequeuedBuffer->unlock()); 171 QueueBufferInput queueBufferInput(kQueueBufferInputTimeStamp, 172 kQueueBufferInputIsAutoTimeStamp, 173 kQueueBufferInputDataspace, 174 kQueueBufferInputRect, 175 kQueueBufferInputScalingMode, 176 kQueueBufferInputTransform, 177 kQueueBufferInputFence); 178 QueueBufferOutput queueBufferOutput; 179 ASSERT_EQ(OK, igbp->queueBuffer(dequeuedSlot, queueBufferInput, 180 &queueBufferOutput)); 181 // wait until the onImageAvailable callback is called, or timeout completes. 182 std::unique_lock<std::mutex> lock(imageAvailableMutex_); 183 imageCondVar_.wait_for(lock, std::chrono::microseconds(kOnImageAvailableWaitUs), 184 [this]{ return this->imageAvailable_;}); 185 EXPECT_TRUE(imageAvailable_) << "Timed out waiting for image data to be handled!\n"; 186 } 187 188 class AImageReaderPrivateFormatTest : public ::testing::Test { 189 public: 190 void SetUp() override { 191 auto status = AImageReader_new(kImageWidth, kImageHeight, AIMAGE_FORMAT_RAW_DEPTH, 192 kMaxImages, &imgReader); 193 EXPECT_TRUE(status == AMEDIA_OK); 194 } 195 196 void TearDown() override { 197 if (imgReader) { 198 AImageReader_delete(imgReader); 199 } 200 } 201 AImageReader *imgReader = nullptr; 202 }; 203 204 TEST_F(AImageReaderPrivateFormatTest, CreateTest) { 205 EXPECT_TRUE(imgReader != nullptr); 206 } 207 208 209 } // namespace android 210