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