1 /*
2 * Copyright (c) 2022-2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "hdf_operate.h"
17
18 #include <dlfcn.h>
19
20 #include "component_loader.h"
21 #include "distributed_hardware_errno.h"
22 #include "distributed_hardware_log.h"
23 #include "task_board.h"
24 #include "task_executor.h"
25 #include "task_factory.h"
26
27 #undef DH_LOG_TAG
28 #define DH_LOG_TAG "HdfOperator"
29
30 namespace OHOS {
31 namespace DistributedHardware {
32 using GetSourceHardwareClass = IDistributedHardwareSource *(*)();
33
LoadDistributedHDF()34 int32_t HdfOperator::LoadDistributedHDF()
35 {
36 DHLOGI("Load hdf impl begin, dhType = %{public}#X!", dhType_);
37 std::unique_lock<std::mutex> loadRefLocker(hdfLoadRefMutex_);
38 if (hdfLoadRef_ > 0) {
39 hdfLoadRef_++;
40 DHLOGI("The hdf impl has been loaded, just inc ref, dhType = %{public}#X!", dhType_);
41 return DH_FWK_SUCCESS;
42 }
43 auto ret = sourcePtr_->LoadDistributedHDF(hdfDeathCallback_);
44 if (ret != DH_FWK_SUCCESS) {
45 DHLOGE("Source handler load hdf failed, dhType = %{public}#X, ret = %{public}d.", dhType_, ret);
46 return ret;
47 }
48 hdfLoadRef_++;
49 DHLOGI("Load hdf impl end, dhType = %{public}#X!", dhType_);
50 return DH_FWK_SUCCESS;
51 }
52
UnLoadDistributedHDF()53 int32_t HdfOperator::UnLoadDistributedHDF()
54 {
55 DHLOGI("UnLoad hdf impl begin, dhType = %{public}#X!", dhType_);
56 std::unique_lock<std::mutex> loadRefLocker(hdfLoadRefMutex_);
57 if (hdfLoadRef_ <= 0) {
58 DHLOGI("The hdf impl has been unloaded, dhType = %{public}#X!", dhType_);
59 return DH_FWK_SUCCESS;
60 }
61 if (hdfLoadRef_ > 1) {
62 hdfLoadRef_--;
63 DHLOGI("The hdf impl has been loaded, just dec ref, dhType = %{public}#X!", dhType_);
64 return DH_FWK_SUCCESS;
65 }
66 auto ret = sourcePtr_->UnLoadDistributedHDF();
67 if (ret != DH_FWK_SUCCESS) {
68 DHLOGE("Source handler unload hdf failed, dhType = %{public}#X, ret = %{public}d.", dhType_, ret);
69 return ret;
70 }
71 hdfLoadRef_--;
72 DHLOGI("UnLoad hdf impl end, dhType = %{public}#X!", dhType_);
73 return DH_FWK_SUCCESS;
74 }
75
ResetRefCount()76 void HdfOperator::ResetRefCount()
77 {
78 DHLOGI("Reset reference count, dhType = %{public}#X!", dhType_);
79 std::unique_lock<std::mutex> loadRefLocker(hdfLoadRefMutex_);
80 hdfLoadRef_ = 0;
81 }
82
IsNeedErase()83 bool HdfOperator::IsNeedErase()
84 {
85 std::unique_lock<std::mutex> loadRefLocker(hdfLoadRefMutex_);
86 return hdfLoadRef_ <= 0;
87 }
88
89 IMPLEMENT_SINGLE_INSTANCE(HdfOperateManager);
90
LoadDistributedHDF(DHType dhType)91 int32_t HdfOperateManager::LoadDistributedHDF(DHType dhType)
92 {
93 DHLOGI("HdfOperateManager load hdf, dhType = %{public}#X!", dhType);
94 std::unique_lock<std::mutex> hdfOperateMapLocker(hdfOperateMapMutex_);
95 auto itHdfOperate = hdfOperateMap_.find(dhType);
96 if (itHdfOperate == hdfOperateMap_.end()) {
97 IDistributedHardwareSource *sourcePtr = nullptr;
98 auto ret = ComponentLoader::GetInstance().GetSource(dhType, sourcePtr);
99 if (ret != DH_FWK_SUCCESS) {
100 DHLOGE("GetSource failed, compType = %{public}#X, ret = %{public}d.", dhType, ret);
101 ret = RigidGetSourcePtr(dhType, sourcePtr);
102 if (ret != DH_FWK_SUCCESS) {
103 DHLOGE("RigidGetSourcePtr failed, compType = %{public}#X, ret = %{public}d.", dhType, ret);
104 return ret;
105 }
106 }
107 auto result = hdfOperateMap_.insert(
108 std::pair<DHType, std::shared_ptr<HdfOperator>>(
109 dhType, std::make_shared<HdfOperator>(dhType, sourcePtr)));
110 itHdfOperate = result.first;
111 }
112 auto hdfOperate = itHdfOperate->second;
113 if (hdfOperate == nullptr) {
114 DHLOGE("Get hdf operator is nullptr, dhType = %{public}#X.", dhType);
115 return ERR_DH_FWK_POINTER_IS_NULL;
116 }
117 auto ret = hdfOperate->LoadDistributedHDF();
118 if (ret == DH_FWK_SUCCESS) {
119 hdfInuseRefCount_++;
120 }
121 return ret;
122 }
123
UnLoadDistributedHDF(DHType dhType)124 int32_t HdfOperateManager::UnLoadDistributedHDF(DHType dhType)
125 {
126 DHLOGI("HdfOperateManager unload hdf, dhType = %{public}#X!", dhType);
127 std::unique_lock<std::mutex> hdfOperateMapLocker(hdfOperateMapMutex_);
128 auto itHdfOperate = hdfOperateMap_.find(dhType);
129 if (itHdfOperate == hdfOperateMap_.end()) {
130 DHLOGI("The hdf operate has not been created yet, dhType = %{public}#X!", dhType);
131 return DH_FWK_SUCCESS;
132 }
133 auto hdfOperate = itHdfOperate->second;
134 if (hdfOperate == nullptr) {
135 DHLOGE("Get hdf operator is nullptr, dhType = %{public}#X.", dhType);
136 return ERR_DH_FWK_POINTER_IS_NULL;
137 }
138 auto ret = hdfOperate->UnLoadDistributedHDF();
139 if (ret == DH_FWK_SUCCESS) {
140 if (hdfOperate->IsNeedErase()) {
141 hdfOperateMap_.erase(itHdfOperate);
142 }
143 if (RigidReleaseSourcePtr(dhType) != DH_FWK_SUCCESS) {
144 DHLOGE("RigidReleaseSourcePtr failed, dhType = %{public}#X.", dhType);
145 }
146 hdfInuseRefCount_--;
147 if (hdfInuseRefCount_ <= 0) {
148 DHLOGI("hdf inuse refcount less than 0, create exit dfwk task!");
149 TaskParam taskParam;
150 auto task = TaskFactory::GetInstance().CreateTask(TaskType::EXIT_DFWK, taskParam, nullptr);
151 TaskExecutor::GetInstance().PushTask(task);
152 }
153 }
154 return ret;
155 }
156
AddDeathRecipient(DHType dhType,sptr<IRemoteObject> & remote)157 int32_t HdfOperateManager::AddDeathRecipient(DHType dhType, sptr<IRemoteObject> &remote)
158 {
159 if (remote == nullptr) {
160 DHLOGE("remote ptr is null.");
161 return ERR_DH_FWK_POINTER_IS_NULL;
162 }
163 DHLOGI("Add death recipient begin, dhType = %{public}#X!", dhType);
164 bool ret = false;
165 switch (dhType) {
166 case DHType::AUDIO:
167 ret = remote->AddDeathRecipient(audioHdfLoadRefRecipient_);
168 break;
169 case DHType::CAMERA:
170 ret = remote->AddDeathRecipient(cameraHdfLoadRefRecipient_);
171 break;
172 default:
173 DHLOGE("No hdf support, dhType = %{public}#X.", dhType);
174 return ERR_DH_FWK_NO_HDF_SUPPORT;
175 }
176 if (ret == false) {
177 DHLOGE("call AddDeathRecipient failed, dhType = %{public}#X.", dhType);
178 return ERR_DH_FWK_ADD_DEATH_FAIL;
179 }
180 DHLOGI("Add death recipient end, dhType = %{public}#X!", dhType);
181 return DH_FWK_SUCCESS;
182 }
183
RemoveDeathRecipient(DHType dhType,sptr<IRemoteObject> & remote)184 int32_t HdfOperateManager::RemoveDeathRecipient(DHType dhType, sptr<IRemoteObject> &remote)
185 {
186 if (remote == nullptr) {
187 DHLOGE("remote ptr is null.");
188 return ERR_DH_FWK_POINTER_IS_NULL;
189 }
190 DHLOGI("Remove death recipient begin, dhType = %{public}#X!", dhType);
191 bool ret = false;
192 switch (dhType) {
193 case DHType::AUDIO:
194 ret = remote->RemoveDeathRecipient(audioHdfLoadRefRecipient_);
195 break;
196 case DHType::CAMERA:
197 ret = remote->RemoveDeathRecipient(cameraHdfLoadRefRecipient_);
198 break;
199 default:
200 DHLOGE("No hdf support, dhType = %{public}#X.", dhType);
201 return ERR_DH_FWK_NO_HDF_SUPPORT;
202 }
203 if (ret == false) {
204 DHLOGE("call RemoveDeathRecipient failed, dhType = %{public}#X.", dhType);
205 return ERR_DH_FWK_REMOVE_DEATH_FAIL;
206 }
207 DHLOGI("Remove death recipient end, dhType = %{public}#X!", dhType);
208 return DH_FWK_SUCCESS;
209 }
210
ResetRefCount(DHType dhType)211 void HdfOperateManager::ResetRefCount(DHType dhType)
212 {
213 DHLOGI("Reset ref count begin, dhType = %{public}#X!", dhType);
214 std::unique_lock<std::mutex> hdfOperateMapLocker(hdfOperateMapMutex_);
215 auto itHdfOperate = hdfOperateMap_.find(dhType);
216 if (itHdfOperate == hdfOperateMap_.end()) {
217 DHLOGI("The hdf operate has not been created yet, dhType = %{public}#X!", dhType);
218 return;
219 }
220 auto hdfOperate = itHdfOperate->second;
221 hdfOperate->ResetRefCount();
222 DHLOGI("reset ref count end, dhType = %{public}#X!", dhType);
223 }
224
RigidGetSourcePtr(DHType dhType,IDistributedHardwareSource * & sourcePtr)225 int32_t HdfOperateManager::RigidGetSourcePtr(DHType dhType, IDistributedHardwareSource *&sourcePtr)
226 {
227 DHLOGI("Rigid get source ptr begin, dhType = %{public}#X!", dhType);
228 std::lock_guard<std::mutex> locker(sourceHandlerDataMapMutex_);
229 auto itSourceHandlerData = sourceHandlerDataMap_.find(dhType);
230 if (itSourceHandlerData != sourceHandlerDataMap_.end()) {
231 auto &sourceHandlerData = itSourceHandlerData->second;
232 sourcePtr = sourceHandlerData.sourcePtr;
233 sourceHandlerData.refCount++;
234 DHLOGI("Source ptr already exists, only increase reference count, dhType = %{public}#X!", dhType);
235 return DH_FWK_SUCCESS;
236 }
237 std::string compSourceLoc;
238 switch (dhType) {
239 case DHType::AUDIO:
240 compSourceLoc = "libdistributed_audio_source_sdk.z.so";
241 break;
242 case DHType::CAMERA:
243 compSourceLoc = "libdistributed_camera_source_sdk.z.so";
244 break;
245 default:
246 DHLOGE("No hdf support, dhType = %{public}#X.", dhType);
247 return ERR_DH_FWK_NO_HDF_SUPPORT;
248 }
249 void *sourceHandler = dlopen(compSourceLoc.c_str(), RTLD_LAZY | RTLD_NODELETE);
250 if (sourceHandler == nullptr) {
251 DHLOGE("dlopen failed, failed reason: %{public}s, dhType: %{public}" PRIu32, dlerror(), (uint32_t)dhType);
252 return ERR_DH_FWK_LOADER_HANDLER_IS_NULL;
253 }
254 auto getSourceHardClassHandler = (GetSourceHardwareClass)dlsym(
255 sourceHandler, COMPONENT_LOADER_GET_SOURCE_HANDLER.c_str());
256 if (getSourceHardClassHandler == nullptr) {
257 DHLOGE("get getSourceHardClassHandler is null, failed reason : %{public}s", dlerror());
258 dlclose(sourceHandler);
259 sourceHandler = nullptr;
260 return ERR_DH_FWK_LOADER_HANDLER_IS_NULL;
261 }
262 sourcePtr = getSourceHardClassHandler();
263 if (sourcePtr == nullptr) {
264 DHLOGE("getSourceHardClassHandler return null!");
265 dlclose(sourceHandler);
266 sourceHandler = nullptr;
267 return ERR_DH_FWK_LOADER_HANDLER_IS_NULL;
268 }
269 sourceHandlerDataMap_[dhType] = SourceHandlerData {
270 .refCount = 1, .sourceHandler = sourceHandler, .sourcePtr = sourcePtr
271 };
272 DHLOGI("Rigid get source ptr end, dhType = %{public}#X!", dhType);
273 return DH_FWK_SUCCESS;
274 }
275
RigidReleaseSourcePtr(DHType dhType)276 int32_t HdfOperateManager::RigidReleaseSourcePtr(DHType dhType)
277 {
278 DHLOGI("Rigid release source ptr begin, dhType = %{public}#X!", dhType);
279 std::lock_guard<std::mutex> locker(sourceHandlerDataMapMutex_);
280 auto itSourceHandlerData = sourceHandlerDataMap_.find(dhType);
281 if (itSourceHandlerData == sourceHandlerDataMap_.end()) {
282 DHLOGI("The source ptr has not been obtained yet, dhType = %{public}#X!", dhType);
283 return DH_FWK_SUCCESS;
284 }
285 auto &sourceHandlerData = itSourceHandlerData->second;
286 if (sourceHandlerData.refCount > 1) {
287 sourceHandlerData.refCount--;
288 DHLOGI("Source ptr is still in use, only reducing reference count, dhType = %{public}#X!", dhType);
289 return DH_FWK_SUCCESS;
290 }
291 if (dlclose(sourceHandlerData.sourceHandler) != 0) {
292 DHLOGE("dlclose failed, failed reason: %{public}s, dhType: %{public}" PRIu32, dlerror(), (uint32_t)dhType);
293 return ERR_DH_FWK_LOADER_DLCLOSE_FAIL;
294 }
295 sourceHandlerDataMap_.erase(itSourceHandlerData);
296 DHLOGI("Rigid release source ptr end, dhType = %{public}#X!", dhType);
297 return DH_FWK_SUCCESS;
298 }
299
IsAnyHdfInuse()300 bool HdfOperateManager::IsAnyHdfInuse()
301 {
302 std::unique_lock<std::mutex> hdfOperateMapLocker(hdfOperateMapMutex_);
303 return hdfInuseRefCount_ > 0;
304 }
305
OnRemoteDied(const wptr<IRemoteObject> & remote)306 void HdfLoadRefRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
307 {
308 DHLOGI("On remote died, dhType = %{public}#X!", dhType_);
309 HdfOperateManager::GetInstance().UnLoadDistributedHDF(dhType_);
310 }
311
OnHdfHostDied()312 void HdfDeathCallbackImpl::OnHdfHostDied()
313 {
314 DHLOGI("On hdf died, dhType = %{public}#X!", dhType_);
315 HdfOperateManager::GetInstance().ResetRefCount(dhType_);
316 }
317 } // namespace DistributedHardware
318 } // namespace OHOS