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