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