diff --git a/camera/ndk/impl/ACameraManager.cpp b/camera/ndk/impl/ACameraManager.cpp index f408b6a854..b58ebe21e9 100644 --- a/camera/ndk/impl/ACameraManager.cpp +++ b/camera/ndk/impl/ACameraManager.cpp @@ -35,6 +35,7 @@ const char* CameraManagerGlobal::kCameraIdKey = "CameraId"; const char* CameraManagerGlobal::kPhysicalCameraIdKey = "PhysicalCameraId"; const char* CameraManagerGlobal::kCallbackFpKey = "CallbackFp"; const char* CameraManagerGlobal::kContextKey = "CallbackContext"; +const nsecs_t CameraManagerGlobal::kCallbackDrainTimeout = 5000000; // 5 ms Mutex CameraManagerGlobal::sLock; CameraManagerGlobal* CameraManagerGlobal::sInstance = nullptr; @@ -117,7 +118,7 @@ sp CameraManagerGlobal::getCameraServiceLocked() { return nullptr; } if (mHandler == nullptr) { - mHandler = new CallbackHandler(); + mHandler = new CallbackHandler(this); } mCbLooper->registerHandler(mHandler); } @@ -211,6 +212,9 @@ void CameraManagerGlobal::registerExtendedAvailabilityCallback( void CameraManagerGlobal::unregisterExtendedAvailabilityCallback( const ACameraManager_ExtendedAvailabilityCallbacks *callback) { Mutex::Autolock _l(mLock); + + drainPendingCallbacksLocked(); + Callback cb(callback); mCallbacks.erase(cb); } @@ -223,10 +227,32 @@ void CameraManagerGlobal::registerAvailabilityCallback( void CameraManagerGlobal::unregisterAvailabilityCallback( const ACameraManager_AvailabilityCallbacks *callback) { Mutex::Autolock _l(mLock); + + drainPendingCallbacksLocked(); + Callback cb(callback); mCallbacks.erase(cb); } +void CameraManagerGlobal::onCallbackCalled() { + Mutex::Autolock _l(mLock); + if (mPendingCallbackCnt > 0) { + mPendingCallbackCnt--; + } + mCallbacksCond.signal(); +} + +void CameraManagerGlobal::drainPendingCallbacksLocked() { + while (mPendingCallbackCnt > 0) { + auto res = mCallbacksCond.waitRelative(mLock, kCallbackDrainTimeout); + if (res != NO_ERROR) { + ALOGE("%s: Error waiting to drain callbacks: %s(%d)", + __FUNCTION__, strerror(-res), res); + break; + } + } +} + template void CameraManagerGlobal::registerAvailCallback(const T *callback) { Mutex::Autolock _l(mLock); @@ -250,6 +276,7 @@ void CameraManagerGlobal::registerAvailCallback(const T *callback) { msg->setPointer(kCallbackFpKey, (void *) cbFunc); msg->setPointer(kContextKey, cb.mContext); msg->setString(kCameraIdKey, AString(cameraId)); + mPendingCallbackCnt++; msg->post(); // Physical camera unavailable callback @@ -263,6 +290,7 @@ void CameraManagerGlobal::registerAvailCallback(const T *callback) { msg->setPointer(kContextKey, cb.mContext); msg->setString(kCameraIdKey, AString(cameraId)); msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId)); + mPendingCallbackCnt++; msg->post(); } } @@ -323,6 +351,16 @@ bool CameraManagerGlobal::isStatusAvailable(int32_t status) { } void CameraManagerGlobal::CallbackHandler::onMessageReceived( + const sp &msg) { + onMessageReceivedInternal(msg); + if (msg->what() == kWhatSendSingleCallback || + msg->what() == kWhatSendSingleAccessCallback || + msg->what() == kWhatSendSinglePhysicalCameraCallback) { + notifyParent(); + } +} + +void CameraManagerGlobal::CallbackHandler::onMessageReceivedInternal( const sp &msg) { switch (msg->what()) { case kWhatSendSingleCallback: @@ -405,6 +443,13 @@ void CameraManagerGlobal::CallbackHandler::onMessageReceived( } } +void CameraManagerGlobal::CallbackHandler::notifyParent() { + sp parent = mParent.promote(); + if (parent != nullptr) { + parent->onCallbackCalled(); + } +} + binder::Status CameraManagerGlobal::CameraServiceListener::onCameraAccessPrioritiesChanged() { sp cm = mCameraManager.promote(); if (cm != nullptr) { @@ -445,6 +490,7 @@ void CameraManagerGlobal::onCameraAccessPrioritiesChanged() { if (cbFp != nullptr) { msg->setPointer(kCallbackFpKey, (void *) cbFp); msg->setPointer(kContextKey, cb.mContext); + mPendingCallbackCnt++; msg->post(); } } @@ -491,6 +537,7 @@ void CameraManagerGlobal::onStatusChangedLocked( msg->setPointer(kCallbackFpKey, (void *) cbFp); msg->setPointer(kContextKey, cb.mContext); msg->setString(kCameraIdKey, AString(cameraId)); + mPendingCallbackCnt++; msg->post(); } } @@ -545,6 +592,7 @@ void CameraManagerGlobal::onStatusChangedLocked( msg->setPointer(kContextKey, cb.mContext); msg->setString(kCameraIdKey, AString(cameraId)); msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId)); + mPendingCallbackCnt++; msg->post(); } } diff --git a/camera/ndk/impl/ACameraManager.h b/camera/ndk/impl/ACameraManager.h index 7fba188bd7..ccbfaa986b 100644 --- a/camera/ndk/impl/ACameraManager.h +++ b/camera/ndk/impl/ACameraManager.h @@ -163,6 +163,12 @@ class CameraManagerGlobal final : public RefBase { ACameraManager_PhysicalCameraAvailabilityCallback mPhysicalCamUnavailable; void* mContext; }; + + android::Condition mCallbacksCond; + size_t mPendingCallbackCnt = 0; + void onCallbackCalled(); + void drainPendingCallbacksLocked(); + std::set mCallbacks; // definition of handler and message @@ -175,10 +181,16 @@ class CameraManagerGlobal final : public RefBase { static const char* kPhysicalCameraIdKey; static const char* kCallbackFpKey; static const char* kContextKey; + static const nsecs_t kCallbackDrainTimeout; class CallbackHandler : public AHandler { public: - CallbackHandler() {} + CallbackHandler(wp parent) : mParent(parent) {} void onMessageReceived(const sp &msg) override; + + private: + wp mParent; + void notifyParent(); + void onMessageReceivedInternal(const sp &msg); }; sp mHandler; sp mCbLooper; // Looper thread where callbacks actually happen on diff --git a/camera/ndk/include/camera/NdkCameraManager.h b/camera/ndk/include/camera/NdkCameraManager.h index e2b71bf017..0a2ee57510 100644 --- a/camera/ndk/include/camera/NdkCameraManager.h +++ b/camera/ndk/include/camera/NdkCameraManager.h @@ -191,6 +191,9 @@ camera_status_t ACameraManager_registerAvailabilityCallback( * *

Removing a callback that isn't registered has no effect.

* + *

This function must not be called with a mutex lock also held by + * the availability callbacks.

+ * * @param manager the {@link ACameraManager} of interest. * @param callback the {@link ACameraManager_AvailabilityCallbacks} to be unregistered. * @@ -382,6 +385,9 @@ camera_status_t ACameraManager_registerExtendedAvailabilityCallback( * *

Removing a callback that isn't registered has no effect.

* + *

This function must not be called with a mutex lock also held by + * the extended availability callbacks.

+ * * @param manager the {@link ACameraManager} of interest. * @param callback the {@link ACameraManager_ExtendedAvailabilityCallbacks} to be unregistered. * diff --git a/camera/ndk/ndk_vendor/impl/ACameraManager.cpp b/camera/ndk/ndk_vendor/impl/ACameraManager.cpp index e2097b5639..5aa9c467fb 100644 --- a/camera/ndk/ndk_vendor/impl/ACameraManager.cpp +++ b/camera/ndk/ndk_vendor/impl/ACameraManager.cpp @@ -45,6 +45,7 @@ const char* CameraManagerGlobal::kCameraIdKey = "CameraId"; const char* CameraManagerGlobal::kPhysicalCameraIdKey = "PhysicalCameraId"; const char* CameraManagerGlobal::kCallbackFpKey = "CallbackFp"; const char* CameraManagerGlobal::kContextKey = "CallbackContext"; +const nsecs_t CameraManagerGlobal::kCallbackDrainTimeout = 5000000; // 5 ms Mutex CameraManagerGlobal::sLock; CameraManagerGlobal* CameraManagerGlobal::sInstance = nullptr; @@ -249,7 +250,7 @@ sp CameraManagerGlobal::getCameraService() { return nullptr; } if (mHandler == nullptr) { - mHandler = new CallbackHandler(); + mHandler = new CallbackHandler(this); } mCbLooper->registerHandler(mHandler); } @@ -317,6 +318,7 @@ void CameraManagerGlobal::registerAvailabilityCallback( void CameraManagerGlobal::unregisterAvailabilityCallback( const ACameraManager_AvailabilityCallbacks *callback) { Mutex::Autolock _l(mLock); + drainPendingCallbacksLocked(); Callback cb(callback); mCallbacks.erase(cb); } @@ -329,10 +331,30 @@ void CameraManagerGlobal::registerExtendedAvailabilityCallback( void CameraManagerGlobal::unregisterExtendedAvailabilityCallback( const ACameraManager_ExtendedAvailabilityCallbacks *callback) { Mutex::Autolock _l(mLock); + drainPendingCallbacksLocked(); Callback cb(callback); mCallbacks.erase(cb); } +void CameraManagerGlobal::onCallbackCalled() { + Mutex::Autolock _l(mLock); + if (mPendingCallbackCnt > 0) { + mPendingCallbackCnt--; + } + mCallbacksCond.signal(); +} + +void CameraManagerGlobal::drainPendingCallbacksLocked() { + while (mPendingCallbackCnt > 0) { + auto res = mCallbacksCond.waitRelative(mLock, kCallbackDrainTimeout); + if (res != NO_ERROR) { + ALOGE("%s: Error waiting to drain callbacks: %s(%d)", + __FUNCTION__, strerror(-res), res); + break; + } + } +} + template void CameraManagerGlobal::registerAvailCallback(const T *callback) { Mutex::Autolock _l(mLock); @@ -351,6 +373,7 @@ void CameraManagerGlobal::registerAvailCallback(const T *callback) { msg->setPointer(kCallbackFpKey, (void *) cbFunc); msg->setPointer(kContextKey, cb.mContext); msg->setString(kCameraIdKey, AString(cameraId.c_str())); + mPendingCallbackCnt++; msg->post(); // Physical camera unavailable callback @@ -363,6 +386,7 @@ void CameraManagerGlobal::registerAvailCallback(const T *callback) { msg->setPointer(kContextKey, cb.mContext); msg->setString(kCameraIdKey, AString(cameraId.c_str())); msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId.c_str())); + mPendingCallbackCnt++; msg->post(); } } @@ -406,6 +430,15 @@ bool CameraManagerGlobal::isStatusAvailable(CameraDeviceStatus status) { } void CameraManagerGlobal::CallbackHandler::onMessageReceived( + const sp &msg) { + onMessageReceivedInternal(msg); + if (msg->what() == kWhatSendSingleCallback || + msg->what() == kWhatSendSinglePhysicalCameraCallback) { + notifyParent(); + } +} + +void CameraManagerGlobal::CallbackHandler::onMessageReceivedInternal( const sp &msg) { switch (msg->what()) { case kWhatSendSingleCallback: @@ -466,6 +499,13 @@ void CameraManagerGlobal::CallbackHandler::onMessageReceived( } } +void CameraManagerGlobal::CallbackHandler::notifyParent() { + sp parent = mParent.promote(); + if (parent != nullptr) { + parent->onCallbackCalled(); + } +} + hardware::Return CameraManagerGlobal::CameraServiceListener::onStatusChanged( const CameraStatusAndId &statusAndId) { sp cm = mCameraManager.promote(); @@ -512,6 +552,7 @@ void CameraManagerGlobal::onStatusChangedLocked( msg->setPointer(kCallbackFpKey, (void *) cbFp); msg->setPointer(kContextKey, cb.mContext); msg->setString(kCameraIdKey, AString(cameraId.c_str())); + mPendingCallbackCnt++; msg->post(); } if (status == CameraDeviceStatus::STATUS_NOT_PRESENT) { @@ -577,6 +618,7 @@ void CameraManagerGlobal::onStatusChangedLocked( msg->setPointer(kContextKey, cb.mContext); msg->setString(kCameraIdKey, AString(cameraId.c_str())); msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId.c_str())); + mPendingCallbackCnt++; msg->post(); } } diff --git a/camera/ndk/ndk_vendor/impl/ACameraManager.h b/camera/ndk/ndk_vendor/impl/ACameraManager.h index 36c8e2bd8f..85da3e9554 100644 --- a/camera/ndk/ndk_vendor/impl/ACameraManager.h +++ b/camera/ndk/ndk_vendor/impl/ACameraManager.h @@ -156,6 +156,12 @@ class CameraManagerGlobal final : public RefBase { ACameraManager_PhysicalCameraAvailabilityCallback mPhysicalCamUnavailable; void* mContext; }; + + android::Condition mCallbacksCond; + size_t mPendingCallbackCnt = 0; + void onCallbackCalled(); + void drainPendingCallbacksLocked(); + std::set mCallbacks; // definition of handler and message @@ -167,10 +173,15 @@ class CameraManagerGlobal final : public RefBase { static const char* kPhysicalCameraIdKey; static const char* kCallbackFpKey; static const char* kContextKey; + static const nsecs_t kCallbackDrainTimeout; class CallbackHandler : public AHandler { public: - CallbackHandler() {} + CallbackHandler(wp parent) : mParent(parent) {} void onMessageReceived(const sp &msg) override; + private: + wp mParent; + void notifyParent(); + void onMessageReceivedInternal(const sp &msg); }; sp mHandler; sp mCbLooper; // Looper thread where callbacks actually happen on