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