xref: /aosp_15_r20/frameworks/av/media/ndk/NdkImageReader.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
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 #include <inttypes.h>
18 
19 //#define LOG_NDEBUG 0
20 #define LOG_TAG "NdkImageReader"
21 
22 #include "NdkImagePriv.h"
23 #include "NdkImageReaderPriv.h"
24 
25 #include <android_media_Utils.h>
26 #include <com_android_graphics_libgui_flags.h>
27 #include <grallocusage/GrallocUsageConversion.h>
28 #include <gui/bufferqueue/1.0/WGraphicBufferProducer.h>
29 #include <private/android/AHardwareBufferHelpers.h>
30 #include <ui/PublicFormat.h>
31 #include <utils/Log.h>
32 
33 #include <cutils/atomic.h>
34 
35 using namespace android;
36 
37 namespace {
38     // Get an ID that's unique within this process.
createProcessUniqueId()39     static int32_t createProcessUniqueId() {
40         static volatile int32_t globalCounter = 0;
41         return android_atomic_inc(&globalCounter);
42     }
43 }
44 
45 const char* AImageReader::kCallbackFpKey = "Callback";
46 const char* AImageReader::kContextKey    = "Context";
47 const char* AImageReader::kGraphicBufferKey = "GraphicBuffer";
48 
49 static constexpr int kWindowHalTokenSizeMax = 256;
50 
51 static media_status_t validateParameters(int32_t width, int32_t height, int32_t format,
52                                          uint64_t usage, int32_t maxImages,
53                                          /*out*/ AImageReader**& reader);
54 static native_handle_t *convertHalTokenToNativeHandle(const HalToken &halToken);
55 
56 bool
isSupportedFormatAndUsage(int32_t format,uint64_t usage)57 AImageReader::isSupportedFormatAndUsage(int32_t format, uint64_t usage) {
58     // Check whether usage has either CPU_READ_OFTEN or CPU_READ set. Note that check against
59     // AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN (0x6) is sufficient as it implies
60     // AHARDWAREBUFFER_USAGE_CPU_READ (0x2).
61     bool hasCpuUsage = usage & AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN;
62     switch (format) {
63         case AIMAGE_FORMAT_RGBA_8888:
64         case AIMAGE_FORMAT_RGBX_8888:
65         case AIMAGE_FORMAT_RGB_888:
66         case AIMAGE_FORMAT_RGB_565:
67         case AIMAGE_FORMAT_RGBA_FP16:
68         case AIMAGE_FORMAT_YUV_420_888:
69         case AIMAGE_FORMAT_JPEG:
70         case AIMAGE_FORMAT_RAW16:
71         case AIMAGE_FORMAT_RAW_DEPTH:
72         case AIMAGE_FORMAT_RAW_PRIVATE:
73         case AIMAGE_FORMAT_RAW10:
74         case AIMAGE_FORMAT_RAW12:
75         case AIMAGE_FORMAT_DEPTH16:
76         case AIMAGE_FORMAT_DEPTH_POINT_CLOUD:
77         case AIMAGE_FORMAT_Y8:
78         case AIMAGE_FORMAT_HEIC:
79         case AIMAGE_FORMAT_DEPTH_JPEG:
80         case AIMAGE_FORMAT_RAW_DEPTH10:
81         case HAL_PIXEL_FORMAT_YCBCR_P010:
82             return true;
83         case AIMAGE_FORMAT_PRIVATE:
84             // For private format, cpu usage is prohibited.
85             return !hasCpuUsage;
86         default:
87             return false;
88     }
89 }
90 
91 int
getNumPlanesForFormat(int32_t format)92 AImageReader::getNumPlanesForFormat(int32_t format) {
93     switch (format) {
94         case AIMAGE_FORMAT_YUV_420_888:
95         case HAL_PIXEL_FORMAT_YCBCR_P010:
96             return 3;
97         case AIMAGE_FORMAT_RGBA_8888:
98         case AIMAGE_FORMAT_RGBX_8888:
99         case AIMAGE_FORMAT_RGB_888:
100         case AIMAGE_FORMAT_RGB_565:
101         case AIMAGE_FORMAT_RGBA_FP16:
102         case AIMAGE_FORMAT_JPEG:
103         case AIMAGE_FORMAT_RAW16:
104         case AIMAGE_FORMAT_RAW_DEPTH:
105         case AIMAGE_FORMAT_RAW_PRIVATE:
106         case AIMAGE_FORMAT_RAW10:
107         case AIMAGE_FORMAT_RAW12:
108         case AIMAGE_FORMAT_DEPTH16:
109         case AIMAGE_FORMAT_DEPTH_POINT_CLOUD:
110         case AIMAGE_FORMAT_Y8:
111         case AIMAGE_FORMAT_HEIC:
112         case AIMAGE_FORMAT_DEPTH_JPEG:
113         case AIMAGE_FORMAT_RAW_DEPTH10:
114             return 1;
115         case AIMAGE_FORMAT_PRIVATE:
116             return 0;
117         default:
118             return -1;
119     }
120 }
121 
122 void
onFrameAvailable(const BufferItem &)123 AImageReader::FrameListener::onFrameAvailable(const BufferItem& /*item*/) {
124     sp<AImageReader> reader = mReader.promote();
125     if (reader == nullptr) {
126         ALOGW("A frame is available after AImageReader closed!");
127         return; // reader has been closed
128     }
129     Mutex::Autolock _l(mLock);
130     if (mListener.onImageAvailable == nullptr) {
131         return; // No callback registered
132     }
133 
134     sp<AMessage> msg = new AMessage(AImageReader::kWhatImageAvailable, reader->mHandler);
135     msg->setPointer(AImageReader::kCallbackFpKey, (void *) mListener.onImageAvailable);
136     msg->setPointer(AImageReader::kContextKey, mListener.context);
137     msg->post();
138 }
139 
140 media_status_t
setImageListener(AImageReader_ImageListener * listener)141 AImageReader::FrameListener::setImageListener(AImageReader_ImageListener* listener) {
142     Mutex::Autolock _l(mLock);
143     if (listener == nullptr) {
144         mListener.context = nullptr;
145         mListener.onImageAvailable = nullptr;
146     } else {
147         mListener = *listener;
148     }
149     return AMEDIA_OK;
150 }
151 
152 void
onBufferFreed(const wp<GraphicBuffer> & graphicBuffer)153 AImageReader::BufferRemovedListener::onBufferFreed(const wp<GraphicBuffer>& graphicBuffer) {
154     sp<AImageReader> reader = mReader.promote();
155     if (reader == nullptr) {
156         ALOGW("A frame is available after AImageReader closed!");
157         return; // reader has been closed
158     }
159     Mutex::Autolock _l(mLock);
160     if (mListener.onBufferRemoved == nullptr) {
161         return; // No callback registered
162     }
163 
164     sp<GraphicBuffer> gBuffer = graphicBuffer.promote();
165     if (gBuffer == nullptr) {
166         ALOGW("A buffer being freed has gone away!");
167         return; // buffer is already destroyed
168     }
169 
170     sp<AMessage> msg = new AMessage(AImageReader::kWhatBufferRemoved, reader->mHandler);
171     msg->setPointer(
172         AImageReader::kCallbackFpKey, (void*) mListener.onBufferRemoved);
173     msg->setPointer(AImageReader::kContextKey, mListener.context);
174     msg->setObject(AImageReader::kGraphicBufferKey, gBuffer);
175     msg->post();
176 }
177 
178 media_status_t
setBufferRemovedListener(AImageReader_BufferRemovedListener * listener)179 AImageReader::BufferRemovedListener::setBufferRemovedListener(
180     AImageReader_BufferRemovedListener* listener) {
181     Mutex::Autolock _l(mLock);
182     if (listener == nullptr) {
183         mListener.context = nullptr;
184         mListener.onBufferRemoved = nullptr;
185     } else {
186         mListener = *listener;
187     }
188     return AMEDIA_OK;
189 }
190 
191 media_status_t
setImageListenerLocked(AImageReader_ImageListener * listener)192 AImageReader::setImageListenerLocked(AImageReader_ImageListener* listener) {
193     return mFrameListener->setImageListener(listener);
194 }
195 
196 media_status_t
setImageListener(AImageReader_ImageListener * listener)197 AImageReader::setImageListener(AImageReader_ImageListener* listener) {
198     Mutex::Autolock _l(mLock);
199     return setImageListenerLocked(listener);
200 }
201 
202 media_status_t
setBufferRemovedListenerLocked(AImageReader_BufferRemovedListener * listener)203 AImageReader::setBufferRemovedListenerLocked(AImageReader_BufferRemovedListener* listener) {
204     return mBufferRemovedListener->setBufferRemovedListener(listener);
205 }
206 
207 media_status_t
setBufferRemovedListener(AImageReader_BufferRemovedListener * listener)208 AImageReader::setBufferRemovedListener(AImageReader_BufferRemovedListener* listener) {
209     Mutex::Autolock _l(mLock);
210     return setBufferRemovedListenerLocked(listener);
211 }
212 
onMessageReceived(const sp<AMessage> & msg)213 void AImageReader::CallbackHandler::onMessageReceived(
214         const sp<AMessage> &msg) {
215     switch (msg->what()) {
216         case kWhatBufferRemoved:
217         {
218             AImageReader_BufferRemovedCallback onBufferRemoved;
219             void* context;
220             bool found = msg->findPointer(kCallbackFpKey, (void**) &onBufferRemoved);
221             if (!found || onBufferRemoved == nullptr) {
222                 ALOGE("%s: Cannot find onBufferRemoved callback fp!", __FUNCTION__);
223                 return;
224             }
225             found = msg->findPointer(kContextKey, &context);
226             if (!found) {
227                 ALOGE("%s: Cannot find callback context!", __FUNCTION__);
228                 return;
229             }
230             sp<RefBase> bufferToFree;
231             found = msg->findObject(kGraphicBufferKey, &bufferToFree);
232             if (!found || bufferToFree == nullptr) {
233                 ALOGE("%s: Cannot find the buffer to free!", __FUNCTION__);
234                 return;
235             }
236 
237             // TODO(jwcai) Someone from Android graphics team stating this should just be a
238             // static_cast.
239             AHardwareBuffer* outBuffer = reinterpret_cast<AHardwareBuffer*>(bufferToFree.get());
240 
241             // At this point, bufferToFree holds the last reference to the GraphicBuffer owned by
242             // this AImageReader, and the reference will be gone once this function returns.
243             (*onBufferRemoved)(context, mReader, outBuffer);
244             break;
245         }
246         case kWhatImageAvailable:
247         {
248             AImageReader_ImageCallback onImageAvailable;
249             void* context;
250             bool found = msg->findPointer(kCallbackFpKey, (void**) &onImageAvailable);
251             if (!found || onImageAvailable == nullptr) {
252                 ALOGE("%s: Cannot find onImageAvailable callback fp!", __FUNCTION__);
253                 return;
254             }
255             found = msg->findPointer(kContextKey, &context);
256             if (!found) {
257                 ALOGE("%s: Cannot find callback context!", __FUNCTION__);
258                 return;
259             }
260             (*onImageAvailable)(context, mReader);
261             break;
262         }
263         default:
264             ALOGE("%s: unknown message type %d", __FUNCTION__, msg->what());
265             break;
266     }
267 }
268 
AImageReader(int32_t width,int32_t height,int32_t format,uint64_t usage,int32_t maxImages,uint32_t hardwareBufferFormat,android_dataspace dataSpace)269 AImageReader::AImageReader(int32_t width,
270                            int32_t height,
271                            int32_t format,
272                            uint64_t usage,
273                            int32_t maxImages,
274                            uint32_t hardwareBufferFormat,
275                            android_dataspace dataSpace)
276     : mWidth(width),
277       mHeight(height),
278       mFormat(format),
279       mUsage(usage),
280       mMaxImages(maxImages),
281       mNumPlanes(getNumPlanesForFormat(format)),
282       mHalFormat(hardwareBufferFormat),
283       mHalDataSpace(dataSpace),
284       mFrameListener(new FrameListener(this)),
285       mBufferRemovedListener(new BufferRemovedListener(this)) {}
286 
~AImageReader()287 AImageReader::~AImageReader() {
288     Mutex::Autolock _l(mLock);
289     LOG_FATAL_IF(mIsOpen, "AImageReader not closed before destruction");
290 }
291 
292 media_status_t
init()293 AImageReader::init() {
294     mHalUsage = AHardwareBuffer_convertToGrallocUsageBits(mUsage);
295 
296 #if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
297     sp<IGraphicBufferProducer> gbProducer;
298     sp<IGraphicBufferConsumer> gbConsumer;
299     BufferQueue::createBufferQueue(&gbProducer, &gbConsumer);
300 #endif  // !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
301 
302     String8 consumerName = String8::format("ImageReader-%dx%df%xu%" PRIu64 "m%d-%d-%d",
303             mWidth, mHeight, mFormat, mUsage, mMaxImages, getpid(),
304             createProcessUniqueId());
305 
306 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
307     mBufferItemConsumer = new BufferItemConsumer(mHalUsage, mMaxImages, /*controlledByApp*/ true);
308 #else
309     mBufferItemConsumer =
310             new BufferItemConsumer(gbConsumer, mHalUsage, mMaxImages, /*controlledByApp*/ true);
311 #endif  // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
312     if (mBufferItemConsumer == nullptr) {
313         ALOGE("Failed to allocate BufferItemConsumer");
314         return AMEDIA_ERROR_UNKNOWN;
315     }
316 
317 #if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
318     mProducer = gbProducer;
319 #endif  // !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
320     mBufferItemConsumer->setName(consumerName);
321     mBufferItemConsumer->setFrameAvailableListener(mFrameListener);
322     mBufferItemConsumer->setBufferFreedListener(mBufferRemovedListener);
323 
324     status_t res;
325     res = mBufferItemConsumer->setDefaultBufferSize(mWidth, mHeight);
326     if (res != OK) {
327         ALOGE("Failed to set BufferItemConsumer buffer size");
328         return AMEDIA_ERROR_UNKNOWN;
329     }
330     res = mBufferItemConsumer->setDefaultBufferFormat(mHalFormat);
331     if (res != OK) {
332         ALOGE("Failed to set BufferItemConsumer buffer format");
333         return AMEDIA_ERROR_UNKNOWN;
334     }
335     res = mBufferItemConsumer->setDefaultBufferDataSpace(mHalDataSpace);
336     if (res != OK) {
337         ALOGE("Failed to set BufferItemConsumer buffer dataSpace");
338         return AMEDIA_ERROR_UNKNOWN;
339     }
340     if (mUsage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT) {
341 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
342         mBufferItemConsumer->setConsumerIsProtected(true);
343 #else
344         gbConsumer->setConsumerIsProtected(true);
345 #endif  // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
346     }
347 
348 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
349     mSurface = mBufferItemConsumer->getSurface();
350 #else
351     mSurface = new Surface(mProducer, /*controlledByApp*/true);
352 #endif  // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
353     if (mSurface == nullptr) {
354         ALOGE("Failed to create surface");
355         return AMEDIA_ERROR_UNKNOWN;
356     }
357     mWindow = static_cast<ANativeWindow*>(mSurface.get());
358 
359     for (int i = 0; i < mMaxImages; i++) {
360         BufferItem* buffer = new BufferItem;
361         mBuffers.push_back(buffer);
362     }
363 
364     mCbLooper = new ALooper;
365     mCbLooper->setName(consumerName.c_str());
366     res = mCbLooper->start(
367             /*runOnCallingThread*/false,
368             /*canCallJava*/       true,
369             PRIORITY_DEFAULT);
370     if (res != OK) {
371         ALOGE("Failed to start the looper");
372         return AMEDIA_ERROR_UNKNOWN;
373     }
374     mHandler = new CallbackHandler(this);
375     mCbLooper->registerHandler(mHandler);
376     mIsOpen = true;
377     return AMEDIA_OK;
378 }
379 
close()380 void AImageReader::close() {
381     Mutex::Autolock _l(mLock);
382     if (!mIsOpen) {
383         return;
384     }
385     mIsOpen = false;
386     AImageReader_ImageListener nullListener = {nullptr, nullptr};
387     setImageListenerLocked(&nullListener);
388 
389     AImageReader_BufferRemovedListener nullBufferRemovedListener = {nullptr, nullptr};
390     setBufferRemovedListenerLocked(&nullBufferRemovedListener);
391 
392     if (mCbLooper != nullptr) {
393         mCbLooper->unregisterHandler(mHandler->id());
394         mCbLooper->stop();
395     }
396     mCbLooper.clear();
397     mHandler.clear();
398 
399     // Close all previously acquired images
400     for (auto it = mAcquiredImages.begin();
401               it != mAcquiredImages.end(); it++) {
402         AImage* image = *it;
403         Mutex::Autolock _l(image->mLock);
404         // Do not alter mAcquiredImages while we are iterating on it
405         releaseImageLocked(image, /*releaseFenceFd*/-1, /*clearCache*/false);
406     }
407     mAcquiredImages.clear();
408 
409     // Delete Buffer Items
410     for (auto it = mBuffers.begin();
411               it != mBuffers.end(); it++) {
412         delete *it;
413     }
414 
415     if (mBufferItemConsumer != nullptr) {
416         mBufferItemConsumer->abandon();
417         mBufferItemConsumer->setFrameAvailableListener(nullptr);
418     }
419 
420     if (mWindowHandle != nullptr) {
421         int size = mWindowHandle->data[0];
422         hidl_vec<uint8_t> halToken;
423         halToken.setToExternal(
424             reinterpret_cast<uint8_t *>(&mWindowHandle->data[1]), size);
425         deleteHalToken(halToken);
426         native_handle_delete(mWindowHandle);
427     }
428 }
429 
430 media_status_t
acquireImageLocked(AImage ** image,int * acquireFenceFd)431 AImageReader::acquireImageLocked(/*out*/AImage** image, /*out*/int* acquireFenceFd) {
432     *image = nullptr;
433     BufferItem* buffer = getBufferItemLocked();
434     if (buffer == nullptr) {
435         ALOGW("Unable to acquire a lockedBuffer, very likely client tries to lock more than"
436             " maxImages buffers");
437         return AMEDIA_IMGREADER_MAX_IMAGES_ACQUIRED;
438     }
439 
440     // When the output paramter fence is not NULL, we are acquiring the image asynchronously.
441     bool waitForFence = acquireFenceFd == nullptr;
442     status_t res = mBufferItemConsumer->acquireBuffer(buffer, 0, waitForFence);
443 
444     if (res != NO_ERROR) {
445         returnBufferItemLocked(buffer);
446         if (res != BufferQueue::NO_BUFFER_AVAILABLE) {
447             if (res == INVALID_OPERATION) {
448                 return AMEDIA_IMGREADER_MAX_IMAGES_ACQUIRED;
449             } else {
450                 ALOGE("%s: Acquire image failed with some unknown error: %s (%d)",
451                       __FUNCTION__, strerror(-res), res);
452                 return AMEDIA_ERROR_UNKNOWN;
453             }
454         }
455         return AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE;
456     }
457 
458     const int bufferWidth = getBufferWidth(buffer);
459     const int bufferHeight = getBufferHeight(buffer);
460     const int bufferFmt = buffer->mGraphicBuffer->getPixelFormat();
461     const int bufferUsage = buffer->mGraphicBuffer->getUsage();
462 
463     const int readerWidth = mWidth;
464     const int readerHeight = mHeight;
465     const int readerFmt = mHalFormat;
466     const int readerUsage = mHalUsage;
467 
468     // Check if the producer buffer configurations match what AImageReader configured. Add some
469     // extra checks for non-opaque formats.
470     if (!isFormatOpaque(readerFmt)) {
471         // Check if the left-top corner of the crop rect is origin, we currently assume this point
472         // is zero, will revisit this once this assumption turns out problematic.
473         Point lt = buffer->mCrop.leftTop();
474         if (lt.x != 0 || lt.y != 0) {
475             ALOGE("Crop left top corner [%d, %d] not at origin", lt.x, lt.y);
476             return AMEDIA_ERROR_UNKNOWN;
477         }
478 
479         // Check if the producer buffer configurations match what ImageReader configured.
480         ALOGV_IF(readerWidth != bufferWidth || readerHeight != bufferHeight,
481                 "%s: Buffer size: %dx%d, doesn't match AImageReader configured size: %dx%d",
482                 __FUNCTION__, bufferWidth, bufferHeight, readerWidth, readerHeight);
483 
484         // Check if the buffer usage is a super set of reader's usage bits, aka all usage bits that
485         // ImageReader requested has been supported from the producer side.
486         ALOGD_IF((readerUsage | bufferUsage) != bufferUsage,
487                 "%s: Producer buffer usage: %x, doesn't cover all usage bits AImageReader "
488                 "configured: %x",
489                 __FUNCTION__, bufferUsage, readerUsage);
490 
491         if (readerFmt != bufferFmt) {
492             if (readerFmt == HAL_PIXEL_FORMAT_YCbCr_420_888 && isPossiblyYUV(bufferFmt)) {
493                 // Special casing for when producer switches to a format compatible with flexible
494                 // YUV.
495                 mHalFormat = bufferFmt;
496                 ALOGD("%s: Overriding buffer format YUV_420_888 to 0x%x.", __FUNCTION__, bufferFmt);
497             } else {
498                 // Return the buffer to the queue. No need to provide fence, as this buffer wasn't
499                 // used anywhere yet.
500                 mBufferItemConsumer->releaseBuffer(*buffer);
501                 returnBufferItemLocked(buffer);
502 
503                 ALOGE("%s: Output buffer format: 0x%x, ImageReader configured format: 0x%x",
504                         __FUNCTION__, bufferFmt, readerFmt);
505 
506                 return AMEDIA_ERROR_UNKNOWN;
507             }
508         }
509     }
510 
511     if (mHalFormat == HAL_PIXEL_FORMAT_BLOB) {
512         *image = new AImage(this, mFormat, mUsage, buffer, buffer->mTimestamp,
513                 readerWidth, readerHeight, mNumPlanes);
514     } else {
515         *image = new AImage(this, mFormat, mUsage, buffer, buffer->mTimestamp,
516                 bufferWidth, bufferHeight, mNumPlanes);
517     }
518     mAcquiredImages.push_back(*image);
519 
520     // When the output paramter fence is not NULL, we are acquiring the image asynchronously.
521     if (acquireFenceFd != nullptr) {
522         *acquireFenceFd = buffer->mFence->dup();
523     }
524 
525     return AMEDIA_OK;
526 }
527 
528 BufferItem*
getBufferItemLocked()529 AImageReader::getBufferItemLocked() {
530     if (mBuffers.empty()) {
531         return nullptr;
532     }
533     // Return a BufferItem pointer and remove it from the list
534     auto it = mBuffers.begin();
535     BufferItem* buffer = *it;
536     mBuffers.erase(it);
537     return buffer;
538 }
539 
540 void
returnBufferItemLocked(BufferItem * buffer)541 AImageReader::returnBufferItemLocked(BufferItem* buffer) {
542     mBuffers.push_back(buffer);
543 }
544 
545 void
releaseImageLocked(AImage * image,int releaseFenceFd,bool clearCache)546 AImageReader::releaseImageLocked(AImage* image, int releaseFenceFd, bool clearCache) {
547     BufferItem* buffer = image->mBuffer;
548     if (buffer == nullptr) {
549         // This should not happen, but is not fatal
550         ALOGW("AImage %p has no buffer!", image);
551         return;
552     }
553 
554     int unlockFenceFd = -1;
555     media_status_t ret = image->unlockImageIfLocked(&unlockFenceFd);
556     if (ret < 0) {
557         ALOGW("%s: AImage %p is cannot be unlocked.", __FUNCTION__, image);
558         return;
559     }
560 
561     sp<Fence> unlockFence = unlockFenceFd > 0 ? new Fence(unlockFenceFd) : Fence::NO_FENCE;
562     sp<Fence> releaseFence = releaseFenceFd > 0 ? new Fence(releaseFenceFd) : Fence::NO_FENCE;
563     sp<Fence> bufferFence = Fence::merge("AImageReader", unlockFence, releaseFence);
564     mBufferItemConsumer->releaseBuffer(*buffer, bufferFence);
565     returnBufferItemLocked(buffer);
566     image->mBuffer = nullptr;
567     image->mLockedBuffer = nullptr;
568     image->mIsClosed = true;
569 
570     if (!clearCache) {
571         return;
572     }
573 
574     bool found = false;
575     // cleanup acquired image list
576     for (auto it = mAcquiredImages.begin();
577               it != mAcquiredImages.end(); it++) {
578         AImage* readerCopy = *it;
579         if (readerCopy == image) {
580             found = true;
581             mAcquiredImages.erase(it);
582             break;
583         }
584     }
585     if (!found) {
586         ALOGE("Error: AImage %p is not generated by AImageReader %p",
587                 image, this);
588     }
589 }
590 
591 // The LL-NDK API is now deprecated. New devices will no longer have the token
592 // manager service installed, so createHalToken will return false and this
593 // will return AMEDIA_ERROR_UNKNOWN on those devices.
getWindowNativeHandle(native_handle ** handle)594 media_status_t AImageReader::getWindowNativeHandle(native_handle **handle) {
595     if (mWindowHandle != nullptr) {
596         *handle = mWindowHandle;
597         return AMEDIA_OK;
598     }
599 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
600     sp<HGraphicBufferProducer> hgbp = new TWGraphicBufferProducer<HGraphicBufferProducer>(
601             mSurface->getIGraphicBufferProducer());
602 #else
603     sp<HGraphicBufferProducer> hgbp =
604         new TWGraphicBufferProducer<HGraphicBufferProducer>(mProducer);
605 #endif  // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
606     HalToken halToken;
607     if (!createHalToken(hgbp, &halToken)) {
608         return AMEDIA_ERROR_UNKNOWN;
609     }
610     mWindowHandle = convertHalTokenToNativeHandle(halToken);
611     if (!mWindowHandle) {
612         return AMEDIA_ERROR_UNKNOWN;
613     }
614     *handle = mWindowHandle;
615     return AMEDIA_OK;
616 }
617 
618 int
getBufferWidth(BufferItem * buffer)619 AImageReader::getBufferWidth(BufferItem* buffer) {
620     if (buffer == NULL) return -1;
621 
622     if (!buffer->mCrop.isEmpty()) {
623         return buffer->mCrop.getWidth();
624     }
625 
626     return buffer->mGraphicBuffer->getWidth();
627 }
628 
629 int
getBufferHeight(BufferItem * buffer)630 AImageReader::getBufferHeight(BufferItem* buffer) {
631     if (buffer == NULL) return -1;
632 
633     if (!buffer->mCrop.isEmpty()) {
634         return buffer->mCrop.getHeight();
635     }
636 
637     return buffer->mGraphicBuffer->getHeight();
638 }
639 
640 media_status_t
acquireNextImage(AImage ** image,int * acquireFenceFd)641 AImageReader::acquireNextImage(/*out*/AImage** image, /*out*/int* acquireFenceFd) {
642     Mutex::Autolock _l(mLock);
643     return acquireImageLocked(image, acquireFenceFd);
644 }
645 
646 media_status_t
acquireLatestImage(AImage ** image,int * acquireFenceFd)647 AImageReader::acquireLatestImage(/*out*/AImage** image, /*out*/int* acquireFenceFd) {
648     if (image == nullptr) {
649         return AMEDIA_ERROR_INVALID_PARAMETER;
650     }
651     Mutex::Autolock _l(mLock);
652     *image = nullptr;
653     AImage* prevImage = nullptr;
654     AImage* nextImage = nullptr;
655     media_status_t ret = acquireImageLocked(&prevImage, acquireFenceFd);
656     if (prevImage == nullptr) {
657         return ret;
658     }
659     for (;;) {
660         ret = acquireImageLocked(&nextImage, acquireFenceFd);
661         if (nextImage == nullptr) {
662             *image = prevImage;
663             return AMEDIA_OK;
664         }
665 
666         if (acquireFenceFd == nullptr) {
667             // No need for release fence here since the prevImage is unused and acquireImageLocked
668             // has already waited for acquired fence to be signaled.
669             prevImage->close();
670         } else {
671             // Use the acquire fence as release fence, so that producer can wait before trying to
672             // refill the buffer.
673             prevImage->close(*acquireFenceFd);
674         }
675         prevImage->free();
676         prevImage = nextImage;
677         nextImage = nullptr;
678     }
679 }
680 
681 media_status_t
setUsage(uint64_t usage)682 AImageReader::setUsage(uint64_t usage) {
683     Mutex::Autolock _l(mLock);
684     if (!mIsOpen || mBufferItemConsumer == nullptr) {
685         ALOGE("not ready to perform setUsage()");
686         return AMEDIA_ERROR_INVALID_PARAMETER;
687     }
688     if (mUsage == usage) {
689         return AMEDIA_OK;
690     }
691 
692     uint64_t halUsage = AHardwareBuffer_convertToGrallocUsageBits(mUsage);
693     status_t ret = mBufferItemConsumer->setConsumerUsageBits(halUsage);
694     if (ret != OK) {
695         ALOGE("setConsumerUsageBits() failed %d", ret);
696         return AMEDIA_ERROR_UNKNOWN;
697     }
698     mUsage = usage;
699     mHalUsage = halUsage;
700     return AMEDIA_OK;
701 }
702 
703 static
validateParameters(int32_t width,int32_t height,int32_t format,uint64_t usage,int32_t maxImages,AImageReader ** & reader)704 media_status_t validateParameters(int32_t width, int32_t height, int32_t format,
705                                   uint64_t usage, int32_t maxImages,
706                                   /*out*/ AImageReader**& reader) {
707     if (reader == nullptr) {
708         ALOGE("%s: reader argument is null", __FUNCTION__);
709         return AMEDIA_ERROR_INVALID_PARAMETER;
710     }
711 
712     if (width < 1 || height < 1) {
713         ALOGE("%s: image dimension must be positive: w:%d h:%d",
714                 __FUNCTION__, width, height);
715         return AMEDIA_ERROR_INVALID_PARAMETER;
716     }
717 
718     if (maxImages < 1) {
719         ALOGE("%s: max outstanding image count must be at least 1 (%d)",
720                 __FUNCTION__, maxImages);
721         return AMEDIA_ERROR_INVALID_PARAMETER;
722     }
723 
724     if (maxImages > BufferQueueDefs::NUM_BUFFER_SLOTS) {
725         ALOGE("%s: max outstanding image count (%d) cannot be larget than %d.",
726               __FUNCTION__, maxImages, BufferQueueDefs::NUM_BUFFER_SLOTS);
727         return AMEDIA_ERROR_INVALID_PARAMETER;
728     }
729 
730     if (!AImageReader::isSupportedFormatAndUsage(format, usage)) {
731         ALOGE("%s: format %d is not supported with usage 0x%" PRIx64 " by AImageReader",
732                 __FUNCTION__, format, usage);
733         return AMEDIA_ERROR_INVALID_PARAMETER;
734     }
735     return AMEDIA_OK;
736 }
737 
convertHalTokenToNativeHandle(const HalToken & halToken)738 static native_handle_t *convertHalTokenToNativeHandle(
739         const HalToken &halToken) {
740     // We attempt to store halToken in the ints of the native_handle_t after its
741     // size. The first int stores the size of the token. We store this in an int
742     // to avoid alignment issues where size_t and int do not have the same
743     // alignment.
744     size_t nhDataByteSize = halToken.size();
745     if (nhDataByteSize > kWindowHalTokenSizeMax) {
746         // The size of the token isn't reasonable..
747         return nullptr;
748     }
749     size_t numInts = ceil(nhDataByteSize / sizeof(int)) + 1;
750 
751     // We don't check for overflow, whether numInts can fit in an int, since we
752     // expect kWindowHalTokenSizeMax to be a reasonable limit.
753     // create a native_handle_t with 0 numFds and numInts number of ints.
754     native_handle_t *nh =
755         native_handle_create(0, numInts);
756     if (!nh) {
757         return nullptr;
758     }
759     // Store the size of the token in the first int.
760     nh->data[0] = nhDataByteSize;
761     memcpy(&(nh->data[1]), halToken.data(), nhDataByteSize);
762     return nh;
763 }
764 
765 EXPORT
AImageReader_new(int32_t width,int32_t height,int32_t format,int32_t maxImages,AImageReader ** reader)766 media_status_t AImageReader_new(
767         int32_t width, int32_t height, int32_t format, int32_t maxImages,
768         /*out*/AImageReader** reader) {
769     ALOGV("%s", __FUNCTION__);
770     return AImageReader_newWithUsage(
771             width, height, format, AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN, maxImages, reader);
772 }
773 
774 extern "C" {
775 
776 EXPORT
AImageReader_getWindowNativeHandle(AImageReader * reader,native_handle_t ** handle)777 media_status_t AImageReader_getWindowNativeHandle(
778         AImageReader *reader, /*out*/native_handle_t **handle) {
779     if (reader == nullptr || handle == nullptr) {
780         return AMEDIA_ERROR_INVALID_PARAMETER;
781     }
782     return reader->getWindowNativeHandle(handle);
783 }
784 
785 } //extern "C"
786 
787 EXPORT
AImageReader_newWithDataSpace(int32_t width,int32_t height,uint64_t usage,int32_t maxImages,uint32_t hardwareBufferFormat,int32_t dataSpace,AImageReader ** reader)788 media_status_t AImageReader_newWithDataSpace(
789         int32_t width, int32_t height, uint64_t usage, int32_t maxImages,
790         uint32_t hardwareBufferFormat, int32_t dataSpace,
791         /*out*/ AImageReader** reader) {
792     ALOGV("%s", __FUNCTION__);
793 
794     android_dataspace halDataSpace = static_cast<android_dataspace>(dataSpace);
795     int32_t format = static_cast<int32_t>(
796           mapHalFormatDataspaceToPublicFormat(hardwareBufferFormat, halDataSpace));
797     return AImageReader_newWithUsage(width, height, format, usage, maxImages, reader);
798 }
799 
800 EXPORT
AImageReader_newWithUsage(int32_t width,int32_t height,int32_t format,uint64_t usage,int32_t maxImages,AImageReader ** reader)801 media_status_t AImageReader_newWithUsage(
802         int32_t width, int32_t height, int32_t format, uint64_t usage,
803         int32_t maxImages, /*out*/ AImageReader** reader) {
804     ALOGV("%s", __FUNCTION__);
805 
806     validateParameters(width, height, format, usage, maxImages, reader);
807 
808     PublicFormat publicFormat = static_cast<PublicFormat>(format);
809     uint32_t halFormat = mapPublicFormatToHalFormat(publicFormat);
810     android_dataspace halDataSpace = mapPublicFormatToHalDataspace(publicFormat);
811 
812     AImageReader* tmpReader = new AImageReader(
813         width, height, format, usage, maxImages, halFormat, halDataSpace);
814     if (tmpReader == nullptr) {
815         ALOGE("%s: AImageReader allocation failed", __FUNCTION__);
816         return AMEDIA_ERROR_UNKNOWN;
817     }
818     media_status_t ret = tmpReader->init();
819     if (ret != AMEDIA_OK) {
820         ALOGE("%s: AImageReader initialization failed!", __FUNCTION__);
821         delete tmpReader;
822         return ret;
823     }
824     *reader = tmpReader;
825     (*reader)->incStrong((void*) AImageReader_new);
826     return AMEDIA_OK;
827 }
828 
829 EXPORT
AImageReader_delete(AImageReader * reader)830 void AImageReader_delete(AImageReader* reader) {
831     ALOGV("%s", __FUNCTION__);
832     if (reader != nullptr) {
833         reader->close();
834         reader->decStrong((void*) AImageReader_delete);
835     }
836     return;
837 }
838 
839 EXPORT
AImageReader_getWindow(AImageReader * reader,ANativeWindow ** window)840 media_status_t AImageReader_getWindow(AImageReader* reader, /*out*/ANativeWindow** window) {
841     ALOGV("%s", __FUNCTION__);
842     if (reader == nullptr || window == nullptr) {
843         ALOGE("%s: invalid argument. reader %p, window %p",
844                 __FUNCTION__, reader, window);
845         return AMEDIA_ERROR_INVALID_PARAMETER;
846     }
847     *window = reader->getWindow();
848     return AMEDIA_OK;
849 }
850 
851 EXPORT
AImageReader_getWidth(const AImageReader * reader,int32_t * width)852 media_status_t AImageReader_getWidth(const AImageReader* reader, /*out*/int32_t* width) {
853     ALOGV("%s", __FUNCTION__);
854     if (reader == nullptr || width == nullptr) {
855         ALOGE("%s: invalid argument. reader %p, width %p",
856                 __FUNCTION__, reader, width);
857         return AMEDIA_ERROR_INVALID_PARAMETER;
858     }
859     *width = reader->getWidth();
860     return AMEDIA_OK;
861 }
862 
863 EXPORT
AImageReader_getHeight(const AImageReader * reader,int32_t * height)864 media_status_t AImageReader_getHeight(const AImageReader* reader, /*out*/int32_t* height) {
865     ALOGV("%s", __FUNCTION__);
866     if (reader == nullptr || height == nullptr) {
867         ALOGE("%s: invalid argument. reader %p, height %p",
868                 __FUNCTION__, reader, height);
869         return AMEDIA_ERROR_INVALID_PARAMETER;
870     }
871     *height = reader->getHeight();
872     return AMEDIA_OK;
873 }
874 
875 EXPORT
AImageReader_getFormat(const AImageReader * reader,int32_t * format)876 media_status_t AImageReader_getFormat(const AImageReader* reader, /*out*/int32_t* format) {
877     ALOGV("%s", __FUNCTION__);
878     if (reader == nullptr || format == nullptr) {
879         ALOGE("%s: invalid argument. reader %p, format %p",
880                 __FUNCTION__, reader, format);
881         return AMEDIA_ERROR_INVALID_PARAMETER;
882     }
883     *format = reader->getFormat();
884     return AMEDIA_OK;
885 }
886 
887 EXPORT
AImageReader_getMaxImages(const AImageReader * reader,int32_t * maxImages)888 media_status_t AImageReader_getMaxImages(const AImageReader* reader, /*out*/int32_t* maxImages) {
889     ALOGV("%s", __FUNCTION__);
890     if (reader == nullptr || maxImages == nullptr) {
891         ALOGE("%s: invalid argument. reader %p, maxImages %p",
892                 __FUNCTION__, reader, maxImages);
893         return AMEDIA_ERROR_INVALID_PARAMETER;
894     }
895     *maxImages = reader->getMaxImages();
896     return AMEDIA_OK;
897 }
898 
899 EXPORT
AImageReader_acquireNextImage(AImageReader * reader,AImage ** image)900 media_status_t AImageReader_acquireNextImage(AImageReader* reader, /*out*/AImage** image) {
901     ALOGV("%s", __FUNCTION__);
902     return AImageReader_acquireNextImageAsync(reader, image, nullptr);
903 }
904 
905 EXPORT
AImageReader_acquireLatestImage(AImageReader * reader,AImage ** image)906 media_status_t AImageReader_acquireLatestImage(AImageReader* reader, /*out*/AImage** image) {
907     ALOGV("%s", __FUNCTION__);
908     return AImageReader_acquireLatestImageAsync(reader, image, nullptr);
909 }
910 
911 EXPORT
AImageReader_acquireNextImageAsync(AImageReader * reader,AImage ** image,int * acquireFenceFd)912 media_status_t AImageReader_acquireNextImageAsync(
913     AImageReader* reader, /*out*/AImage** image, /*out*/int* acquireFenceFd) {
914     ALOGV("%s", __FUNCTION__);
915     if (reader == nullptr || image == nullptr) {
916         ALOGE("%s: invalid argument. reader %p, image %p",
917                 __FUNCTION__, reader, image);
918         return AMEDIA_ERROR_INVALID_PARAMETER;
919     }
920     return reader->acquireNextImage(image, acquireFenceFd);
921 }
922 
923 EXPORT
AImageReader_acquireLatestImageAsync(AImageReader * reader,AImage ** image,int * acquireFenceFd)924 media_status_t AImageReader_acquireLatestImageAsync(
925     AImageReader* reader, /*out*/AImage** image, /*out*/int* acquireFenceFd) {
926     ALOGV("%s", __FUNCTION__);
927     if (reader == nullptr || image == nullptr) {
928         ALOGE("%s: invalid argument. reader %p, image %p",
929                 __FUNCTION__, reader, image);
930         return AMEDIA_ERROR_INVALID_PARAMETER;
931     }
932     return reader->acquireLatestImage(image, acquireFenceFd);
933 }
934 
935 EXPORT
AImageReader_setImageListener(AImageReader * reader,AImageReader_ImageListener * listener)936 media_status_t AImageReader_setImageListener(
937         AImageReader* reader, AImageReader_ImageListener* listener) {
938     ALOGV("%s", __FUNCTION__);
939     if (reader == nullptr) {
940         ALOGE("%s: invalid argument! reader %p", __FUNCTION__, reader);
941         return AMEDIA_ERROR_INVALID_PARAMETER;
942     }
943 
944     reader->setImageListener(listener);
945     return AMEDIA_OK;
946 }
947 
948 EXPORT
AImageReader_setBufferRemovedListener(AImageReader * reader,AImageReader_BufferRemovedListener * listener)949 media_status_t AImageReader_setBufferRemovedListener(
950     AImageReader* reader, AImageReader_BufferRemovedListener* listener) {
951     ALOGV("%s", __FUNCTION__);
952     if (reader == nullptr) {
953         ALOGE("%s: invalid argument! reader %p", __FUNCTION__, reader);
954         return AMEDIA_ERROR_INVALID_PARAMETER;
955     }
956 
957     reader->setBufferRemovedListener(listener);
958     return AMEDIA_OK;
959 }
960 
961 EXPORT
AImageReader_setUsage(AImageReader * reader,uint64_t usage)962 media_status_t AImageReader_setUsage(
963     AImageReader *reader, uint64_t usage) {
964     ALOGV("%s", __FUNCTION__);
965     if (reader == nullptr) {
966         ALOGE("%s: invalid argument! reader %p", __FUNCTION__, reader);
967         return AMEDIA_ERROR_INVALID_PARAMETER;
968     }
969     return reader->setUsage(usage);
970 }
971