diff --git a/common/utils/include/distributed_hardware_errno.h b/common/utils/include/distributed_hardware_errno.h index 194d54486583806c2ed2ff73b37116f73caa18ad..4a244df3931688a690ab820011b7212d75ec5079 100644 --- a/common/utils/include/distributed_hardware_errno.h +++ b/common/utils/include/distributed_hardware_errno.h @@ -102,6 +102,7 @@ namespace DistributedHardware { constexpr int32_t ERR_DH_FWK_NO_HDF_SUPPORT = -10816; constexpr int32_t ERR_DH_FWK_ADD_DEATH_FAIL = -10817; constexpr int32_t ERR_DH_FWK_REMOVE_DEATH_FAIL = -10818; + constexpr int32_t ERR_DH_FWK_LOAD_CALLBACK_FAIL = -10819; /* AccessManager errno, range: [-10900, -10999] */ constexpr int32_t ERR_DH_FWK_ACCESS_INIT_DM_FAILED = -10900; diff --git a/interfaces/inner_kits/include/distributed_hardware_fwk_kit.h b/interfaces/inner_kits/include/distributed_hardware_fwk_kit.h index bb7d6678544e9bf9991f774c20b028c4891c7b6c..906561a2586c534292d727da3afb43969d4a04ec 100644 --- a/interfaces/inner_kits/include/distributed_hardware_fwk_kit.h +++ b/interfaces/inner_kits/include/distributed_hardware_fwk_kit.h @@ -269,8 +269,16 @@ private: */ bool IsQueryLocalSysSpecTypeValid(QueryLocalSysSpecType spec); + /** + * @brief Load distributed hardware SA. + * + * @return Returns 0 if success. + */ + int32_t LoadDistributedHardwareSA(); + private: std::atomic isDHFWKOnLine_; + std::mutex dfwkLoadServiceMutex_; }; } // namespace DistributedHardware } // namespace OHOS diff --git a/interfaces/inner_kits/src/distributed_hardware_fwk_kit.cpp b/interfaces/inner_kits/src/distributed_hardware_fwk_kit.cpp index 4e3880052b1709698e8bc62b7214c9247469f11d..3e2516c7d5f3a96f5af0d76c58e8cfafe2ab0bfe 100644 --- a/interfaces/inner_kits/src/distributed_hardware_fwk_kit.cpp +++ b/interfaces/inner_kits/src/distributed_hardware_fwk_kit.cpp @@ -25,9 +25,56 @@ #include "distributed_hardware_log.h" #include "dh_utils_hisysevent.h" #include "idistributed_hardware.h" +#include "iservice_registry.h" +#include "system_ability_definition.h" +#include "system_ability_load_callback_stub.h" namespace OHOS { namespace DistributedHardware { +namespace { +constexpr int32_t WAIT_TIME_MILL = 3000; +} + +class DFWKLoadCallback : public SystemAbilityLoadCallbackStub { +public: + void OnLoadSystemAbilitySuccess(int32_t systemAbilityId, const sptr &remoteObject); + void OnLoadSystemAbilityFail(int32_t systemAbilityId); + bool WaitLoadComplete(); +private: + bool isNotified_ = false; + bool isLoadSuccess_ = false; + std::mutex waitLoadCompleteMutex_; + std::condition_variable waitLoadCompleteCondVar_; +}; + +void DFWKLoadCallback::OnLoadSystemAbilitySuccess( + int32_t systemAbilityId, const sptr &remoteObject) +{ + std::unique_lock locker(waitLoadCompleteMutex_); + isNotified_ = true; + isLoadSuccess_ = true; + waitLoadCompleteCondVar_.notify_all(); +} + +void DFWKLoadCallback::OnLoadSystemAbilityFail(int32_t systemAbilityId) +{ + std::unique_lock locker(waitLoadCompleteMutex_); + isNotified_ = true; + isLoadSuccess_ = false; + waitLoadCompleteCondVar_.notify_all(); +} + +bool DFWKLoadCallback::WaitLoadComplete() +{ + std::unique_lock locker(waitLoadCompleteMutex_); + auto waitStatus = waitLoadCompleteCondVar_.wait_for(locker, std::chrono::milliseconds(WAIT_TIME_MILL), + [this]() { return isNotified_; }); + if (!waitStatus) { + DHLOGE("Load distributed hardware SA timeout."); + return false; + } + return isLoadSuccess_; +} std::string DumpDescriptors(const std::vector &descriptors) { @@ -138,6 +185,38 @@ bool DistributedHardwareFwkKit::IsQueryLocalSysSpecTypeValid(QueryLocalSysSpecTy return spec > QueryLocalSysSpecType::MIN && spec < QueryLocalSysSpecType::MAX; } +int32_t DistributedHardwareFwkKit::LoadDistributedHardwareSA() +{ + DHLOGI("Load distributed hardware SA begin!"); + std::unique_lock locker(dfwkLoadServiceMutex_); + sptr saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (saMgr == nullptr) { + DHLOGE("Failed to get system ability mgr."); + return ERR_DH_FWK_POINTER_IS_NULL; + } + sptr remote = saMgr->CheckSystemAbility(DISTRIBUTED_HARDWARE_SA_ID); + if (remote != nullptr) { + DHLOGI("DHFWK service has already been loaded!"); + return DH_FWK_SUCCESS; + } + sptr dfwkLoadCallback(new DFWKLoadCallback); + if (dfwkLoadCallback == nullptr) { + DHLOGE("Failed to create DFWK load callback."); + return ERR_DH_FWK_POINTER_IS_NULL; + } + int32_t ret = saMgr->LoadSystemAbility(DISTRIBUTED_HARDWARE_SA_ID, dfwkLoadCallback); + if (ret != DH_FWK_SUCCESS) { + DHLOGE("Failed to load DFWK service, ret: %{public}d", ret); + return ret; + } + if (!dfwkLoadCallback->WaitLoadComplete()) { + DHLOGE("Load DFWK service callback failed"); + return ERR_DH_FWK_LOAD_CALLBACK_FAIL; + } + DHLOGI("Load distributed hardware SA end!"); + return DH_FWK_SUCCESS; +} + std::string DistributedHardwareFwkKit::QueryLocalSysSpec(enum QueryLocalSysSpecType spec) { DHLOGI("Query Local Sys Spec, %{public}d", (uint32_t)spec); @@ -385,8 +464,15 @@ int32_t DistributedHardwareFwkKit::LoadDistributedHDF(const DHType dhType) { DHLOGI("Load distributed HDF, dhType: %{public}u.", dhType); if (DHFWKSAManager::GetInstance().GetDHFWKProxy() == nullptr) { - DHLOGI("DHFWK not online or get proxy failed, can not load distributed HDF."); - return ERR_DH_FWK_POINTER_IS_NULL; + DHLOGE("DHFWK not online or get proxy failed, try to load DFWK service."); + if (LoadDistributedHardwareSA() != DH_FWK_SUCCESS) { + DHLOGE("Load distributed hardware SA failed, can not load distributed HDF."); + return ERR_DH_FWK_POINTER_IS_NULL; + } + if (DHFWKSAManager::GetInstance().GetDHFWKProxy() == nullptr) { + DHLOGE("DHFWK already not online or get proxy failed yet, can not load distributed HDF."); + return ERR_DH_FWK_POINTER_IS_NULL; + } } return DHFWKSAManager::GetInstance().GetDHFWKProxy()->LoadDistributedHDF(dhType); } diff --git a/interfaces/inner_kits/test/unittest/common/distributedhardwarefwkkit/src/distributed_hardware_fwk_kit_test.cpp b/interfaces/inner_kits/test/unittest/common/distributedhardwarefwkkit/src/distributed_hardware_fwk_kit_test.cpp index 27ecfe959ad5d712e87110711fc6197e1ddba425..f329874640f870b871404d20b44f98e4df00604b 100644 --- a/interfaces/inner_kits/test/unittest/common/distributedhardwarefwkkit/src/distributed_hardware_fwk_kit_test.cpp +++ b/interfaces/inner_kits/test/unittest/common/distributedhardwarefwkkit/src/distributed_hardware_fwk_kit_test.cpp @@ -614,7 +614,7 @@ HWTEST_F(DistributedHardwareFwkKitTest, LoadDistributedHDF_001, testing::ext::Te { ASSERT_TRUE(dhfwkPtr_ != nullptr); int32_t ret = dhfwkPtr_->LoadDistributedHDF(DHType::CAMERA); - EXPECT_EQ(ERR_DH_FWK_POINTER_IS_NULL, ret); + EXPECT_EQ(ERR_DH_AVT_SERVICE_IPC_SEND_REQUEST_FAIL, ret); } /** @@ -627,7 +627,7 @@ HWTEST_F(DistributedHardwareFwkKitTest, UnLoadDistributedHDF_001, testing::ext:: { ASSERT_TRUE(dhfwkPtr_ != nullptr); int32_t ret = dhfwkPtr_->UnLoadDistributedHDF(DHType::CAMERA); - EXPECT_EQ(ERR_DH_FWK_POINTER_IS_NULL, ret); + EXPECT_EQ(ERR_DH_AVT_SERVICE_IPC_SEND_REQUEST_FAIL, ret); } } // namespace DistributedHardware } // namespace OHOS \ No newline at end of file diff --git a/services/distributedhardwarefwkservice/BUILD.gn b/services/distributedhardwarefwkservice/BUILD.gn index d1464005a109fc1b18dc1e395fce50c2e66d0cd4..3fb8c7a35366928680e5d1394ed3defe2f49cd1d 100644 --- a/services/distributedhardwarefwkservice/BUILD.gn +++ b/services/distributedhardwarefwkservice/BUILD.gn @@ -97,6 +97,7 @@ ohos_shared_library("distributedhardwarefwksvr") { "src/resourcemanager/version_info_manager.cpp", "src/task/disable_task.cpp", "src/task/enable_task.cpp", + "src/task/exit_dfwk_task.cpp", "src/task/meta_disable_task.cpp", "src/task/meta_enable_task.cpp", "src/task/offline_task.cpp", diff --git a/services/distributedhardwarefwkservice/include/distributed_hardware_manager_factory.h b/services/distributedhardwarefwkservice/include/distributed_hardware_manager_factory.h index 3eb5557737184df42579d4630e563ea81db3cc1a..a2d67a60637ce41f3d2e8e827e7bf41c1d31bde6 100644 --- a/services/distributedhardwarefwkservice/include/distributed_hardware_manager_factory.h +++ b/services/distributedhardwarefwkservice/include/distributed_hardware_manager_factory.h @@ -44,9 +44,9 @@ public: bool GetUnInitFlag(); void SetSAProcessState(bool saState); bool GetSAProcessState(); + void CheckExitSAOrNot(); private: bool Init(); - void CheckExitSAOrNot(); void ExitDHFWK(); private: diff --git a/services/distributedhardwarefwkservice/include/hdfoperate/hdf_operate.h b/services/distributedhardwarefwkservice/include/hdfoperate/hdf_operate.h index c6b6a3b3a043be74a9cf4b73ec7f27b1d65b85dc..11439ebf19da12c8f8f7c81188d51638740774a5 100644 --- a/services/distributedhardwarefwkservice/include/hdfoperate/hdf_operate.h +++ b/services/distributedhardwarefwkservice/include/hdfoperate/hdf_operate.h @@ -54,6 +54,7 @@ public: int32_t LoadDistributedHDF(); int32_t UnLoadDistributedHDF(); void ResetRefCount(); + bool IsNeedErase(); private: DHType dhType_ = DHType::UNKNOWN; int32_t hdfLoadRef_ = 0; @@ -70,12 +71,25 @@ public: int32_t AddDeathRecipient(DHType dhType, sptr &remote); int32_t RemoveDeathRecipient(DHType dhType, sptr &remote); void ResetRefCount(DHType dhType); + int32_t RigidGetSourcePtr(DHType dhType, IDistributedHardwareSource *&sourcePtr); + int32_t RigidReleaseSourcePtr(DHType dhType); + bool IsAnyHdfInuse(); + +private: + struct SourceHandlerData { + int32_t refCount; + void *sourceHandler; + IDistributedHardwareSource *sourcePtr; + }; private: std::mutex hdfOperateMapMutex_; std::map> hdfOperateMap_; sptr audioHdfLoadRefRecipient_ = sptr(new HdfLoadRefRecipient(DHType::AUDIO)); sptr cameraHdfLoadRefRecipient_ = sptr(new HdfLoadRefRecipient(DHType::CAMERA)); + std::mutex sourceHandlerDataMapMutex_; + std::map sourceHandlerDataMap_; + int32_t hdfInuseRefCount_ = 0; }; } // namespace DistributedHardware } // namespace OHOS diff --git a/services/distributedhardwarefwkservice/include/task/exit_dfwk_task.h b/services/distributedhardwarefwkservice/include/task/exit_dfwk_task.h new file mode 100644 index 0000000000000000000000000000000000000000..12532f673ef18c53273c397f5a4765ddb34ad583 --- /dev/null +++ b/services/distributedhardwarefwkservice/include/task/exit_dfwk_task.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DISTRIBUTED_HARDWARE_EXIT_DFWK_TASK_H +#define OHOS_DISTRIBUTED_HARDWARE_EXIT_DFWK_TASK_H + +#include "task.h" + +namespace OHOS { +namespace DistributedHardware { +class ExitDfwkTask : public Task { +public: + ExitDfwkTask() = delete; + ExitDfwkTask(const std::string &networkId, const std::string &uuid, const std::string &udid, + const std::string &dhId, const DHType dhType); + virtual ~ExitDfwkTask(); + virtual void DoTask(); + +private: + void DoTaskInner(); +}; +} // namespace DistributedHardware +} // namespace OHOS +#endif diff --git a/services/distributedhardwarefwkservice/include/task/task_factory.h b/services/distributedhardwarefwkservice/include/task/task_factory.h index c733bd8d1a825facc2cae2e411775376af2551ec..f515ef1b77f9254611e63b729146a1c61ac682e2 100644 --- a/services/distributedhardwarefwkservice/include/task/task_factory.h +++ b/services/distributedhardwarefwkservice/include/task/task_factory.h @@ -30,6 +30,8 @@ public: private: std::shared_ptr CreateEnableTask(const TaskParam &taskParam); std::shared_ptr CreateDisableTask(const TaskParam &taskParam); + std::shared_ptr CreateTaskEx(TaskType taskType, + const TaskParam &taskParam, std::shared_ptr fatherTask); }; } // namespace DistributedHardware } // namespace OHOS diff --git a/services/distributedhardwarefwkservice/include/utils/impl_utils.h b/services/distributedhardwarefwkservice/include/utils/impl_utils.h index e10a675f00cf696ddcf4b2f4302c994b28f74b32..ecfcd95467ebd773f4f6cbce514ae3af0cd8283e 100644 --- a/services/distributedhardwarefwkservice/include/utils/impl_utils.h +++ b/services/distributedhardwarefwkservice/include/utils/impl_utils.h @@ -30,7 +30,8 @@ enum class TaskType : int32_t { ON_LINE = 3, OFF_LINE = 4, META_ENABLE = 5, - META_DISABLE = 6 + META_DISABLE = 6, + EXIT_DFWK = 7 }; enum class TaskStep : int32_t { diff --git a/services/distributedhardwarefwkservice/src/distributed_hardware_manager_factory.cpp b/services/distributedhardwarefwkservice/src/distributed_hardware_manager_factory.cpp index ae1f57c35f39ffa656870ceae4198205ca19e9e9..44b909d0f5f417388c740813c6ac78e95dc988e7 100644 --- a/services/distributedhardwarefwkservice/src/distributed_hardware_manager_factory.cpp +++ b/services/distributedhardwarefwkservice/src/distributed_hardware_manager_factory.cpp @@ -38,8 +38,12 @@ #include "distributed_hardware_log.h" #include "distributed_hardware_manager.h" #include "device_param_mgr.h" +#include "hdf_operate.h" #include "local_capability_info_manager.h" #include "meta_info_manager.h" +#include "task_board.h" +#include "task_executor.h" +#include "task_factory.h" namespace OHOS { namespace DistributedHardware { @@ -65,15 +69,10 @@ bool DistributedHardwareManagerFactory::InitLocalDevInfo() DHLOGE("InitLocalDevInfo failed, errCode = %{public}d", initResult); return false; } - DHLOGI("InitLocalDevInfo success, check is need exit"); - - deviceList.clear(); - DeviceManager::GetInstance().GetTrustedDeviceList(DH_FWK_PKG_NAME, "", deviceList); - if ((deviceList.size() == 0 || deviceList.size() > MAX_ONLINE_DEVICE_SIZE) && - DHContext::GetInstance().GetIsomerismConnectCount() == 0) { - DHLOGI("After InitLocalDevInfo, no device online, exit dhfwk"); - ExitDHFWK(); - } + DHLOGI("init local dev info, create exit dfwk task!"); + TaskParam taskParam; + auto task = TaskFactory::GetInstance().CreateTask(TaskType::EXIT_DFWK, taskParam, nullptr); + TaskExecutor::GetInstance().PushTask(task); return true; } @@ -136,7 +135,8 @@ void DistributedHardwareManagerFactory::CheckExitSAOrNot() std::vector deviceList; DeviceManager::GetInstance().GetTrustedDeviceList(DH_FWK_PKG_NAME, "", deviceList); if ((deviceList.size() == 0 || deviceList.size() > MAX_ONLINE_DEVICE_SIZE) && - DHContext::GetInstance().GetIsomerismConnectCount() == 0) { + DHContext::GetInstance().GetIsomerismConnectCount() == 0 && + HdfOperateManager::GetInstance().IsAnyHdfInuse() == false) { ExitDHFWK(); return; } diff --git a/services/distributedhardwarefwkservice/src/hdfoperate/hdf_operate.cpp b/services/distributedhardwarefwkservice/src/hdfoperate/hdf_operate.cpp index 6e5e57423c37c137786268aa512ca8b8ac298528..e465fee177a96b55efefe95f43dd962b7149f3fe 100644 --- a/services/distributedhardwarefwkservice/src/hdfoperate/hdf_operate.cpp +++ b/services/distributedhardwarefwkservice/src/hdfoperate/hdf_operate.cpp @@ -15,15 +15,22 @@ #include "hdf_operate.h" +#include + #include "component_loader.h" #include "distributed_hardware_errno.h" #include "distributed_hardware_log.h" +#include "task_board.h" +#include "task_executor.h" +#include "task_factory.h" #undef DH_LOG_TAG #define DH_LOG_TAG "HdfOperator" namespace OHOS { namespace DistributedHardware { +using GetSourceHardwareClass = IDistributedHardwareSource *(*)(); + int32_t HdfOperator::LoadDistributedHDF() { DHLOGI("Load hdf impl begin, dhType = %{public}#X!", dhType_); @@ -73,6 +80,12 @@ void HdfOperator::ResetRefCount() hdfLoadRef_ = 0; } +bool HdfOperator::IsNeedErase() +{ + std::unique_lock loadRefLocker(hdfLoadRefMutex_); + return hdfLoadRef_ <= 0; +} + IMPLEMENT_SINGLE_INSTANCE(HdfOperateManager); int32_t HdfOperateManager::LoadDistributedHDF(DHType dhType) @@ -85,7 +98,11 @@ int32_t HdfOperateManager::LoadDistributedHDF(DHType dhType) auto ret = ComponentLoader::GetInstance().GetSource(dhType, sourcePtr); if (ret != DH_FWK_SUCCESS) { DHLOGE("GetSource failed, compType = %{public}#X, ret = %{public}d.", dhType, ret); - return ret; + ret = RigidGetSourcePtr(dhType, sourcePtr); + if (ret != DH_FWK_SUCCESS) { + DHLOGE("RigidGetSourcePtr failed, compType = %{public}#X, ret = %{public}d.", dhType, ret); + return ret; + } } auto result = hdfOperateMap_.insert( std::pair>( @@ -93,7 +110,15 @@ int32_t HdfOperateManager::LoadDistributedHDF(DHType dhType) itHdfOperate = result.first; } auto hdfOperate = itHdfOperate->second; - return hdfOperate->LoadDistributedHDF(); + if (hdfOperate == nullptr) { + DHLOGE("Get hdf operator is nullptr, dhType = %{public}#X.", dhType); + return ERR_DH_FWK_POINTER_IS_NULL; + } + auto ret = hdfOperate->LoadDistributedHDF(); + if (ret == DH_FWK_SUCCESS) { + hdfInuseRefCount_++; + } + return ret; } int32_t HdfOperateManager::UnLoadDistributedHDF(DHType dhType) @@ -106,7 +131,27 @@ int32_t HdfOperateManager::UnLoadDistributedHDF(DHType dhType) return DH_FWK_SUCCESS; } auto hdfOperate = itHdfOperate->second; - return hdfOperate->UnLoadDistributedHDF(); + if (hdfOperate == nullptr) { + DHLOGE("Get hdf operator is nullptr, dhType = %{public}#X.", dhType); + return ERR_DH_FWK_POINTER_IS_NULL; + } + auto ret = hdfOperate->UnLoadDistributedHDF(); + if (ret == DH_FWK_SUCCESS) { + if (hdfOperate->IsNeedErase()) { + hdfOperateMap_.erase(itHdfOperate); + } + if (RigidReleaseSourcePtr(dhType) != DH_FWK_SUCCESS) { + DHLOGE("RigidReleaseSourcePtr failed, dhType = %{public}#X.", dhType); + } + hdfInuseRefCount_--; + if (hdfInuseRefCount_ <= 0) { + DHLOGI("hdf inuse refcount less than 0, create exit dfwk task!"); + TaskParam taskParam; + auto task = TaskFactory::GetInstance().CreateTask(TaskType::EXIT_DFWK, taskParam, nullptr); + TaskExecutor::GetInstance().PushTask(task); + } + } + return ret; } int32_t HdfOperateManager::AddDeathRecipient(DHType dhType, sptr &remote) @@ -169,6 +214,87 @@ void HdfOperateManager::ResetRefCount(DHType dhType) DHLOGI("reset ref count end, dhType = %{public}#X!", dhType); } +int32_t HdfOperateManager::RigidGetSourcePtr(DHType dhType, IDistributedHardwareSource *&sourcePtr) +{ + DHLOGI("Rigid get source ptr begin, dhType = %{public}#X!", dhType); + std::lock_guard locker(sourceHandlerDataMapMutex_); + auto itSourceHandlerData = sourceHandlerDataMap_.find(dhType); + if (itSourceHandlerData != sourceHandlerDataMap_.end()) { + auto &sourceHandlerData = itSourceHandlerData->second; + sourcePtr = sourceHandlerData.sourcePtr; + sourceHandlerData.refCount++; + DHLOGI("Source ptr already exists, only increase reference count, dhType = %{public}#X!", dhType); + return DH_FWK_SUCCESS; + } + std::string compSourceLoc; + switch (dhType) { + case DHType::AUDIO: + compSourceLoc = "libdistributed_audio_source_sdk.z.so"; + break; + case DHType::CAMERA: + compSourceLoc = "libdistributed_camera_source_sdk.z.so"; + break; + default: + DHLOGE("No hdf support, dhType = %{public}#X.", dhType); + return ERR_DH_FWK_NO_HDF_SUPPORT; + } + void *sourceHandler = dlopen(compSourceLoc.c_str(), RTLD_LAZY | RTLD_NODELETE); + if (sourceHandler == nullptr) { + DHLOGE("dlopen failed, failed reason: %{public}s, dhType: %{public}" PRIu32, dlerror(), (uint32_t)dhType); + return ERR_DH_FWK_LOADER_HANDLER_IS_NULL; + } + auto getSourceHardClassHandler = (GetSourceHardwareClass)dlsym( + sourceHandler, COMPONENT_LOADER_GET_SOURCE_HANDLER.c_str()); + if (getSourceHardClassHandler == nullptr) { + DHLOGE("get getSourceHardClassHandler is null, failed reason : %{public}s", dlerror()); + dlclose(sourceHandler); + sourceHandler = nullptr; + return ERR_DH_FWK_LOADER_HANDLER_IS_NULL; + } + sourcePtr = getSourceHardClassHandler(); + if (sourcePtr == nullptr) { + DHLOGE("getSourceHardClassHandler return null!"); + dlclose(sourceHandler); + sourceHandler = nullptr; + return ERR_DH_FWK_LOADER_HANDLER_IS_NULL; + } + sourceHandlerDataMap_[dhType] = SourceHandlerData { + .refCount = 1, .sourceHandler = sourceHandler, .sourcePtr = sourcePtr + }; + DHLOGI("Rigid get source ptr end, dhType = %{public}#X!", dhType); + return DH_FWK_SUCCESS; +} + +int32_t HdfOperateManager::RigidReleaseSourcePtr(DHType dhType) +{ + DHLOGI("Rigid release source ptr begin, dhType = %{public}#X!", dhType); + std::lock_guard locker(sourceHandlerDataMapMutex_); + auto itSourceHandlerData = sourceHandlerDataMap_.find(dhType); + if (itSourceHandlerData == sourceHandlerDataMap_.end()) { + DHLOGI("The source ptr has not been obtained yet, dhType = %{public}#X!", dhType); + return DH_FWK_SUCCESS; + } + auto &sourceHandlerData = itSourceHandlerData->second; + if (sourceHandlerData.refCount > 1) { + sourceHandlerData.refCount--; + DHLOGI("Source ptr is still in use, only reducing reference count, dhType = %{public}#X!", dhType); + return DH_FWK_SUCCESS; + } + if (dlclose(sourceHandlerData.sourceHandler) != 0) { + DHLOGE("dlclose failed, failed reason: %{public}s, dhType: %{public}" PRIu32, dlerror(), (uint32_t)dhType); + return ERR_DH_FWK_LOADER_DLCLOSE_FAIL; + } + sourceHandlerDataMap_.erase(itSourceHandlerData); + DHLOGI("Rigid release source ptr end, dhType = %{public}#X!", dhType); + return DH_FWK_SUCCESS; +} + +bool HdfOperateManager::IsAnyHdfInuse() +{ + std::unique_lock hdfOperateMapLocker(hdfOperateMapMutex_); + return hdfInuseRefCount_ > 0; +} + void HdfLoadRefRecipient::OnRemoteDied(const wptr &remote) { DHLOGI("On remote died, dhType = %{public}#X!", dhType_); diff --git a/services/distributedhardwarefwkservice/src/task/exit_dfwk_task.cpp b/services/distributedhardwarefwkservice/src/task/exit_dfwk_task.cpp new file mode 100644 index 0000000000000000000000000000000000000000..29feb4f5259e3f8971359fedcaefaad8c53e7529 --- /dev/null +++ b/services/distributedhardwarefwkservice/src/task/exit_dfwk_task.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "exit_dfwk_task.h" + +#include +#include + +#include "ffrt.h" + +#include "anonymous_string.h" +#include "distributed_hardware_errno.h" +#include "distributed_hardware_log.h" +#include "distributed_hardware_manager_factory.h" +#include "task_board.h" + +namespace OHOS { +namespace DistributedHardware { + +#undef DH_LOG_TAG +#define DH_LOG_TAG "ExitDfwkTask" + +namespace { +constexpr int32_t WAIT_TIME_SEC = 5; +} + +ExitDfwkTask::ExitDfwkTask(const std::string &networkId, const std::string &uuid, const std::string &udid, + const std::string &dhId, const DHType dhType) : Task(networkId, uuid, udid, dhId, dhType) +{ + SetTaskType(TaskType::EXIT_DFWK); + DHLOGD("ExitDfwkTask id: %{public}s", GetId().c_str()); +} + +ExitDfwkTask::~ExitDfwkTask() +{ + DHLOGD("id = %{public}s", GetId().c_str()); +} + +void ExitDfwkTask::DoTask() +{ + ffrt::submit([this]() { this->DoTaskInner(); }); +} + +void ExitDfwkTask::DoTaskInner() +{ + DHLOGI("do exit dfwk task bebin!"); + std::this_thread::sleep_for(std::chrono::seconds(WAIT_TIME_SEC)); + DistributedHardwareManagerFactory::GetInstance().CheckExitSAOrNot(); + DHLOGI("do exit dfwk task end!"); +} +} // namespace DistributedHardware +} // namespace OHOS diff --git a/services/distributedhardwarefwkservice/src/task/task_factory.cpp b/services/distributedhardwarefwkservice/src/task/task_factory.cpp index 27f791c708e1c6b90977f0251e1b48c1e1cc76f0..8b4909b36caec5452916e863f354ad161b351db1 100644 --- a/services/distributedhardwarefwkservice/src/task/task_factory.cpp +++ b/services/distributedhardwarefwkservice/src/task/task_factory.cpp @@ -19,6 +19,7 @@ #include "disable_task.h" #include "distributed_hardware_log.h" #include "enable_task.h" +#include "exit_dfwk_task.h" #include "meta_disable_task.h" #include "meta_enable_task.h" #include "offline_task.h" @@ -56,28 +57,20 @@ std::shared_ptr TaskFactory::CreateTask(TaskType taskType, TaskParam taskP taskParam.dhId, taskParam.dhType); break; } - case TaskType::META_ENABLE: { - task = std::make_shared(taskParam.networkId, taskParam.uuid, taskParam.udid, - taskParam.dhId, taskParam.dhType); - break; - } - case TaskType::META_DISABLE: { - task = std::make_shared(taskParam.networkId, taskParam.uuid, taskParam.udid, - taskParam.dhId, taskParam.dhType); - break; - } default: { - DHLOGE("CreateTask type invalid, type: %{public}d", taskType); - return nullptr; + task = CreateTaskEx(taskType, taskParam, fatherTask); + break; } } - + if (task == nullptr) { + DHLOGE("Create task failed, task is nullptr, type: %{public}d", taskType); + return task; + } if (fatherTask != nullptr) { task->SetFatherTask(fatherTask); fatherTask->AddChildrenTask(task); } TaskBoard::GetInstance().AddTask(task); - return task; } @@ -106,5 +99,33 @@ std::shared_ptr TaskFactory::CreateDisableTask(const TaskParam &taskParam) } return disableTask; } + +std::shared_ptr TaskFactory::CreateTaskEx(TaskType taskType, + const TaskParam &taskParam, std::shared_ptr fatherTask) +{ + std::shared_ptr task = nullptr; + switch (taskType) { + case TaskType::META_ENABLE: { + task = std::make_shared(taskParam.networkId, taskParam.uuid, taskParam.udid, + taskParam.dhId, taskParam.dhType); + break; + } + case TaskType::META_DISABLE: { + task = std::make_shared(taskParam.networkId, taskParam.uuid, taskParam.udid, + taskParam.dhId, taskParam.dhType); + break; + } + case TaskType::EXIT_DFWK: { + task = std::make_shared(taskParam.networkId, taskParam.uuid, taskParam.udid, + taskParam.dhId, taskParam.dhType); + break; + } + default: { + DHLOGE("CreateTask type invalid, type: %{public}d", taskType); + return nullptr; + } + } + return task; +} } // namespace DistributedHardware } // namespace OHOS diff --git a/services/distributedhardwarefwkservice/test/unittest/common/hdfoperate/hdf_operate_test.cpp b/services/distributedhardwarefwkservice/test/unittest/common/hdfoperate/hdf_operate_test.cpp index 363013d3496031510c61aa67ddb549519229edff..1a2459c42b51bb4a7c2c73e78975f290ae3b5e30 100644 --- a/services/distributedhardwarefwkservice/test/unittest/common/hdfoperate/hdf_operate_test.cpp +++ b/services/distributedhardwarefwkservice/test/unittest/common/hdfoperate/hdf_operate_test.cpp @@ -110,6 +110,36 @@ HWTEST_F(HdfOperateTest, LoadDistributedHDF_001, TestSize.Level1) SetDownComponentLoaderConfig(); } +#ifndef DHARDWARE_CLOSE_UT +/** + * @tc.name: LoadDistributedHDF_002 + * @tc.desc: Verify LoadDistributedHDF func + * @tc.type: FUNC + * @tc.require: AR000GHSJM + */ +HWTEST_F(HdfOperateTest, LoadDistributedHDF_002, TestSize.Level1) +{ + DHLOGI("HdfOperateTest::LoadDistributedHDF_002"); + EXPECT_EQ(DH_FWK_SUCCESS, HdfOperateManager::GetInstance().LoadDistributedHDF(DHType::AUDIO)); + EXPECT_EQ(DH_FWK_SUCCESS, HdfOperateManager::GetInstance().UnLoadDistributedHDF(DHType::AUDIO)); +} +#endif + +/** + * @tc.name: LoadDistributedHDF_003 + * @tc.desc: Verify LoadDistributedHDF func + * @tc.type: FUNC + * @tc.require: AR000GHSJM + */ +HWTEST_F(HdfOperateTest, LoadDistributedHDF_003, TestSize.Level1) +{ + DHLOGI("HdfOperateTest::LoadDistributedHDF_003"); + HdfOperateManager::GetInstance().hdfOperateMap_[DHType::AUDIO] = nullptr; + int32_t ret = HdfOperateManager::GetInstance().LoadDistributedHDF(DHType::AUDIO); + HdfOperateManager::GetInstance().hdfOperateMap_.clear(); + EXPECT_EQ(ERR_DH_FWK_POINTER_IS_NULL, ret); +} + /** * @tc.name: UnLoadDistributedHDF_001 * @tc.desc: Verify UnLoadDistributedHDF func @@ -124,6 +154,21 @@ HWTEST_F(HdfOperateTest, UnLoadDistributedHDF_001, TestSize.Level1) EXPECT_EQ(DH_FWK_SUCCESS, ret); } +/** + * @tc.name: UnLoadDistributedHDF_002 + * @tc.desc: Verify UnLoadDistributedHDF func + * @tc.type: FUNC + * @tc.require: AR000GHSJM + */ +HWTEST_F(HdfOperateTest, UnLoadDistributedHDF_002, TestSize.Level1) +{ + DHLOGI("HdfOperateTest::UnLoadDistributedHDF_002"); + HdfOperateManager::GetInstance().hdfOperateMap_[DHType::AUDIO] = nullptr; + int32_t ret = HdfOperateManager::GetInstance().UnLoadDistributedHDF(DHType::AUDIO); + HdfOperateManager::GetInstance().hdfOperateMap_.clear(); + EXPECT_EQ(ERR_DH_FWK_POINTER_IS_NULL, ret); +} + /** * @tc.name: ResetRefCount_001 * @tc.desc: Verify ResetRefCount func @@ -145,5 +190,45 @@ HWTEST_F(HdfOperateTest, ResetRefCount_001, TestSize.Level1) SetDownComponentLoaderConfig(); EXPECT_EQ(DH_FWK_SUCCESS, ret); } + +/** + * @tc.name: RigidGetSourcePtr_001 + * @tc.desc: Verify RigidGetSourcePtr func + * @tc.type: FUNC + * @tc.require: AR000GHSJM + */ +HWTEST_F(HdfOperateTest, RigidGetSourcePtr_001, TestSize.Level1) +{ + DHLOGI("HdfOperateTest::RigidGetSourcePtr_001"); + IDistributedHardwareSource *sourcePtr = nullptr; + EXPECT_EQ(DH_FWK_SUCCESS, HdfOperateManager::GetInstance().RigidGetSourcePtr(DHType::AUDIO, sourcePtr)); + EXPECT_EQ(DH_FWK_SUCCESS, HdfOperateManager::GetInstance().RigidGetSourcePtr(DHType::AUDIO, sourcePtr)); + EXPECT_EQ(DH_FWK_SUCCESS, HdfOperateManager::GetInstance().RigidReleaseSourcePtr(DHType::AUDIO)); + EXPECT_EQ(DH_FWK_SUCCESS, HdfOperateManager::GetInstance().RigidReleaseSourcePtr(DHType::AUDIO)); + EXPECT_EQ(DH_FWK_SUCCESS, HdfOperateManager::GetInstance().RigidGetSourcePtr(DHType::CAMERA, sourcePtr)); + EXPECT_EQ(DH_FWK_SUCCESS, HdfOperateManager::GetInstance().RigidGetSourcePtr(DHType::CAMERA, sourcePtr)); + EXPECT_EQ(DH_FWK_SUCCESS, HdfOperateManager::GetInstance().RigidReleaseSourcePtr(DHType::CAMERA)); + EXPECT_EQ(DH_FWK_SUCCESS, HdfOperateManager::GetInstance().RigidReleaseSourcePtr(DHType::CAMERA)); + EXPECT_EQ(ERR_DH_FWK_NO_HDF_SUPPORT, + HdfOperateManager::GetInstance().RigidGetSourcePtr(DHType::UNKNOWN, sourcePtr)); +} + +/** + * @tc.name: RigidReleaseSourcePtr_001 + * @tc.desc: Verify RigidReleaseSourcePtr func + * @tc.type: FUNC + * @tc.require: AR000GHSJM + */ +HWTEST_F(HdfOperateTest, RigidReleaseSourcePtr_001, TestSize.Level1) +{ + DHLOGI("HdfOperateTest::RigidReleaseSourcePtr_001"); + EXPECT_EQ(DH_FWK_SUCCESS, HdfOperateManager::GetInstance().RigidReleaseSourcePtr(DHType::AUDIO)); + HdfOperateManager::GetInstance().sourceHandlerDataMap_[DHType::AUDIO] = HdfOperateManager::SourceHandlerData { + .refCount = 1, .sourceHandler = nullptr, .sourcePtr = nullptr + }; + auto ret = HdfOperateManager::GetInstance().RigidReleaseSourcePtr(DHType::AUDIO); + HdfOperateManager::GetInstance().sourceHandlerDataMap_.erase(DHType::AUDIO); + EXPECT_EQ(ERR_DH_FWK_LOADER_DLCLOSE_FAIL, ret); +} } // namespace DistributedHardware } // namespace OHOS diff --git a/services/distributedhardwarefwkservice/test/unittest/common/task/src/task_test.cpp b/services/distributedhardwarefwkservice/test/unittest/common/task/src/task_test.cpp index 5179354f349fdc9a0f76fd706e9fa39e4e0d18c9..900c0f67a43f4f19bba3e3eac2d91df6e1fdee17 100644 --- a/services/distributedhardwarefwkservice/test/unittest/common/task/src/task_test.cpp +++ b/services/distributedhardwarefwkservice/test/unittest/common/task/src/task_test.cpp @@ -405,5 +405,24 @@ HWTEST_F(TaskTest, task_test_023, TestSize.Level1) task->DoTask(); ASSERT_EQ(true, task->childrenTasks_.empty()); } + +HWTEST_F(TaskTest, task_test_024, TestSize.Level1) +{ + TaskParam taskParam; + std::shared_ptr fatherTask = + std::make_shared("networkId", "uuid", "udid", "dhId", DHType::CAMERA); + auto task = TaskFactory::GetInstance().CreateTask(TaskType::META_DISABLE, taskParam, fatherTask); + task->DoTask(); + ASSERT_TRUE(task->childrenTasks_.empty()); +} + +HWTEST_F(TaskTest, task_test_025, TestSize.Level1) +{ + TaskParam taskParam; + std::shared_ptr fatherTask = + std::make_shared("networkId", "uuid", "udid", "dhId", DHType::CAMERA); + auto task = TaskFactory::GetInstance().CreateTask(TaskType::UNKNOWN, taskParam, fatherTask); + ASSERT_EQ(nullptr, task); +} } // namespace DistributedHardware } // namespace OHOS