Merge changes from topic "camera_ndk_fixes"

* changes:
  camera2ndk: ~ACameraCaptureSession shouldn't hold device lock in ACameraDevice_close().
  AImage: don't allow ~AImageReader to run before AImages are deleted.
  AImageReader: make sure ~AImageReader isn't called with FrameListener::mLock held.
  AImageReaderVendorTest: Tolerate failures for ACameraDevice_isSessionConfigurationSupported.
gugelfrei
Jayant Chowdhary 5 years ago committed by Gerrit Code Review
commit 35f148bc5a

@ -29,7 +29,7 @@
#include "ACameraCaptureSession.inc" #include "ACameraCaptureSession.inc"
ACameraDevice::~ACameraDevice() { ACameraDevice::~ACameraDevice() {
mDevice->stopLooper(); mDevice->stopLooperAndDisconnect();
} }
namespace android { namespace android {
@ -112,19 +112,7 @@ CameraDevice::CameraDevice(
} }
} }
// Device close implementaiton CameraDevice::~CameraDevice() { }
CameraDevice::~CameraDevice() {
sp<ACameraCaptureSession> session = mCurrentSession.promote();
{
Mutex::Autolock _l(mDeviceLock);
if (!isClosed()) {
disconnectLocked(session);
}
LOG_ALWAYS_FATAL_IF(mCbLooper != nullptr,
"CameraDevice looper should've been stopped before ~CameraDevice");
mCurrentSession = nullptr;
}
}
void void
CameraDevice::postSessionMsgAndCleanup(sp<AMessage>& msg) { CameraDevice::postSessionMsgAndCleanup(sp<AMessage>& msg) {
@ -892,8 +880,14 @@ CameraDevice::onCaptureErrorLocked(
return; return;
} }
void CameraDevice::stopLooper() { void CameraDevice::stopLooperAndDisconnect() {
Mutex::Autolock _l(mDeviceLock); Mutex::Autolock _l(mDeviceLock);
sp<ACameraCaptureSession> session = mCurrentSession.promote();
if (!isClosed()) {
disconnectLocked(session);
}
mCurrentSession = nullptr;
if (mCbLooper != nullptr) { if (mCbLooper != nullptr) {
mCbLooper->unregisterHandler(mHandler->id()); mCbLooper->unregisterHandler(mHandler->id());
mCbLooper->stop(); mCbLooper->stop();

@ -40,6 +40,7 @@
#include <camera/NdkCameraManager.h> #include <camera/NdkCameraManager.h>
#include <camera/NdkCameraCaptureSession.h> #include <camera/NdkCameraCaptureSession.h>
#include "ACameraMetadata.h" #include "ACameraMetadata.h"
namespace android { namespace android {
@ -110,7 +111,7 @@ class CameraDevice final : public RefBase {
inline ACameraDevice* getWrapper() const { return mWrapper; }; inline ACameraDevice* getWrapper() const { return mWrapper; };
// Stop the looper thread and unregister the handler // Stop the looper thread and unregister the handler
void stopLooper(); void stopLooperAndDisconnect();
private: private:
friend ACameraCaptureSession; friend ACameraCaptureSession;

@ -45,7 +45,7 @@
using namespace android; using namespace android;
ACameraDevice::~ACameraDevice() { ACameraDevice::~ACameraDevice() {
mDevice->stopLooper(); mDevice->stopLooperAndDisconnect();
} }
namespace android { namespace android {
@ -125,19 +125,7 @@ CameraDevice::CameraDevice(
} }
} }
// Device close implementaiton CameraDevice::~CameraDevice() { }
CameraDevice::~CameraDevice() {
sp<ACameraCaptureSession> session = mCurrentSession.promote();
{
Mutex::Autolock _l(mDeviceLock);
if (!isClosed()) {
disconnectLocked(session);
}
mCurrentSession = nullptr;
LOG_ALWAYS_FATAL_IF(mCbLooper != nullptr,
"CameraDevice looper should've been stopped before ~CameraDevice");
}
}
void void
CameraDevice::postSessionMsgAndCleanup(sp<AMessage>& msg) { CameraDevice::postSessionMsgAndCleanup(sp<AMessage>& msg) {
@ -1388,6 +1376,7 @@ CameraDevice::checkAndFireSequenceCompleteLocked() {
// before cbh goes out of scope and causing we call the session // before cbh goes out of scope and causing we call the session
// destructor while holding device lock // destructor while holding device lock
cbh.mSession.clear(); cbh.mSession.clear();
postSessionMsgAndCleanup(msg); postSessionMsgAndCleanup(msg);
} }
@ -1400,8 +1389,13 @@ CameraDevice::checkAndFireSequenceCompleteLocked() {
} }
} }
void CameraDevice::stopLooper() { void CameraDevice::stopLooperAndDisconnect() {
Mutex::Autolock _l(mDeviceLock); Mutex::Autolock _l(mDeviceLock);
sp<ACameraCaptureSession> session = mCurrentSession.promote();
if (!isClosed()) {
disconnectLocked(session);
}
mCurrentSession = nullptr;
if (mCbLooper != nullptr) { if (mCbLooper != nullptr) {
mCbLooper->unregisterHandler(mHandler->id()); mCbLooper->unregisterHandler(mHandler->id());
mCbLooper->stop(); mCbLooper->stop();

@ -36,6 +36,7 @@
#include <camera/NdkCameraManager.h> #include <camera/NdkCameraManager.h>
#include <camera/NdkCameraCaptureSession.h> #include <camera/NdkCameraCaptureSession.h>
#include "ACameraMetadata.h" #include "ACameraMetadata.h"
#include "utils.h" #include "utils.h"
@ -134,7 +135,7 @@ class CameraDevice final : public RefBase {
inline ACameraDevice* getWrapper() const { return mWrapper; }; inline ACameraDevice* getWrapper() const { return mWrapper; };
// Stop the looper thread and unregister the handler // Stop the looper thread and unregister the handler
void stopLooper(); void stopLooperAndDisconnect();
private: private:
friend ACameraCaptureSession; friend ACameraCaptureSession;

@ -24,6 +24,7 @@
#include <algorithm> #include <algorithm>
#include <mutex> #include <mutex>
#include <string> #include <string>
#include <variant>
#include <vector> #include <vector>
#include <stdio.h> #include <stdio.h>
#include <stdio.h> #include <stdio.h>
@ -49,6 +50,7 @@ static constexpr int kTestImageHeight = 480;
static constexpr int kTestImageFormat = AIMAGE_FORMAT_YUV_420_888; static constexpr int kTestImageFormat = AIMAGE_FORMAT_YUV_420_888;
using android::hardware::camera::common::V1_0::helper::VendorTagDescriptorCache; using android::hardware::camera::common::V1_0::helper::VendorTagDescriptorCache;
using ConfiguredWindows = std::set<native_handle_t *>;
class CameraHelper { class CameraHelper {
public: public:
@ -60,9 +62,12 @@ class CameraHelper {
const char* physicalCameraId; const char* physicalCameraId;
native_handle_t* anw; native_handle_t* anw;
}; };
int initCamera(native_handle_t* imgReaderAnw,
// Retaining the error code in case the caller needs to analyze it.
std::variant<int, ConfiguredWindows> initCamera(native_handle_t* imgReaderAnw,
const std::vector<PhysicalImgReaderInfo>& physicalImgReaders, const std::vector<PhysicalImgReaderInfo>& physicalImgReaders,
bool usePhysicalSettings) { bool usePhysicalSettings) {
ConfiguredWindows configuredWindows;
if (imgReaderAnw == nullptr) { if (imgReaderAnw == nullptr) {
ALOGE("Cannot initialize camera before image reader get initialized."); ALOGE("Cannot initialize camera before image reader get initialized.");
return -1; return -1;
@ -78,7 +83,7 @@ class CameraHelper {
ret = ACameraManager_openCamera(mCameraManager, mCameraId, &mDeviceCb, &mDevice); ret = ACameraManager_openCamera(mCameraManager, mCameraId, &mDeviceCb, &mDevice);
if (ret != AMEDIA_OK || mDevice == nullptr) { if (ret != AMEDIA_OK || mDevice == nullptr) {
ALOGE("Failed to open camera, ret=%d, mDevice=%p.", ret, mDevice); ALOGE("Failed to open camera, ret=%d, mDevice=%p.", ret, mDevice);
return -1; return ret;
} }
// Create capture session // Create capture session
@ -97,8 +102,9 @@ class CameraHelper {
ALOGE("ACaptureSessionOutputContainer_add failed, ret=%d", ret); ALOGE("ACaptureSessionOutputContainer_add failed, ret=%d", ret);
return ret; return ret;
} }
configuredWindows.insert(mImgReaderAnw);
std::vector<const char*> idPointerList; std::vector<const char*> idPointerList;
std::set<const native_handle_t*> physicalStreamMap;
for (auto& physicalStream : physicalImgReaders) { for (auto& physicalStream : physicalImgReaders) {
ACaptureSessionOutput* sessionOutput = nullptr; ACaptureSessionOutput* sessionOutput = nullptr;
ret = ACaptureSessionPhysicalOutput_create(physicalStream.anw, ret = ACaptureSessionPhysicalOutput_create(physicalStream.anw,
@ -112,21 +118,25 @@ class CameraHelper {
ALOGE("ACaptureSessionOutputContainer_add failed, ret=%d", ret); ALOGE("ACaptureSessionOutputContainer_add failed, ret=%d", ret);
return ret; return ret;
} }
mExtraOutputs.push_back(sessionOutput); ret = ACameraDevice_isSessionConfigurationSupported(mDevice, mOutputs);
if (ret != ACAMERA_OK && ret != ACAMERA_ERROR_UNSUPPORTED_OPERATION) {
ALOGW("ACameraDevice_isSessionConfigurationSupported failed, ret=%d camera id %s",
ret, mCameraId);
ACaptureSessionOutputContainer_remove(mOutputs, sessionOutput);
ACaptureSessionOutput_free(sessionOutput);
continue;
}
configuredWindows.insert(physicalStream.anw);
// Assume that at most one physical stream per physical camera. // Assume that at most one physical stream per physical camera.
mPhysicalCameraIds.push_back(physicalStream.physicalCameraId); mPhysicalCameraIds.push_back(physicalStream.physicalCameraId);
idPointerList.push_back(physicalStream.physicalCameraId); idPointerList.push_back(physicalStream.physicalCameraId);
physicalStreamMap.insert(physicalStream.anw);
mSessionPhysicalOutputs.push_back(sessionOutput);
} }
ACameraIdList cameraIdList; ACameraIdList cameraIdList;
cameraIdList.numCameras = idPointerList.size(); cameraIdList.numCameras = idPointerList.size();
cameraIdList.cameraIds = idPointerList.data(); cameraIdList.cameraIds = idPointerList.data();
ret = ACameraDevice_isSessionConfigurationSupported(mDevice, mOutputs);
if (ret != ACAMERA_OK && ret != ACAMERA_ERROR_UNSUPPORTED_OPERATION) {
ALOGE("ACameraDevice_isSessionConfigurationSupported failed, ret=%d", ret);
return ret;
}
ret = ACameraDevice_createCaptureSession(mDevice, mOutputs, &mSessionCb, &mSession); ret = ACameraDevice_createCaptureSession(mDevice, mOutputs, &mSessionCb, &mSession);
if (ret != AMEDIA_OK) { if (ret != AMEDIA_OK) {
ALOGE("ACameraDevice_createCaptureSession failed, ret=%d", ret); ALOGE("ACameraDevice_createCaptureSession failed, ret=%d", ret);
@ -157,6 +167,10 @@ class CameraHelper {
} }
for (auto& physicalStream : physicalImgReaders) { for (auto& physicalStream : physicalImgReaders) {
if (physicalStreamMap.find(physicalStream.anw) == physicalStreamMap.end()) {
ALOGI("Skipping physicalStream anw=%p", physicalStream.anw);
continue;
}
ACameraOutputTarget* outputTarget = nullptr; ACameraOutputTarget* outputTarget = nullptr;
ret = ACameraOutputTarget_create(physicalStream.anw, &outputTarget); ret = ACameraOutputTarget_create(physicalStream.anw, &outputTarget);
if (ret != AMEDIA_OK) { if (ret != AMEDIA_OK) {
@ -168,11 +182,11 @@ class CameraHelper {
ALOGE("ACaptureRequest_addTarget failed, ret=%d", ret); ALOGE("ACaptureRequest_addTarget failed, ret=%d", ret);
return ret; return ret;
} }
mReqExtraOutputs.push_back(outputTarget); mReqPhysicalOutputs.push_back(outputTarget);
} }
mIsCameraReady = true; mIsCameraReady = true;
return 0; return configuredWindows;
} }
@ -184,10 +198,10 @@ class CameraHelper {
ACameraOutputTarget_free(mReqImgReaderOutput); ACameraOutputTarget_free(mReqImgReaderOutput);
mReqImgReaderOutput = nullptr; mReqImgReaderOutput = nullptr;
} }
for (auto& outputTarget : mReqExtraOutputs) { for (auto& outputTarget : mReqPhysicalOutputs) {
ACameraOutputTarget_free(outputTarget); ACameraOutputTarget_free(outputTarget);
} }
mReqExtraOutputs.clear(); mReqPhysicalOutputs.clear();
if (mStillRequest) { if (mStillRequest) {
ACaptureRequest_free(mStillRequest); ACaptureRequest_free(mStillRequest);
mStillRequest = nullptr; mStillRequest = nullptr;
@ -201,10 +215,10 @@ class CameraHelper {
ACaptureSessionOutput_free(mImgReaderOutput); ACaptureSessionOutput_free(mImgReaderOutput);
mImgReaderOutput = nullptr; mImgReaderOutput = nullptr;
} }
for (auto& extraOutput : mExtraOutputs) { for (auto& extraOutput : mSessionPhysicalOutputs) {
ACaptureSessionOutput_free(extraOutput); ACaptureSessionOutput_free(extraOutput);
} }
mExtraOutputs.clear(); mSessionPhysicalOutputs.clear();
if (mOutputs) { if (mOutputs) {
ACaptureSessionOutputContainer_free(mOutputs); ACaptureSessionOutputContainer_free(mOutputs);
mOutputs = nullptr; mOutputs = nullptr;
@ -262,13 +276,13 @@ class CameraHelper {
// Capture session // Capture session
ACaptureSessionOutputContainer* mOutputs = nullptr; ACaptureSessionOutputContainer* mOutputs = nullptr;
ACaptureSessionOutput* mImgReaderOutput = nullptr; ACaptureSessionOutput* mImgReaderOutput = nullptr;
std::vector<ACaptureSessionOutput*> mExtraOutputs; std::vector<ACaptureSessionOutput*> mSessionPhysicalOutputs;
ACameraCaptureSession* mSession = nullptr; ACameraCaptureSession* mSession = nullptr;
// Capture request // Capture request
ACaptureRequest* mStillRequest = nullptr; ACaptureRequest* mStillRequest = nullptr;
ACameraOutputTarget* mReqImgReaderOutput = nullptr; ACameraOutputTarget* mReqImgReaderOutput = nullptr;
std::vector<ACameraOutputTarget*> mReqExtraOutputs; std::vector<ACameraOutputTarget*> mReqPhysicalOutputs;
bool mIsCameraReady = false; bool mIsCameraReady = false;
const char* mCameraId; const char* mCameraId;
@ -581,9 +595,11 @@ class AImageReaderVendorTest : public ::testing::Test {
} }
CameraHelper cameraHelper(id, mCameraManager); CameraHelper cameraHelper(id, mCameraManager);
ret = cameraHelper.initCamera(testCase.getNativeWindow(), std::variant<int, ConfiguredWindows> retInit =
{}/*physicalImageReaders*/, false/*usePhysicalSettings*/); cameraHelper.initCamera(testCase.getNativeWindow(), {}/*physicalImageReaders*/,
if (ret < 0) { false/*usePhysicalSettings*/);
int *retp = std::get_if<int>(&retInit);
if (retp) {
ALOGE("Unable to initialize camera helper"); ALOGE("Unable to initialize camera helper");
return false; return false;
} }
@ -751,10 +767,15 @@ class AImageReaderVendorTest : public ::testing::Test {
physicalImgReaderInfo.push_back({physicalCameraIds[0], testCases[1]->getNativeWindow()}); physicalImgReaderInfo.push_back({physicalCameraIds[0], testCases[1]->getNativeWindow()});
physicalImgReaderInfo.push_back({physicalCameraIds[1], testCases[2]->getNativeWindow()}); physicalImgReaderInfo.push_back({physicalCameraIds[1], testCases[2]->getNativeWindow()});
int ret = cameraHelper.initCamera(testCases[0]->getNativeWindow(), std::variant<int, ConfiguredWindows> retInit =
physicalImgReaderInfo, usePhysicalSettings); cameraHelper.initCamera(testCases[0]->getNativeWindow(), physicalImgReaderInfo,
ASSERT_EQ(ret, 0); usePhysicalSettings);
int *retp = std::get_if<int>(&retInit);
ASSERT_EQ(retp, nullptr);
ConfiguredWindows *configuredWindowsp = std::get_if<ConfiguredWindows>(&retInit);
ASSERT_NE(configuredWindowsp, nullptr);
ASSERT_LE(configuredWindowsp->size(), testCases.size());
int ret = 0;
if (!cameraHelper.isCameraReady()) { if (!cameraHelper.isCameraReady()) {
ALOGW("Camera is not ready after successful initialization. It's either due to camera " ALOGW("Camera is not ready after successful initialization. It's either due to camera "
"on board lacks BACKWARDS_COMPATIBLE capability or the device does not have " "on board lacks BACKWARDS_COMPATIBLE capability or the device does not have "
@ -776,9 +797,15 @@ class AImageReaderVendorTest : public ::testing::Test {
break; break;
} }
} }
ASSERT_EQ(testCases[0]->getAcquiredImageCount(), pictureCount); for(auto &testCase : testCases) {
ASSERT_EQ(testCases[1]->getAcquiredImageCount(), pictureCount); auto it = configuredWindowsp->find(testCase->getNativeWindow());
ASSERT_EQ(testCases[2]->getAcquiredImageCount(), pictureCount); if (it == configuredWindowsp->end()) {
continue;
}
ALOGI("Testing window %p", testCase->getNativeWindow());
ASSERT_EQ(testCase->getAcquiredImageCount(), pictureCount);
}
ASSERT_TRUE(cameraHelper.checkCallbacks(pictureCount)); ASSERT_TRUE(cameraHelper.checkCallbacks(pictureCount));
ACameraMetadata_free(staticMetadata); ACameraMetadata_free(staticMetadata);

@ -35,6 +35,7 @@ AImage::AImage(AImageReader* reader, int32_t format, uint64_t usage, BufferItem*
int64_t timestamp, int32_t width, int32_t height, int32_t numPlanes) : int64_t timestamp, int32_t width, int32_t height, int32_t numPlanes) :
mReader(reader), mFormat(format), mUsage(usage), mBuffer(buffer), mLockedBuffer(nullptr), mReader(reader), mFormat(format), mUsage(usage), mBuffer(buffer), mLockedBuffer(nullptr),
mTimestamp(timestamp), mWidth(width), mHeight(height), mNumPlanes(numPlanes) { mTimestamp(timestamp), mWidth(width), mHeight(height), mNumPlanes(numPlanes) {
LOG_FATAL_IF(reader == nullptr, "AImageReader shouldn't be null while creating AImage");
} }
AImage::~AImage() { AImage::~AImage() {
@ -57,14 +58,9 @@ AImage::close(int releaseFenceFd) {
if (mIsClosed) { if (mIsClosed) {
return; return;
} }
sp<AImageReader> reader = mReader.promote(); if (!mReader->mIsClosed) {
if (reader != nullptr) { mReader->releaseImageLocked(this, releaseFenceFd);
reader->releaseImageLocked(this, releaseFenceFd);
} else if (mBuffer != nullptr) {
LOG_ALWAYS_FATAL("%s: parent AImageReader closed without releasing image %p",
__FUNCTION__, this);
} }
// Should have been set to nullptr in releaseImageLocked // Should have been set to nullptr in releaseImageLocked
// Set to nullptr here for extra safety only // Set to nullptr here for extra safety only
mBuffer = nullptr; mBuffer = nullptr;
@ -83,22 +79,12 @@ AImage::free() {
void void
AImage::lockReader() const { AImage::lockReader() const {
sp<AImageReader> reader = mReader.promote(); mReader->mLock.lock();
if (reader == nullptr) {
// Reader has been closed
return;
}
reader->mLock.lock();
} }
void void
AImage::unlockReader() const { AImage::unlockReader() const {
sp<AImageReader> reader = mReader.promote(); mReader->mLock.unlock();
if (reader == nullptr) {
// Reader has been closed
return;
}
reader->mLock.unlock();
} }
media_status_t media_status_t

@ -72,7 +72,7 @@ struct AImage {
uint32_t getJpegSize() const; uint32_t getJpegSize() const;
// When reader is close, AImage will only accept close API call // When reader is close, AImage will only accept close API call
wp<AImageReader> mReader; const sp<AImageReader> mReader;
const int32_t mFormat; const int32_t mFormat;
const uint64_t mUsage; // AHARDWAREBUFFER_USAGE_* flags. const uint64_t mUsage; // AHARDWAREBUFFER_USAGE_* flags.
BufferItem* mBuffer; BufferItem* mBuffer;

@ -113,12 +113,12 @@ AImageReader::getNumPlanesForFormat(int32_t format) {
void void
AImageReader::FrameListener::onFrameAvailable(const BufferItem& /*item*/) { AImageReader::FrameListener::onFrameAvailable(const BufferItem& /*item*/) {
Mutex::Autolock _l(mLock);
sp<AImageReader> reader = mReader.promote(); sp<AImageReader> reader = mReader.promote();
if (reader == nullptr) { if (reader == nullptr) {
ALOGW("A frame is available after AImageReader closed!"); ALOGW("A frame is available after AImageReader closed!");
return; // reader has been closed return; // reader has been closed
} }
Mutex::Autolock _l(mLock);
if (mListener.onImageAvailable == nullptr) { if (mListener.onImageAvailable == nullptr) {
return; // No callback registered return; // No callback registered
} }
@ -143,12 +143,12 @@ AImageReader::FrameListener::setImageListener(AImageReader_ImageListener* listen
void void
AImageReader::BufferRemovedListener::onBufferFreed(const wp<GraphicBuffer>& graphicBuffer) { AImageReader::BufferRemovedListener::onBufferFreed(const wp<GraphicBuffer>& graphicBuffer) {
Mutex::Autolock _l(mLock);
sp<AImageReader> reader = mReader.promote(); sp<AImageReader> reader = mReader.promote();
if (reader == nullptr) { if (reader == nullptr) {
ALOGW("A frame is available after AImageReader closed!"); ALOGW("A frame is available after AImageReader closed!");
return; // reader has been closed return; // reader has been closed
} }
Mutex::Autolock _l(mLock);
if (mListener.onBufferRemoved == nullptr) { if (mListener.onBufferRemoved == nullptr) {
return; // No callback registered return; // No callback registered
} }
@ -272,6 +272,11 @@ AImageReader::AImageReader(int32_t width,
mFrameListener(new FrameListener(this)), mFrameListener(new FrameListener(this)),
mBufferRemovedListener(new BufferRemovedListener(this)) {} mBufferRemovedListener(new BufferRemovedListener(this)) {}
AImageReader::~AImageReader() {
Mutex::Autolock _l(mLock);
LOG_FATAL_IF("AImageReader not closed before destruction", mIsClosed != true);
}
media_status_t media_status_t
AImageReader::init() { AImageReader::init() {
PublicFormat publicFormat = static_cast<PublicFormat>(mFormat); PublicFormat publicFormat = static_cast<PublicFormat>(mFormat);
@ -347,8 +352,12 @@ AImageReader::init() {
return AMEDIA_OK; return AMEDIA_OK;
} }
AImageReader::~AImageReader() { void AImageReader::close() {
Mutex::Autolock _l(mLock); Mutex::Autolock _l(mLock);
if (mIsClosed) {
return;
}
mIsClosed = true;
AImageReader_ImageListener nullListener = {nullptr, nullptr}; AImageReader_ImageListener nullListener = {nullptr, nullptr};
setImageListenerLocked(&nullListener); setImageListenerLocked(&nullListener);
@ -741,6 +750,7 @@ EXPORT
void AImageReader_delete(AImageReader* reader) { void AImageReader_delete(AImageReader* reader) {
ALOGV("%s", __FUNCTION__); ALOGV("%s", __FUNCTION__);
if (reader != nullptr) { if (reader != nullptr) {
reader->close();
reader->decStrong((void*) AImageReader_delete); reader->decStrong((void*) AImageReader_delete);
} }
return; return;

@ -76,6 +76,7 @@ struct AImageReader : public RefBase {
int32_t getHeight() const { return mHeight; }; int32_t getHeight() const { return mHeight; };
int32_t getFormat() const { return mFormat; }; int32_t getFormat() const { return mFormat; };
int32_t getMaxImages() const { return mMaxImages; }; int32_t getMaxImages() const { return mMaxImages; };
void close();
private: private:
@ -134,7 +135,7 @@ struct AImageReader : public RefBase {
private: private:
AImageReader_ImageListener mListener = {nullptr, nullptr}; AImageReader_ImageListener mListener = {nullptr, nullptr};
wp<AImageReader> mReader; const wp<AImageReader> mReader;
Mutex mLock; Mutex mLock;
}; };
sp<FrameListener> mFrameListener; sp<FrameListener> mFrameListener;
@ -149,7 +150,7 @@ struct AImageReader : public RefBase {
private: private:
AImageReader_BufferRemovedListener mListener = {nullptr, nullptr}; AImageReader_BufferRemovedListener mListener = {nullptr, nullptr};
wp<AImageReader> mReader; const wp<AImageReader> mReader;
Mutex mLock; Mutex mLock;
}; };
sp<BufferRemovedListener> mBufferRemovedListener; sp<BufferRemovedListener> mBufferRemovedListener;
@ -165,6 +166,7 @@ struct AImageReader : public RefBase {
native_handle_t* mWindowHandle = nullptr; native_handle_t* mWindowHandle = nullptr;
List<AImage*> mAcquiredImages; List<AImage*> mAcquiredImages;
bool mIsClosed = false;
Mutex mLock; Mutex mLock;
}; };

Loading…
Cancel
Save