1 /*
2 * Copyright (c) 2022-2023 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 "devicestatus_msdp_client_impl.h"
17
18 #include <string>
19
20 #include <dlfcn.h>
21
22 #include "devicestatus_define.h"
23 #include "devicestatus_dumper.h"
24 #include "fi_log.h"
25
26 namespace OHOS {
27 namespace Msdp {
28 namespace DeviceStatus {
29 namespace {
30 constexpr ::OHOS::HiviewDFX::HiLogLabel LABEL { LOG_CORE, MSDP_DOMAIN_ID, "DeviceStatusMsdpClientImpl" };
31 #ifdef __aarch64__
32 const std::string DEVICESTATUS_MOCK_LIB_PATH { "/system/lib64/libdevicestatus_mock.z.so" };
33 const std::string DEVICESTATUS_ALGO_LIB_PATH { "/system/lib64/libdevicestatus_algo.z.so" };
34 #else
35 const std::string DEVICESTATUS_MOCK_LIB_PATH { "/system/lib/libdevicestatus_mock.z.so" };
36 const std::string DEVICESTATUS_ALGO_LIB_PATH { "/system/lib/libdevicestatus_algo.z.so" };
37 #endif
38 using ClientType = Type;
39 using ClientValue = OnChangedValue;
40 } // namespace
41
DeviceStatusMsdpClientImpl()42 DeviceStatusMsdpClientImpl::DeviceStatusMsdpClientImpl()
43 {
44 for (int32_t type = 0; type < static_cast<int32_t>(Type::TYPE_MAX); ++type) {
45 algoCallCount_[static_cast<Type>(type)] = 0;
46 mockCallCount_[static_cast<Type>(type)] = 0;
47 }
48 }
49
InitMsdpImpl(Type type)50 ErrCode DeviceStatusMsdpClientImpl::InitMsdpImpl(Type type)
51 {
52 CALL_DEBUG_ENTER;
53 if (GetSensorHdi(type) == RET_OK) {
54 FI_HILOGI("GetSensorHdi is support");
55 return RET_OK;
56 }
57 if (AlgoHandle(type) == RET_OK) {
58 FI_HILOGI("AlgoHandle is support");
59 return RET_OK;
60 }
61 if (MockHandle(type) == RET_OK) {
62 FI_HILOGI("MockHandle is support");
63 return RET_OK;
64 }
65 return RET_ERR;
66 }
67
MockHandle(Type type)68 ErrCode DeviceStatusMsdpClientImpl::MockHandle(Type type)
69 {
70 if (StartMock(type) == RET_ERR) {
71 FI_HILOGE("Start mock Library failed");
72 return RET_ERR;
73 }
74 CHKPR(iMock_, RET_ERR);
75 iMock_->Enable(type);
76 auto iter = mockCallCount_.find(type);
77 if (iter == mockCallCount_.end()) {
78 auto ret = mockCallCount_.emplace(type, 0);
79 if (!ret.second) {
80 FI_HILOGW("type is duplicated");
81 return RET_ERR;
82 }
83 } else {
84 iter->second++;
85 }
86 RegisterMock();
87 FI_HILOGI("mockCallCount_:%{public}d", mockCallCount_[type]);
88 return RET_OK;
89 }
90
AlgoHandle(Type type)91 ErrCode DeviceStatusMsdpClientImpl::AlgoHandle(Type type)
92 {
93 if (GetAlgoAbility(type) == RET_ERR) {
94 FI_HILOGE("Algo Library is not support");
95 return RET_ERR;
96 }
97 if (StartAlgo(type) == RET_ERR) {
98 FI_HILOGE("Start algo Library failed");
99 return RET_ERR;
100 }
101 CHKPR(iAlgo_, RET_ERR);
102 if ((iAlgo_->Enable(type)) == RET_ERR) {
103 FI_HILOGE("Enable algo Library failed");
104 return RET_ERR;
105 }
106
107 auto iter = algoCallCount_.find(type);
108 if (iter == algoCallCount_.end()) {
109 auto ret = algoCallCount_.emplace(type, 0);
110 if (!ret.second) {
111 FI_HILOGW("type is duplicated");
112 return RET_ERR;
113 }
114 } else {
115 iter->second++;
116 }
117 RegisterAlgo();
118 FI_HILOGI("algoCallCount_:%{public}d", algoCallCount_[type]);
119 return RET_OK;
120 }
121
StartAlgo(Type type)122 ErrCode DeviceStatusMsdpClientImpl::StartAlgo(Type type)
123 {
124 if (LoadAlgoLibrary() == RET_ERR) {
125 FI_HILOGE("Load algo Library failed");
126 return RET_ERR;
127 }
128 iAlgo_ = GetAlgoInst(type);
129 CHKPR(iAlgo_, RET_ERR);
130 return RET_OK;
131 }
132
StartMock(Type type)133 ErrCode DeviceStatusMsdpClientImpl::StartMock(Type type)
134 {
135 if (LoadMockLibrary() == RET_ERR) {
136 FI_HILOGE("Load mock Library failed");
137 return RET_ERR;
138 }
139 iMock_ = GetMockInst(type);
140 if (iMock_ == nullptr) {
141 FI_HILOGE("Get mock module failed");
142 return RET_ERR;
143 }
144 return RET_OK;
145 }
146
GetSensorHdi(Type type)147 ErrCode DeviceStatusMsdpClientImpl::GetSensorHdi(Type type)
148 {
149 return RET_ERR;
150 }
151
GetAlgoAbility(Type type)152 ErrCode DeviceStatusMsdpClientImpl::GetAlgoAbility(Type type)
153 {
154 if (type == Type::TYPE_ABSOLUTE_STILL ||type == Type::TYPE_HORIZONTAL_POSITION ||
155 type == Type::TYPE_VERTICAL_POSITION) {
156 return RET_OK;
157 }
158 FI_HILOGI("Not support ability");
159 return RET_ERR;
160 }
161
Disable(Type type)162 ErrCode DeviceStatusMsdpClientImpl::Disable(Type type)
163 {
164 CALL_DEBUG_ENTER;
165 return ((SensorHdiDisable(type) == RET_OK || AlgoDisable(type) == RET_OK || MockDisable(type) == RET_OK) ?
166 RET_OK : RET_ERR);
167 }
168
SensorHdiDisable(Type type)169 ErrCode DeviceStatusMsdpClientImpl::SensorHdiDisable(Type type)
170 {
171 return RET_ERR;
172 }
173
AlgoDisable(Type type)174 ErrCode DeviceStatusMsdpClientImpl::AlgoDisable(Type type)
175 {
176 CALL_DEBUG_ENTER;
177 CHKPR(iAlgo_, RET_ERR);
178 auto iter = algoCallCount_.find(type);
179 if (iter == algoCallCount_.end()) {
180 FI_HILOGE("Failed to find record type");
181 return RET_ERR;
182 }
183 if (iter->second == 0) {
184 algoCallCount_.erase(type);
185 } else {
186 iAlgo_->Disable(type);
187 UnregisterAlgo();
188 }
189 iter->second--;
190 algoCallCount_.erase(type);
191 if (algoCallCount_.empty()) {
192 if (UnloadAlgoLibrary() == RET_ERR) {
193 FI_HILOGE("Failed to close algorithm library");
194 return RET_ERR;
195 }
196 FI_HILOGI("Close algorithm library");
197 iAlgo_ = nullptr;
198 callBacksMgr_ = nullptr;
199 }
200 FI_HILOGI("algoCallCount_:%{public}d", algoCallCount_[type]);
201 return RET_OK;
202 }
203
MockDisable(Type type)204 ErrCode DeviceStatusMsdpClientImpl::MockDisable(Type type)
205 {
206 CALL_DEBUG_ENTER;
207 CHKPR(iMock_, RET_ERR);
208 auto iter = mockCallCount_.find(type);
209 if (iter == mockCallCount_.end()) {
210 FI_HILOGE("Failed to find record type");
211 return RET_ERR;
212 }
213 if (iter->second == 0) {
214 mockCallCount_.erase(type);
215 } else {
216 iMock_->DisableCount(type);
217 iMock_->Disable(type);
218 UnregisterMock();
219 }
220 iter->second--;
221 if (mockCallCount_.empty()) {
222 if (UnloadMockLibrary() == RET_ERR) {
223 FI_HILOGE("Failed to close library");
224 return RET_ERR;
225 }
226 iMock_ = nullptr;
227 callBacksMgr_ = nullptr;
228 }
229 return RET_OK;
230 }
231
ImplCallback(const Data & data)232 ErrCode DeviceStatusMsdpClientImpl::ImplCallback(const Data& data)
233 {
234 CHKPR(callBacksMgr_, RET_ERR);
235 callBacksMgr_(data);
236 return RET_OK;
237 }
238
RegisterImpl(const CallbackManager & callback)239 ErrCode DeviceStatusMsdpClientImpl::RegisterImpl(const CallbackManager& callback)
240 {
241 callBacksMgr_ = callback;
242 return RET_OK;
243 }
244
OnResult(const Data & data)245 void DeviceStatusMsdpClientImpl::OnResult(const Data& data)
246 {
247 FI_HILOGD("type:%{public}d, value:%{public}d", data.type, data.value);
248 MsdpCallback(data);
249 }
250
RegisterMock()251 ErrCode DeviceStatusMsdpClientImpl::RegisterMock()
252 {
253 CALL_DEBUG_ENTER;
254 if (iMock_ != nullptr) {
255 std::shared_ptr<IMsdp::MsdpAlgoCallback> callback = shared_from_this();
256 iMock_->RegisterCallback(callback);
257 }
258 return RET_OK;
259 }
260
UnregisterMock()261 ErrCode DeviceStatusMsdpClientImpl::UnregisterMock()
262 {
263 CALL_DEBUG_ENTER;
264 CHKPR(iMock_, RET_ERR);
265 iMock_->UnregisterCallback();
266 return RET_OK;
267 }
268
RegisterAlgo()269 ErrCode DeviceStatusMsdpClientImpl::RegisterAlgo()
270 {
271 CALL_DEBUG_ENTER;
272 if (iAlgo_ != nullptr) {
273 std::shared_ptr<IMsdp::MsdpAlgoCallback> callback_ = shared_from_this();
274 iAlgo_->RegisterCallback(callback_);
275 }
276 return RET_OK;
277 }
278
UnregisterAlgo()279 ErrCode DeviceStatusMsdpClientImpl::UnregisterAlgo()
280 {
281 CALL_DEBUG_ENTER;
282 CHKPR(iAlgo_, RET_ERR);
283 iAlgo_->UnregisterCallback();
284 return RET_OK;
285 }
286
MsdpCallback(const Data & data)287 int32_t DeviceStatusMsdpClientImpl::MsdpCallback(const Data& data)
288 {
289 CALL_DEBUG_ENTER;
290 DS_DUMPER->PushDeviceStatus(data);
291 SaveObserverData(data);
292 if (notifyManagerFlag_) {
293 ImplCallback(data);
294 notifyManagerFlag_ = false;
295 }
296 return RET_OK;
297 }
298
SaveObserverData(const Data & data)299 Data DeviceStatusMsdpClientImpl::SaveObserverData(const Data& data)
300 {
301 CALL_DEBUG_ENTER;
302 std::lock_guard guard(mutex_);
303 for (auto iter = deviceStatusDataMap_.begin(); iter != deviceStatusDataMap_.end(); ++iter) {
304 if (iter->first == data.type) {
305 iter->second = data.value;
306 notifyManagerFlag_ = true;
307 return data;
308 }
309 }
310 auto ret = deviceStatusDataMap_.insert(std::make_pair(data.type, data.value));
311 if (!ret.second) {
312 FI_HILOGW("type is duplicated");
313 return data;
314 }
315 notifyManagerFlag_ = true;
316 return data;
317 }
318
GetObserverData() const319 std::map<ClientType, ClientValue> DeviceStatusMsdpClientImpl::GetObserverData() const
320 {
321 return deviceStatusDataMap_;
322 }
323
GetDeviceStatusTimestamp()324 void DeviceStatusMsdpClientImpl::GetDeviceStatusTimestamp()
325 {}
326
GetLongtitude()327 void DeviceStatusMsdpClientImpl::GetLongtitude()
328 {}
329
GetLatitude()330 void DeviceStatusMsdpClientImpl::GetLatitude()
331 {}
332
LoadMockLibrary()333 ErrCode DeviceStatusMsdpClientImpl::LoadMockLibrary()
334 {
335 CALL_DEBUG_ENTER;
336 if (mock_.handle != nullptr) {
337 FI_HILOGE("mock handle is not nullptr");
338 return RET_OK;
339 }
340 std::string dlName = DEVICESTATUS_MOCK_LIB_PATH;
341 char libRealPath[PATH_MAX] = {};
342 if (realpath(dlName .c_str(), libRealPath) == nullptr) {
343 FI_HILOGE("get absolute algoPath is error, errno:%{public}d", errno);
344 return RET_ERR;
345 }
346 mock_.handle = dlopen(libRealPath, RTLD_LAZY);
347 if (mock_.handle == nullptr) {
348 FI_HILOGE("Cannot load library error:%{public}s", dlerror());
349 return RET_ERR;
350 }
351 FI_HILOGI("Start create pointer");
352 mock_.create = reinterpret_cast<LoadMockLibraryFunc>(dlsym(mock_.handle, "Create"));
353 FI_HILOGI("Start destroy pointer");
354 mock_.destroy = reinterpret_cast<LoadMockLibraryPtr>(dlsym(mock_.handle, "Destroy"));
355 if (mock_.create == nullptr || mock_.destroy == nullptr) {
356 FI_HILOGE("%{public}s dlsym Create or Destroy failed",
357 dlName.c_str());
358 dlclose(mock_.handle);
359 mock_.Clear();
360 if (mock_.handle == nullptr) {
361 return RET_OK;
362 }
363 FI_HILOGE("Load mock failed");
364 return RET_ERR;
365 }
366 return RET_OK;
367 }
368
UnloadMockLibrary()369 ErrCode DeviceStatusMsdpClientImpl::UnloadMockLibrary()
370 {
371 CALL_DEBUG_ENTER;
372 CHKPR(mock_.handle, RET_ERR);
373 if (mock_.pAlgorithm != nullptr) {
374 mock_.destroy(mock_.pAlgorithm);
375 mock_.pAlgorithm = nullptr;
376 }
377 dlclose(mock_.handle);
378 mock_.Clear();
379 return RET_OK;
380 }
381
GetMockInst(Type type)382 IMsdp* DeviceStatusMsdpClientImpl::GetMockInst(Type type)
383 {
384 CALL_DEBUG_ENTER;
385 CHKPP(mock_.handle);
386 if (mock_.pAlgorithm == nullptr) {
387 std::unique_lock lock(mutex_);
388 mock_.pAlgorithm = mock_.create();
389 mockCallCount_[type] = 0;
390 }
391 return mock_.pAlgorithm;
392 }
393
LoadAlgoLibrary()394 ErrCode DeviceStatusMsdpClientImpl::LoadAlgoLibrary()
395 {
396 CALL_DEBUG_ENTER;
397 if (algo_.handle != nullptr) {
398 FI_HILOGE("algo handle has exists");
399 return RET_OK;
400 }
401 std::string dlName = DEVICESTATUS_ALGO_LIB_PATH;
402 char libRealPath[PATH_MAX] = {};
403 if (realpath(dlName .c_str(), libRealPath) == nullptr) {
404 FI_HILOGE("get absolute algoPath is error, errno:%{public}d", errno);
405 return RET_ERR;
406 }
407 algo_.handle = dlopen(libRealPath, RTLD_LAZY);
408 if (algo_.handle == nullptr) {
409 FI_HILOGE("Cannot load library error:%{public}s", dlerror());
410 return RET_ERR;
411 }
412 FI_HILOGI("Start create pointer");
413 algo_.create = reinterpret_cast<LoadMockLibraryFunc>(dlsym(algo_.handle, "Create"));
414 FI_HILOGI("Start destroy pointer");
415 algo_.destroy = reinterpret_cast<LoadMockLibraryPtr>(dlsym(algo_.handle, "Destroy"));
416 if (algo_.create == nullptr || algo_.destroy == nullptr) {
417 FI_HILOGE("%{public}s dlsym Create or Destroy failed",
418 dlName.c_str());
419 dlclose(algo_.handle);
420 algo_.Clear();
421 if (algo_.handle == nullptr) {
422 return RET_OK;
423 }
424 FI_HILOGE("Load algo failed");
425 return RET_ERR;
426 }
427 return RET_OK;
428 }
429
UnloadAlgoLibrary()430 ErrCode DeviceStatusMsdpClientImpl::UnloadAlgoLibrary()
431 {
432 CALL_DEBUG_ENTER;
433 CHKPR(algo_.handle, RET_ERR);
434 if (algo_.pAlgorithm != nullptr) {
435 algo_.destroy(algo_.pAlgorithm);
436 algo_.pAlgorithm = nullptr;
437 }
438 dlclose(algo_.handle);
439 algo_.Clear();
440 return RET_OK;
441 }
442
GetAlgoInst(Type type)443 IMsdp* DeviceStatusMsdpClientImpl::GetAlgoInst(Type type)
444 {
445 CALL_DEBUG_ENTER;
446 CHKPP(algo_.handle);
447 if (algo_.pAlgorithm == nullptr) {
448 std::unique_lock lock(mutex_);
449 algo_.pAlgorithm = algo_.create();
450 }
451 return algo_.pAlgorithm;
452 }
453 } // namespace DeviceStatus
454 } // namespace Msdp
455 } // namespace OHOS
456