diff --git a/frameworks/native/camera/base/src/input/camera_manager.cpp b/frameworks/native/camera/base/src/input/camera_manager.cpp index 5d34628ead33b43ae1df195ef9e6bda27b90d6c1..7cda69c18c0ccdb266dcfc47abeb3c082b0aacbe 100644 --- a/frameworks/native/camera/base/src/input/camera_manager.cpp +++ b/frameworks/native/camera/base/src/input/camera_manager.cpp @@ -71,6 +71,9 @@ std::mutex CameraManager::g_instanceMutex; constexpr int32_t CONTROL_CENTER_RESOLUTION_WIDTH_MAX = 1920; constexpr int32_t CONTROL_CENTER_RESOLUTION_HEIGHT_MAX = 1080; +constexpr uint32_t MAX_SPTR_RELEASE_CHECK_TIMES = 20; +constexpr uint32_t MAX_SPTR_RELEASE_CHECK_INTERVAL = 50; + const std::string CameraManager::surfaceFormat = "CAMERA_SURFACE_FORMAT"; const std::unordered_map CameraManager::metaToFwCameraFormat_ = { @@ -193,7 +196,12 @@ int32_t CameraManager::CreateListenerObject() CHECK_RETURN_RET_ELOG(object == nullptr, CAMERA_ALLOC_ERROR, "listener object is nullptr.."); auto serviceProxy = GetServiceProxy(); CHECK_RETURN_RET_ELOG(serviceProxy == nullptr, CameraErrorCode::SERVICE_FATL_ERROR, "serviceProxy is null"); - return serviceProxy->SetListenerObject(object); + int32_t ret = serviceProxy->SetListenerObject(object); + if (ret == 0) { + std::lock_guard lock(listenerStubMutex_); + listenerStub_ = listenerStub; + } + return ret; } int32_t CameraStatusListenerManager::OnCameraStatusChanged( @@ -1053,11 +1061,13 @@ int32_t CameraManager::SubscribeSystemAbility() std::lock_guard lock(saListenerMuxtex_); if (saListener_ == nullptr) { auto listener = new(std::nothrow) CameraServiceSystemAbilityListener(); - saListener_ = listener; - CHECK_RETURN_RET_ELOG(saListener_ == nullptr, CameraErrorCode::SERVICE_FATL_ERROR, + CHECK_RETURN_RET_ELOG(listener == nullptr, CameraErrorCode::SERVICE_FATL_ERROR, "CameraManager::SubscribeSystemAbility saListener_ is null"); int32_t ret = samgr->SubscribeSystemAbility(CAMERA_SERVICE_ID, listener); MEDIA_INFO_LOG("SubscribeSystemAbility ret = %{public}d", ret); + if (ret == 0) { + saListener_ = listener; + } return ret == 0 ? CameraErrorCode::SUCCESS : CameraErrorCode::SERVICE_FATL_ERROR; } } @@ -1070,11 +1080,25 @@ int32_t CameraManager::UnSubscribeSystemAbility() auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); CHECK_RETURN_RET_ELOG(samgr == nullptr, CameraErrorCode::SERVICE_FATL_ERROR, "CameraManager::UnSubscribeSystemAbility Failed to get System ability manager"); - CHECK_RETURN_RET(saListener_ == nullptr, CameraErrorCode::SUCCESS); - sptr listener = static_cast(saListener_.GetRefPtr()); + sptr saListener = nullptr; + { + std::lock_guard lock(saListenerMuxtex_); + saListener = saListener_; + saListener_ = nullptr; + } + CHECK_RETURN_RET(saListener == nullptr, CameraErrorCode::SUCCESS); + sptr listener = static_cast(saListener.GetRefPtr()); int32_t ret = samgr->UnSubscribeSystemAbility(CAMERA_SERVICE_ID, listener); MEDIA_INFO_LOG("UnSubscribeSystemAbility ret = %{public}d", ret); - saListener_ = nullptr; + listener = nullptr; + uint32_t i = 0; + for (; i < MAX_SPTR_RELEASE_CHECK_TIMES; i++) { + if (saListener->GetRefCounter()->GetStrongRefCount() == 1) { + break; + } + std::this_thread::sleep_for(std::chrono::milliseconds(MAX_SPTR_RELEASE_CHECK_INTERVAL)); + } + MEDIA_INFO_LOG("after retry %{public}u times, saListener refCount: %{public}u", i, saListener->GetRefCounter()->GetStrongRefCount()); return ret == 0 ? CameraErrorCode::SUCCESS : CameraErrorCode::SERVICE_FATL_ERROR; } @@ -1115,6 +1139,18 @@ int32_t CameraManager::DestroyStubObj() CHECK_PRINT_ELOG(retCode != CAMERA_OK, "Failed to DestroyStubObj, retCode: %{public}d", retCode); } // LCOV_EXCL_STOP + std::lock_guard lock(listenerStubMutex_); + if (listenerStub_ != nullptr) { + uint32_t i = 0; + for (; i < MAX_SPTR_RELEASE_CHECK_TIMES; i++) { + if (listenerStub_->GetRefCounter()->GetStrongRefCount() == 1) { + break; + } + std::this_thread::sleep_for(std::chrono::milliseconds(MAX_SPTR_RELEASE_CHECK_INTERVAL)); + } + MEDIA_INFO_LOG("after retry %{public}u times, listenerStub refCount: %{public}u", i, listenerStub_->GetRefCounter()->GetStrongRefCount()); + listenerStub_ = nullptr; + } return ServiceToCameraError(retCode); } diff --git a/interfaces/inner_api/native/camera/include/input/camera_manager.h b/interfaces/inner_api/native/camera/include/input/camera_manager.h index 022c42c910e27e3f36ee4bf1cb9fbd61524e1bca..332f222dfdef831dcb34f4a45b2a0ce3189b9450 100644 --- a/interfaces/inner_api/native/camera/include/input/camera_manager.h +++ b/interfaces/inner_api/native/camera/include/input/camera_manager.h @@ -1164,6 +1164,8 @@ private: FoldStatus preFoldStatus = FoldStatus::UNKNOWN_FOLD; std::unordered_map> cameraOldCamera_; std::unordered_maprealtoVirtual_; + std::mutex listenerStubMutex_; + sptr listenerStub_ = nullptr; bool controlCenterFrameCondition_ = true; bool controlCenterResolutionCondition_ = true; bool controlCenterPositionCondition_ = true;