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