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     iAlgo_ = GetAlgoInst(type);
136     CHKPR(iAlgo_, RET_ERR);
137     return RET_OK;
138 }
139 
StartMock(Type type)140 ErrCode DeviceStatusMsdpClientImpl::StartMock(Type type)
141 {
142     if (LoadMockLibrary() == RET_ERR) {
143         FI_HILOGE("Load mock Library failed");
144         return RET_ERR;
145     }
146     iMock_ = GetMockInst(type);
147     if (iMock_ == nullptr) {
148         FI_HILOGE("Get mock module failed");
149         return RET_ERR;
150     }
151     return RET_OK;
152 }
153 
GetSensorHdi(Type type)154 ErrCode DeviceStatusMsdpClientImpl::GetSensorHdi(Type type)
155 {
156     return RET_ERR;
157 }
158 
GetAlgoAbility(Type type)159 ErrCode DeviceStatusMsdpClientImpl::GetAlgoAbility(Type type)
160 {
161     if ((type == Type::TYPE_ABSOLUTE_STILL) || (type == Type::TYPE_HORIZONTAL_POSITION) ||
162         (type == Type::TYPE_VERTICAL_POSITION)) {
163         FI_HILOGI("Support ability type:%{public}d", type);
164         return RET_OK;
165     }
166     FI_HILOGI("Not support ability");
167     return RET_ERR;
168 }
169 
Disable(Type type)170 ErrCode DeviceStatusMsdpClientImpl::Disable(Type type)
171 {
172     CALL_DEBUG_ENTER;
173     return (((SensorHdiDisable(type) == RET_OK) || (AlgoDisable(type) == RET_OK) || (MockDisable(type) == RET_OK)) ?
174         RET_OK : RET_ERR);
175 }
176 
SensorHdiDisable(Type type)177 ErrCode DeviceStatusMsdpClientImpl::SensorHdiDisable(Type type)
178 {
179     return RET_ERR;
180 }
181 
AlgoDisable(Type type)182 ErrCode DeviceStatusMsdpClientImpl::AlgoDisable(Type type)
183 {
184     #ifdef DEVICE_STATUS_SENSOR_ENABLE
185     CALL_DEBUG_ENTER;
186     CHKPR(iAlgo_, RET_ERR);
187     auto iter = algoCallCounts_.find(type);
188     if (iter == algoCallCounts_.end()) {
189         FI_HILOGE("Failed to find record type");
190         return RET_ERR;
191     }
192     if (iter->second == 0) {
193         algoCallCounts_.erase(type);
194     } else {
195         iAlgo_->Disable(type);
196         UnregisterAlgo();
197     }
198     algoCallCounts_.erase(type);
199     if (algoCallCounts_.empty()) {
200         if (UnloadAlgoLibrary() == RET_ERR) {
201             FI_HILOGE("Failed to close algorithm library");
202             return RET_ERR;
203         }
204         FI_HILOGI("Close algorithm library");
205         iAlgo_ = nullptr;
206         callBacksMgr_ = nullptr;
207     }
208     FI_HILOGI("algoCallCounts_:%{public}d", algoCallCounts_[type]);
209     return RET_OK;
210     #else
211     FI_HILOGE("Disable:sensor is not exist");
212     return RET_ERR;
213     #endif // DEVICE_STATUS_SENSOR_ENABLE
214 }
215 
MockDisable(Type type)216 ErrCode DeviceStatusMsdpClientImpl::MockDisable(Type type)
217 {
218     CALL_DEBUG_ENTER;
219     CHKPR(iMock_, RET_ERR);
220     std::unique_lock lock(mutex_);
221     auto iter = mockCallCounts_.find(type);
222     if (iter == mockCallCounts_.end()) {
223         FI_HILOGE("Failed to find record type");
224         return RET_ERR;
225     }
226     if (iter->second == 0) {
227         mockCallCounts_.erase(type);
228     } else {
229         iMock_->DisableCount(type);
230         iMock_->Disable(type);
231         UnregisterMock();
232     }
233     iter->second--;
234     if (mockCallCounts_.empty()) {
235         if (UnloadMockLibrary() == RET_ERR) {
236             FI_HILOGE("Failed to close library");
237             return RET_ERR;
238         }
239         iMock_ = nullptr;
240         callBacksMgr_ = nullptr;
241     }
242     return RET_OK;
243 }
244 
ImplCallback(const Data &data)245 ErrCode DeviceStatusMsdpClientImpl::ImplCallback(const Data &data)
246 {
247     std::unique_lock lock(mutex_);
248     CHKPR(callBacksMgr_, RET_ERR);
249     callBacksMgr_(data);
250     return RET_OK;
251 }
252 
RegisterImpl(const CallbackManager &callback)253 ErrCode DeviceStatusMsdpClientImpl::RegisterImpl(const CallbackManager &callback)
254 {
255     callBacksMgr_ = callback;
256     return RET_OK;
257 }
258 
OnResult(const Data &data)259 void DeviceStatusMsdpClientImpl::OnResult(const Data &data)
260 {
261     FI_HILOGD("type:%{public}d, value:%{public}d", data.type, data.value);
262     MsdpCallback(data);
263 }
264 
RegisterMock()265 ErrCode DeviceStatusMsdpClientImpl::RegisterMock()
266 {
267     CALL_DEBUG_ENTER;
268     if (iMock_ != nullptr) {
269         std::shared_ptr<IMsdp::MsdpAlgoCallback> callback = shared_from_this();
270         iMock_->RegisterCallback(callback);
271     }
272     return RET_OK;
273 }
274 
UnregisterMock()275 ErrCode DeviceStatusMsdpClientImpl::UnregisterMock()
276 {
277     CALL_DEBUG_ENTER;
278     CHKPR(iMock_, RET_ERR);
279     iMock_->UnregisterCallback();
280     return RET_OK;
281 }
282 
RegisterAlgo()283 ErrCode DeviceStatusMsdpClientImpl::RegisterAlgo()
284 {
285     CALL_DEBUG_ENTER;
286     if (iAlgo_ != nullptr) {
287         std::shared_ptr<IMsdp::MsdpAlgoCallback> callback_ = shared_from_this();
288         iAlgo_->RegisterCallback(callback_);
289     }
290     return RET_OK;
291 }
292 
UnregisterAlgo()293 ErrCode DeviceStatusMsdpClientImpl::UnregisterAlgo()
294 {
295     CALL_DEBUG_ENTER;
296     CHKPR(iAlgo_, RET_ERR);
297     iAlgo_->UnregisterCallback();
298     return RET_OK;
299 }
300 
MsdpCallback(const Data &data)301 int32_t DeviceStatusMsdpClientImpl::MsdpCallback(const Data &data)
302 {
303     CALL_DEBUG_ENTER;
304     DS_DUMPER->PushDeviceStatus(data);
305     SaveObserverData(data);
306     if (notifyManagerFlag_) {
307         ImplCallback(data);
308         notifyManagerFlag_ = false;
309     }
310     return RET_OK;
311 }
312 
SaveObserverData(const Data &data)313 Data DeviceStatusMsdpClientImpl::SaveObserverData(const Data &data)
314 {
315     CALL_DEBUG_ENTER;
316     std::unique_lock lock(mutex_);
317     for (auto iter = deviceStatusDatas_.begin(); iter != deviceStatusDatas_.end(); ++iter) {
318         if (iter->first == data.type) {
319             iter->second = data.value;
320             notifyManagerFlag_ = true;
321             return data;
322         }
323     }
324     auto ret = deviceStatusDatas_.insert(std::make_pair(data.type, data.value));
325     if (!ret.second) {
326         FI_HILOGW("type is duplicated");
327         return data;
328     }
329     notifyManagerFlag_ = true;
330     return data;
331 }
332 
GetObserverData() const333 std::map<ClientType, ClientValue> DeviceStatusMsdpClientImpl::GetObserverData() const
334 {
335     return deviceStatusDatas_;
336 }
337 
GetDeviceStatusTimestamp()338 void DeviceStatusMsdpClientImpl::GetDeviceStatusTimestamp()
339 {}
340 
GetLongtitude()341 void DeviceStatusMsdpClientImpl::GetLongtitude()
342 {}
343 
GetLatitude()344 void DeviceStatusMsdpClientImpl::GetLatitude()
345 {}
346 
LoadMockLibrary()347 ErrCode DeviceStatusMsdpClientImpl::LoadMockLibrary()
348 {
349     CALL_DEBUG_ENTER;
350     std::unique_lock lock(mutex_);
351     if (mock_.handle != nullptr) {
352         FI_HILOGW("mock handle is not nullptr");
353         return RET_OK;
354     }
355     std::string dlName = DEVICESTATUS_MOCK_LIB_PATH;
356     char libRealPath[PATH_MAX] = { 0 };
357     if (realpath(dlName .c_str(), libRealPath) == nullptr) {
358         FI_HILOGE("Get absolute algoPath is error, errno:%{public}d", errno);
359         return RET_ERR;
360     }
361     mock_.handle = dlopen(libRealPath, RTLD_LAZY);
362     if (mock_.handle == nullptr) {
363         FI_HILOGE("Cannot load library error:%{public}s", dlerror());
364         return RET_ERR;
365     }
366     FI_HILOGI("Start create pointer");
367     mock_.create = reinterpret_cast<LoadMockLibraryFunc>(dlsym(mock_.handle, "Create"));
368     FI_HILOGI("Start destroy pointer");
369     mock_.destroy = reinterpret_cast<LoadMockLibraryPtr>(dlsym(mock_.handle, "Destroy"));
370     if ((mock_.create == nullptr) || (mock_.destroy == nullptr)) {
371         FI_HILOGE("%{public}s dlsym Create or Destroy failed",
372             dlName.c_str());
373         dlclose(mock_.handle);
374         mock_.Clear();
375         if (mock_.handle == nullptr) {
376             return RET_OK;
377         }
378         FI_HILOGE("Load mock failed");
379         return RET_ERR;
380     }
381     return RET_OK;
382 }
383 
UnloadMockLibrary()384 ErrCode DeviceStatusMsdpClientImpl::UnloadMockLibrary()
385 {
386     CALL_DEBUG_ENTER;
387     std::unique_lock lock(mutex_);
388     CHKPR(mock_.handle, RET_ERR);
389     if (mock_.pAlgorithm != nullptr) {
390         mock_.destroy(mock_.pAlgorithm);
391         mock_.pAlgorithm = nullptr;
392     }
393     dlclose(mock_.handle);
394     mock_.Clear();
395     return RET_OK;
396 }
397 
GetMockInst(Type type)398 IMsdp* DeviceStatusMsdpClientImpl::GetMockInst(Type type)
399 {
400     CALL_DEBUG_ENTER;
401     std::unique_lock lock(mutex_);
402     CHKPP(mock_.handle);
403     if (mock_.pAlgorithm == nullptr) {
404         mock_.pAlgorithm = mock_.create();
405         mockCallCounts_[type] = 0;
406     }
407     return mock_.pAlgorithm;
408 }
409 
LoadAlgoLibrary()410 ErrCode DeviceStatusMsdpClientImpl::LoadAlgoLibrary()
411 {
412     CALL_DEBUG_ENTER;
413     std::unique_lock lock(mutex_);
414     if (algo_.handle != nullptr) {
415         FI_HILOGE("Algo handle has exists");
416         return RET_OK;
417     }
418     std::string dlName = DEVICESTATUS_ALGO_LIB_PATH;
419     char libRealPath[PATH_MAX] = { 0 };
420     if (realpath(dlName .c_str(), libRealPath) == nullptr) {
421         FI_HILOGE("Get absolute algoPath is error, errno:%{public}d", errno);
422         return RET_ERR;
423     }
424     algo_.handle = dlopen(libRealPath, RTLD_LAZY);
425     if (algo_.handle == nullptr) {
426         FI_HILOGE("Cannot load library error:%{public}s", dlerror());
427         return RET_ERR;
428     }
429     FI_HILOGI("Start create pointer");
430     algo_.create = reinterpret_cast<LoadMockLibraryFunc>(dlsym(algo_.handle, "Create"));
431     FI_HILOGI("Start destroy pointer");
432     algo_.destroy = reinterpret_cast<LoadMockLibraryPtr>(dlsym(algo_.handle, "Destroy"));
433     if ((algo_.create == nullptr) || (algo_.destroy == nullptr)) {
434         FI_HILOGE("%{public}s dlsym Create or Destroy failed",
435             dlName.c_str());
436         dlclose(algo_.handle);
437         algo_.Clear();
438         if (algo_.handle == nullptr) {
439             return RET_OK;
440         }
441         FI_HILOGE("Load algo failed");
442         return RET_ERR;
443     }
444     return RET_OK;
445 }
446 
UnloadAlgoLibrary()447 ErrCode DeviceStatusMsdpClientImpl::UnloadAlgoLibrary()
448 {
449     CALL_DEBUG_ENTER;
450     std::unique_lock lock(mutex_);
451     CHKPR(algo_.handle, RET_ERR);
452     if (algo_.pAlgorithm != nullptr) {
453         algo_.destroy(algo_.pAlgorithm);
454         algo_.pAlgorithm = nullptr;
455     }
456     dlclose(algo_.handle);
457     algo_.Clear();
458     return RET_OK;
459 }
460 
GetAlgoInst(Type type)461 IMsdp* DeviceStatusMsdpClientImpl::GetAlgoInst(Type type)
462 {
463     CALL_DEBUG_ENTER;
464     std::unique_lock lock(mutex_);
465     CHKPP(algo_.handle);
466     if (algo_.pAlgorithm == nullptr) {
467         algo_.pAlgorithm = algo_.create();
468     }
469     return algo_.pAlgorithm;
470 }
471 } // namespace DeviceStatus
472 } // namespace Msdp
473 } // namespace OHOS
474