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