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