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#ifdef DEVICE_STATUS_SENSOR_ENABLE
17#include "devicestatus_algorithm_manager.h"
18
19#include <cerrno>
20#include <string>
21
22#include <linux/netlink.h>
23#include <sys/epoll.h>
24#include <sys/timerfd.h>
25#include <unistd.h>
26
27#include "devicestatus_common.h"
28#include "devicestatus_define.h"
29
30#undef LOG_TAG
31#define LOG_TAG "AlgoMgr"
32
33namespace OHOS {
34namespace Msdp {
35namespace DeviceStatus {
36
37bool AlgoMgr::StartSensor(Type type)
38{
39    CALL_DEBUG_ENTER;
40    int32_t sensorType = GetSensorTypeId(type);
41    if (sensorType == RET_ERR) {
42        FI_HILOGE("Failed to get sensorType");
43        return false;
44    }
45    if (!CheckSensorTypeId(sensorType)) {
46        FI_HILOGE("Sensor type mismatch");
47        return false;
48    }
49
50    SENSOR_DATA_CB.Init();
51    if (!SENSOR_DATA_CB.RegisterCallbackSensor(sensorType)) {
52        FI_HILOGE("Failed to register callback sensor");
53        return false;
54    }
55
56    return true;
57}
58
59ErrCode AlgoMgr::RegisterCallback(std::shared_ptr<MsdpAlgoCallback> callback)
60{
61    CALL_DEBUG_ENTER;
62    std::lock_guard lock(mutex_);
63    switch (algoType_) {
64        case Type::TYPE_ABSOLUTE_STILL: {
65            if (still_ != nullptr) {
66                still_->RegisterCallback(callback);
67            }
68            break;
69        }
70        case Type::TYPE_HORIZONTAL_POSITION: {
71            if (horizontalPosition_ != nullptr) {
72                horizontalPosition_->RegisterCallback(callback);
73            }
74            break;
75        }
76        case Type::TYPE_VERTICAL_POSITION: {
77            if (verticalPosition_ != nullptr) {
78                verticalPosition_->RegisterCallback(callback);
79            }
80            break;
81        }
82        default: {
83            FI_HILOGE("Unsupported algorithm type");
84            return RET_ERR;
85        }
86    }
87    return RET_OK;
88}
89
90ErrCode AlgoMgr::UnregisterCallback()
91{
92    CALL_DEBUG_ENTER;
93    return RET_OK;
94}
95
96bool AlgoMgr::CheckSensorTypeId(int32_t sensorTypeId)
97{
98    int32_t count = -1;
99    SensorInfo *sensorInfo = nullptr;
100    int32_t ret = GetAllSensors(&sensorInfo, &count);
101    if (ret != 0) {
102        FI_HILOGE("Get all sensors failed");
103        return false;
104    }
105    SensorInfo *pt = sensorInfo + count;
106    for (SensorInfo *ps = sensorInfo; ps < pt; ++ps) {
107        if (ps->sensorTypeId == sensorTypeId) {
108            FI_HILOGI("Get sensor sensorTypeId: %{public}d", sensorTypeId);
109            return true;
110        }
111    }
112    FI_HILOGE("Get sensor failed");
113    return false;
114}
115
116int32_t AlgoMgr::GetSensorTypeId(Type type)
117{
118    FI_HILOGI("Get sensor type: %{public}d", type);
119    switch (type) {
120        case Type::TYPE_ABSOLUTE_STILL: {
121            return SensorTypeId::SENSOR_TYPE_ID_ACCELEROMETER;
122        }
123        case Type::TYPE_HORIZONTAL_POSITION: {
124            return SensorTypeId::SENSOR_TYPE_ID_ACCELEROMETER;
125        }
126        case Type::TYPE_VERTICAL_POSITION: {
127            return SensorTypeId::SENSOR_TYPE_ID_ACCELEROMETER;
128        }
129        default: {
130            FI_HILOGW("GetSensorTypeId failed");
131            break;
132        }
133    }
134    return RET_ERR;
135}
136
137ErrCode AlgoMgr::Enable(Type type)
138{
139    CALL_DEBUG_ENTER;
140    if (!StartSensor(type)) {
141        FI_HILOGE("sensor init failed");
142        return RET_ERR;
143    }
144    std::lock_guard lock(mutex_);
145    switch (type) {
146        case Type::TYPE_ABSOLUTE_STILL: {
147            if (still_ == nullptr) {
148                FI_HILOGE("still_ is nullptr");
149                still_ = std::make_shared<AlgoAbsoluteStill>();
150                still_->Init(type);
151                callAlgoNums_[type] = 0;
152            }
153            callAlgoNums_[type]++;
154            break;
155        }
156        case Type::TYPE_HORIZONTAL_POSITION: {
157            if (horizontalPosition_ == nullptr) {
158                FI_HILOGE("horizontalPosition_ is nullptr");
159                horizontalPosition_ = std::make_shared<AlgoHorizontal>();
160                horizontalPosition_->Init(type);
161                callAlgoNums_[type] = 0;
162            }
163            callAlgoNums_[type]++;
164            break;
165        }
166        case Type::TYPE_VERTICAL_POSITION: {
167            if (verticalPosition_ == nullptr) {
168                FI_HILOGE("verticalPosition_ is nullptr");
169                verticalPosition_ = std::make_shared<AlgoVertical>();
170                verticalPosition_->Init(type);
171                callAlgoNums_[type] = 0;
172            }
173            callAlgoNums_[type]++;
174            break;
175        }
176        default: {
177            FI_HILOGE("Unsupported algorithm type");
178            return RET_ERR;
179        }
180    }
181    algoType_ = type;
182    return RET_OK;
183}
184
185ErrCode AlgoMgr::Disable(Type type)
186{
187    CALL_DEBUG_ENTER;
188    std::lock_guard lock(mutex_);
189    callAlgoNums_[type]--;
190    FI_HILOGI("callAlgoNums_:%{public}d", callAlgoNums_[type]);
191    if (callAlgoNums_[type] != 0) {
192        FI_HILOGE("callAlgoNums_[type] is not zero");
193        return RET_ERR;
194    }
195    switch (type) {
196        case Type::TYPE_ABSOLUTE_STILL: {
197            if (still_ != nullptr) {
198                FI_HILOGD("still_ is not nullptr");
199                still_->Unsubscribe(type);
200                still_ = nullptr;
201            }
202            break;
203        }
204        case Type::TYPE_HORIZONTAL_POSITION: {
205            if (horizontalPosition_ != nullptr) {
206                FI_HILOGD("horizontalPosition_ is not nullptr");
207                horizontalPosition_->Unsubscribe(type);
208                horizontalPosition_ = nullptr;
209            }
210            break;
211        }
212        case Type::TYPE_VERTICAL_POSITION: {
213            if (verticalPosition_ != nullptr) {
214                FI_HILOGD("verticalPosition_ is not nullptr");
215                verticalPosition_->Unsubscribe(type);
216                verticalPosition_ = nullptr;
217            }
218            break;
219        }
220        default: {
221            FI_HILOGE("Unsupported algorithm type");
222            break;
223        }
224    }
225    callAlgoNums_.erase(type);
226    UnregisterSensor(type);
227    return RET_OK;
228}
229
230ErrCode AlgoMgr::DisableCount(Type type)
231{
232    CALL_DEBUG_ENTER;
233    return RET_OK;
234}
235
236ErrCode AlgoMgr::UnregisterSensor(Type type)
237{
238    CALL_DEBUG_ENTER;
239    int32_t sensorType = GetSensorTypeId(type);
240    if (sensorType == RET_ERR) {
241        FI_HILOGE("Failed to get sensorType");
242        return false;
243    }
244    if (!SENSOR_DATA_CB.UnregisterCallbackSensor(sensorType)) {
245        FI_HILOGE("Failed to unregister callback sensor");
246        return false;
247    }
248    return true;
249}
250
251extern "C" IMsdp *Create(void)
252{
253    CALL_DEBUG_ENTER;
254    return new (std::nothrow) AlgoMgr();
255}
256
257extern "C" void Destroy(const IMsdp* algorithm)
258{
259    CALL_DEBUG_ENTER;
260    if (algorithm != nullptr) {
261        FI_HILOGD("algorithm is not nullptr");
262        delete algorithm;
263    }
264}
265} // namespace DeviceStatus
266} // namespace Msdp
267} // namespace OHOS
268#endif // DEVICE_STATUS_SENSOR_ENABLE
269