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