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