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 "sensor_data_callback.h"
18 
19 #include <cmath>
20 #include <cstdio>
21 
22 #include "devicestatus_define.h"
23 #include "include/util.h"
24 
25 #undef LOG_TAG
26 #define LOG_TAG "SensorDataCallback"
27 
28 namespace OHOS {
29 namespace Msdp {
30 namespace DeviceStatus {
31 namespace {
32 constexpr int32_t RATE_MILLISEC { 100100100 };
33 } // namespace
34 
SensorDataCallback()35 SensorDataCallback::SensorDataCallback() {}
~SensorDataCallback()36 SensorDataCallback::~SensorDataCallback()
37 {
38     algoMap_.clear();
39     alive_ = false;
40     CHKPV(algorithmThread_);
41     if (!algorithmThread_->joinable()) {
42         FI_HILOGE("Thread join failed");
43         return;
44     }
45     sem_post(&sem_);
46     algorithmThread_->join();
47     accelDataList_.clear();
48 }
49 
Init()50 void SensorDataCallback::Init()
51 {
52     FI_HILOGI("SensorDataCallback is initiated");
53     std::lock_guard lock(initMutex_);
54     if (algorithmThread_ == nullptr) {
55         FI_HILOGI("Create algorithm thread");
56         algorithmThread_ = std::make_unique<std::thread>([this] { this->AlgorithmLoop(); });
57     }
58 }
59 
Unregister()60 bool SensorDataCallback::Unregister()
61 {
62     CALL_DEBUG_ENTER;
63     bool ret = UnregisterCallbackSensor(SensorTypeId::SENSOR_TYPE_ID_ACCELEROMETER);
64     if (!ret) {
65         FI_HILOGE("UnregisterCallbackSensor failed");
66         return false;
67     }
68     alive_ = false;
69     {
70         std::lock_guard lock(initMutex_);
71         CHKPF(algorithmThread_);
72         if (!algorithmThread_->joinable()) {
73             FI_HILOGE("Thread join failed");
74             return false;
75         }
76     }
77     sem_post(&sem_);
78     {
79         std::lock_guard lock(initMutex_);
80         algorithmThread_->join();
81     }
82     return ret;
83 }
84 
SubscribeSensorEvent(int32_t sensorTypeId,SensorCallback callback)85 bool SensorDataCallback::SubscribeSensorEvent(int32_t sensorTypeId, SensorCallback callback)
86 {
87     CALL_DEBUG_ENTER;
88     std::lock_guard lock(callbackMutex_);
89     auto ret = algoMap_.insert(std::pair(sensorTypeId, callback));
90     if (ret.second) {
91         return true;
92     }
93     FI_HILOGE("SensorCallback is duplicated");
94     return false;
95 }
96 
UnsubscribeSensorEvent(int32_t sensorTypeId,SensorCallback callback)97 bool SensorDataCallback::UnsubscribeSensorEvent(int32_t sensorTypeId, SensorCallback callback)
98 {
99     CALL_DEBUG_ENTER;
100     std::lock_guard lock(callbackMutex_);
101     auto callbackIter = algoMap_.find(sensorTypeId);
102     if (callbackIter != algoMap_.end()) {
103         FI_HILOGE("Erase sensorTypeId:%{public}d", sensorTypeId);
104         algoMap_.erase(callbackIter);
105     }
106     return true;
107 }
108 
NotifyCallback(int32_t sensorTypeId,AccelData * data)109 bool SensorDataCallback::NotifyCallback(int32_t sensorTypeId, AccelData* data)
110 {
111     CHKPF(data);
112     std::lock_guard lock(callbackMutex_);
113     for (auto iter = algoMap_.begin(); iter != algoMap_.end(); ++iter) {
114         (iter->second)(sensorTypeId, data);
115     }
116     return true;
117 }
118 
PushData(int32_t sensorTypeId,uint8_t * data)119 bool SensorDataCallback::PushData(int32_t sensorTypeId, uint8_t* data)
120 {
121     CALL_DEBUG_ENTER;
122     CHKPF(data);
123     AccelData* acclData = reinterpret_cast<AccelData*>(data);
124     if ((abs(acclData->x) > ACC_VALID_THRHD) ||
125         (abs(acclData->y) > ACC_VALID_THRHD) ||
126         (abs(acclData->z) > ACC_VALID_THRHD)) {
127         FI_HILOGE("Acc data is invalid");
128         return false;
129     }
130     {
131         std::lock_guard lock(dataMutex_);
132         accelDataList_.emplace_back(*acclData);
133         FI_HILOGD("ACCEL pushData:x:%{public}f, y:%{public}f, z:%{public}f, PushData sensorTypeId:%{public}d",
134             acclData->x, acclData->y, acclData->z, sensorTypeId);
135     }
136     sem_post(&sem_);
137     return true;
138 }
139 
PopData(int32_t sensorTypeId,AccelData & data)140 bool SensorDataCallback::PopData(int32_t sensorTypeId, AccelData& data)
141 {
142     CALL_DEBUG_ENTER;
143     if (sensorTypeId != SENSOR_TYPE_ID_ACCELEROMETER) {
144         FI_HILOGE("Invalid sensorTypeId:%{public}d", sensorTypeId);
145         return false;
146     }
147     std::lock_guard lock(dataMutex_);
148     if (accelDataList_.empty()) {
149         FI_HILOGE("No accel data");
150         return false;
151     }
152     data = accelDataList_.front();
153     accelDataList_.pop_front();
154     FI_HILOGD("ACCEL popData:x:%{public}f, y:%{public}f, z:%{public}f, PopData sensorTypeId:%{public}d",
155         data.x, data.y, data.z, sensorTypeId);
156     return true;
157 }
158 
SensorDataCallbackImpl(SensorEvent * event)159 static void SensorDataCallbackImpl(SensorEvent *event)
160 {
161     CALL_DEBUG_ENTER;
162     CHKPV(event);
163     FI_HILOGI("SensorDataCallbackImpl sensorTypeId:%{public}d", event->sensorTypeId);
164     SENSOR_DATA_CB.PushData(event->sensorTypeId, event->data);
165 }
166 
RegisterCallbackSensor(int32_t sensorTypeId)167 bool SensorDataCallback::RegisterCallbackSensor(int32_t sensorTypeId)
168 {
169     std::lock_guard lock(sensorMutex_);
170     user_.callback = SensorDataCallbackImpl;
171     int32_t ret = SubscribeSensor(sensorTypeId, &user_);
172     if (ret != 0) {
173         FI_HILOGE("SubscribeSensor failed");
174         return false;
175     }
176     ret = SetBatch(sensorTypeId, &user_, RATE_MILLISEC, RATE_MILLISEC);
177     if (ret != 0) {
178         FI_HILOGE("SetBatch failed");
179         return false;
180     }
181     ret = ActivateSensor(sensorTypeId, &user_);
182     if (ret != 0) {
183         FI_HILOGE("ActivateSensor failed");
184         return false;
185     }
186     return true;
187 }
188 
UnregisterCallbackSensor(int32_t sensorTypeId)189 bool SensorDataCallback::UnregisterCallbackSensor(int32_t sensorTypeId)
190 {
191     CALL_DEBUG_ENTER;
192     std::lock_guard lock(sensorMutex_);
193     CHKPF(user_.callback);
194     int32_t ret = DeactivateSensor(sensorTypeId, &user_);
195     if (ret != 0) {
196         FI_HILOGE("DeactivateSensor failed");
197         return false;
198     }
199     ret = UnsubscribeSensor(sensorTypeId, &user_);
200     if (ret != 0) {
201         FI_HILOGE("UnsubscribeSensor failed");
202         return false;
203     }
204     return true;
205 }
206 
AlgorithmLoop()207 void SensorDataCallback::AlgorithmLoop()
208 {
209     SetThreadName(std::string("os_loop_sensor"));
210     CALL_DEBUG_ENTER;
211     while (alive_) {
212         sem_wait(&sem_);
213         HandleSensorEvent();
214     }
215 }
216 
HandleSensorEvent()217 void SensorDataCallback::HandleSensorEvent()
218 {
219     CALL_DEBUG_ENTER;
220     AccelData acclData;
221     if (PopData(SENSOR_TYPE_ID_ACCELEROMETER, acclData)) {
222         NotifyCallback(SENSOR_TYPE_ID_ACCELEROMETER, static_cast<AccelData*>(&acclData));
223     }
224 }
225 } // namespace DeviceStatus
226 } // namespace Msdp
227 } // namespace OHOS
228 #endif // DEVICE_STATUS_SENSOR_ENABLE
229