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