1 /*
2  * Copyright (c) 2021 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_processer.h"
17 
18 #include <cinttypes>
19 #include <sys/prctl.h>
20 #include <sys/socket.h>
21 #include <thread>
22 
23 #include "hisysevent.h"
24 #include "print_sensor_data.h"
25 #include "permission_util.h"
26 #include "securec.h"
27 #include "sensor_basic_data_channel.h"
28 #include "sensor_errors.h"
29 #include "system_ability_definition.h"
30 
31 #undef LOG_TAG
32 #define LOG_TAG "SensorDataProcesser"
33 
34 namespace OHOS {
35 namespace Sensors {
36 using namespace OHOS::HiviewDFX;
37 
38 namespace {
39 const std::string SENSOR_REPORT_THREAD_NAME = "OS_SenProducer";
40 } // namespace
41 
SensorDataProcesser(const std::unordered_map<int32_t,Sensor> & sensorMap)42 SensorDataProcesser::SensorDataProcesser(const std::unordered_map<int32_t, Sensor> &sensorMap)
43 {
44     sensorMap_.insert(sensorMap.begin(), sensorMap.end());
45     SEN_HILOGD("sensorMap_.size:%{public}d", int32_t { sensorMap_.size() });
46 }
47 
~SensorDataProcesser()48 SensorDataProcesser::~SensorDataProcesser()
49 {
50     dataCountMap_.clear();
51     sensorMap_.clear();
52 }
53 
SendNoneFifoCacheData(std::unordered_map<int32_t,SensorData> & cacheBuf,sptr<SensorBasicDataChannel> & channel,SensorData & data,uint64_t periodCount)54 void SensorDataProcesser::SendNoneFifoCacheData(std::unordered_map<int32_t, SensorData> &cacheBuf,
55                                                 sptr<SensorBasicDataChannel> &channel, SensorData &data,
56                                                 uint64_t periodCount)
57 {
58     std::vector<SensorData> sendEvents;
59     std::lock_guard<std::mutex> dataCountLock(dataCountMutex_);
60     sendEvents.push_back(data);
61     auto dataCountIt = dataCountMap_.find(data.sensorTypeId);
62     if (dataCountIt == dataCountMap_.end()) {
63         std::vector<sptr<FifoCacheData>> channelFifoList;
64         sptr<FifoCacheData> fifoCacheData = new (std::nothrow) FifoCacheData();
65         CHKPV(fifoCacheData);
66         fifoCacheData->SetChannel(channel);
67         channelFifoList.push_back(fifoCacheData);
68         dataCountMap_.insert(std::make_pair(data.sensorTypeId, channelFifoList));
69         SendRawData(cacheBuf, channel, sendEvents);
70         return;
71     }
72     bool channelExist = false;
73     for (auto fifoIt = dataCountIt->second.begin(); fifoIt != dataCountIt->second.end();) {
74         auto fifoCacheData = *fifoIt;
75         CHKPC(fifoCacheData);
76         auto fifoChannel = fifoCacheData->GetChannel();
77         if (fifoChannel == nullptr) {
78             fifoIt = dataCountIt->second.erase(fifoIt);
79             continue;
80         }
81         ++fifoIt;
82         if (fifoChannel != channel) {
83             continue;
84         }
85         channelExist = true;
86         uint64_t curCount = fifoCacheData->GetPeriodCount();
87         curCount++;
88         fifoCacheData->SetPeriodCount(curCount);
89         if (periodCount != 0 && fifoCacheData->GetPeriodCount() % periodCount != 0UL) {
90             continue;
91         }
92         SendRawData(cacheBuf, channel, sendEvents);
93         fifoCacheData->SetPeriodCount(0);
94         return;
95     }
96     if (!channelExist) {
97         sptr<FifoCacheData> fifoCacheData = new (std::nothrow) FifoCacheData();
98         CHKPV(fifoCacheData);
99         fifoCacheData->SetChannel(channel);
100         dataCountIt->second.push_back(fifoCacheData);
101         SendRawData(cacheBuf, channel, sendEvents);
102     }
103 }
104 
SendFifoCacheData(std::unordered_map<int32_t,SensorData> & cacheBuf,sptr<SensorBasicDataChannel> & channel,SensorData & data,uint64_t periodCount,uint64_t fifoCount)105 void SensorDataProcesser::SendFifoCacheData(std::unordered_map<int32_t, SensorData> &cacheBuf,
106                                             sptr<SensorBasicDataChannel> &channel, SensorData &data,
107                                             uint64_t periodCount, uint64_t fifoCount)
108 {
109     std::lock_guard<std::mutex> dataCountLock(dataCountMutex_);
110     auto dataCountIt = dataCountMap_.find(data.sensorTypeId);
111     // there is no channelFifoList
112     if (dataCountIt == dataCountMap_.end()) {
113         std::vector<sptr<FifoCacheData>> channelFifoList;
114         sptr<FifoCacheData> fifoCacheData = new (std::nothrow) FifoCacheData();
115         CHKPV(fifoCacheData);
116         fifoCacheData->SetChannel(channel);
117         channelFifoList.push_back(fifoCacheData);
118         dataCountMap_.insert(std::make_pair(data.sensorTypeId, channelFifoList));
119         return;
120     }
121     // find channel in channelFifoList
122     bool channelExist = false;
123     for (auto fifoIt = dataCountIt->second.begin(); fifoIt != dataCountIt->second.end();) {
124         auto fifoData = *fifoIt;
125         CHKPC(fifoData);
126         auto fifoChannel = fifoData->GetChannel();
127         if (fifoChannel == nullptr) {
128             fifoIt = dataCountIt->second.erase(fifoIt);
129             continue;
130         }
131         ++fifoIt;
132         if (fifoChannel != channel) {
133             continue;
134         }
135         channelExist = true;
136         uint64_t curCount = fifoData->GetPeriodCount();
137         curCount++;
138         fifoData->SetPeriodCount(curCount);
139         if (fifoData->GetPeriodCount() % periodCount != 0UL) {
140             continue;
141         }
142         fifoData->SetPeriodCount(0);
143         std::vector<SensorData> fifoDataList = fifoData->GetFifoCacheData();
144         fifoDataList.push_back(data);
145         fifoData->SetFifoCacheData(fifoDataList);
146         if ((fifoData->GetFifoCacheData()).size() != fifoCount) {
147             continue;
148         }
149         SendRawData(cacheBuf, channel, fifoData->GetFifoCacheData());
150         fifoData->InitFifoCache();
151         return;
152     }
153     // cannot find channel in channelFifoList
154     if (!channelExist) {
155         sptr<FifoCacheData> fifoCacheData = new (std::nothrow) FifoCacheData();
156         CHKPV(fifoCacheData);
157         fifoCacheData->SetChannel(channel);
158         dataCountIt->second.push_back(fifoCacheData);
159     }
160 }
161 
ReportData(sptr<SensorBasicDataChannel> & channel,SensorData & data)162 void SensorDataProcesser::ReportData(sptr<SensorBasicDataChannel> &channel, SensorData &data)
163 {
164     CHKPV(channel);
165     int32_t sensorId = data.sensorTypeId;
166     if (sensorId == SENSOR_TYPE_ID_HALL_EXT) {
167         PrintSensorData::GetInstance().PrintSensorDataLog("ReportData", data);
168     }
169     auto &cacheBuf = const_cast<std::unordered_map<int32_t, SensorData> &>(channel->GetDataCacheBuf());
170     if (ReportNotContinuousData(cacheBuf, channel, data)) {
171         return;
172     }
173     uint64_t periodCount = clientInfo_.ComputeBestPeriodCount(sensorId, channel);
174     if (periodCount == 0UL) {
175         SEN_HILOGE("periodCount is zero");
176         return;
177     }
178     auto fifoCount = clientInfo_.ComputeBestFifoCount(sensorId, channel);
179     if (fifoCount <= 1) {
180         SendNoneFifoCacheData(cacheBuf, channel, data, periodCount);
181         return;
182     }
183     SendFifoCacheData(cacheBuf, channel, data, periodCount, fifoCount);
184 }
185 
ReportNotContinuousData(std::unordered_map<int32_t,SensorData> & cacheBuf,sptr<SensorBasicDataChannel> & channel,SensorData & data)186 bool SensorDataProcesser::ReportNotContinuousData(std::unordered_map<int32_t, SensorData> &cacheBuf,
187                                                   sptr<SensorBasicDataChannel> &channel, SensorData &data)
188 {
189     int32_t sensorId = data.sensorTypeId;
190     std::lock_guard<std::mutex> sensorLock(sensorMutex_);
191     auto sensor = sensorMap_.find(sensorId);
192     if (sensor == sensorMap_.end()) {
193         SEN_HILOGE("Data's sensorId is not supported");
194         return false;
195     }
196     sensor->second.SetFlags(data.mode);
197     if (((SENSOR_ON_CHANGE & sensor->second.GetFlags()) == SENSOR_ON_CHANGE) ||
198         ((SENSOR_ONE_SHOT & sensor->second.GetFlags()) == SENSOR_ONE_SHOT)) {
199         std::vector<SensorData> sendEvents;
200         sendEvents.push_back(data);
201         if (sensorId == SENSOR_TYPE_ID_HALL_EXT) {
202             PrintSensorData::GetInstance().PrintSensorDataLog("ReportNotContinuousData", data);
203         }
204         SendRawData(cacheBuf, channel, sendEvents);
205         return true;
206     }
207     return false;
208 }
209 
SendRawData(std::unordered_map<int32_t,SensorData> & cacheBuf,sptr<SensorBasicDataChannel> channel,std::vector<SensorData> events)210 void SensorDataProcesser::SendRawData(std::unordered_map<int32_t, SensorData> &cacheBuf,
211                                       sptr<SensorBasicDataChannel> channel, std::vector<SensorData> events)
212 {
213     CHKPV(channel);
214     if (events.empty()) {
215         return;
216     }
217     size_t eventSize = events.size();
218     auto ret = channel->SendData(events.data(), eventSize * sizeof(SensorData));
219     if (ret != ERR_OK) {
220         SEN_HILOGE("Send data failed, ret:%{public}d, sensorId:%{public}d, timestamp:%{public}" PRId64,
221             ret, events[eventSize - 1].sensorTypeId, events[eventSize - 1].timestamp);
222         int32_t sensorId = events[eventSize - 1].sensorTypeId;
223         cacheBuf[sensorId] = events[eventSize - 1];
224     }
225 }
226 
CacheSensorEvent(const SensorData & data,sptr<SensorBasicDataChannel> & channel)227 int32_t SensorDataProcesser::CacheSensorEvent(const SensorData &data, sptr<SensorBasicDataChannel> &channel)
228 {
229     CHKPR(channel, INVALID_POINTER);
230     int32_t ret = ERR_OK;
231     auto &cacheBuf = const_cast<std::unordered_map<int32_t, SensorData> &>(channel->GetDataCacheBuf());
232     int32_t sensorId = data.sensorTypeId;
233     if (sensorId == SENSOR_TYPE_ID_HALL_EXT) {
234         PrintSensorData::GetInstance().PrintSensorDataLog("CacheSensorEvent", data);
235     }
236     auto cacheEvent = cacheBuf.find(sensorId);
237     if (cacheEvent != cacheBuf.end()) {
238         // Try to send the last failed value, if it still fails, replace the previous cache directly
239         const SensorData &cacheData = cacheEvent->second;
240         ret = channel->SendData(&cacheData, sizeof(SensorData));
241         if (ret != ERR_OK) {
242             SEN_HILOGE("retry send cache data failed, ret:%{public}d, sensorId:%{public}d, timestamp:%{public}" PRId64,
243                 ret, cacheData.sensorTypeId, cacheData.timestamp);
244         }
245         ret = channel->SendData(&data, sizeof(SensorData));
246         if (ret != ERR_OK) {
247             SEN_HILOGE("retry send data failed, ret:%{public}d, sensorId:%{public}d, timestamp:%{public}" PRId64,
248                 ret, data.sensorTypeId, data.timestamp);
249             cacheBuf[sensorId] = data;
250         } else {
251             cacheBuf.erase(cacheEvent);
252         }
253     } else {
254         ret = channel->SendData(&data, sizeof(SensorData));
255         if (ret != ERR_OK) {
256             SEN_HILOGE("directly retry failed, ret:%{public}d, sensorId:%{public}d, timestamp:%{public}" PRId64,
257                 ret, data.sensorTypeId, data.timestamp);
258             cacheBuf[sensorId] = data;
259         }
260     }
261     return ret;
262 }
263 
EventFilter(CircularEventBuf & eventsBuf)264 void SensorDataProcesser::EventFilter(CircularEventBuf &eventsBuf)
265 {
266     int32_t sensorId = eventsBuf.circularBuf[eventsBuf.readPos].sensorTypeId;
267     if (sensorId == SENSOR_TYPE_ID_HALL_EXT) {
268         PrintSensorData::GetInstance().PrintSensorDataLog("EventFilter", eventsBuf.circularBuf[eventsBuf.readPos]);
269     }
270     std::vector<sptr<SensorBasicDataChannel>> channelList = clientInfo_.GetSensorChannel(sensorId);
271     for (auto &channel : channelList) {
272         if (!channel->GetSensorStatus()) {
273             SEN_HILOGW("Sensor status is not active");
274             continue;
275         }
276         SendEvents(channel, eventsBuf.circularBuf[eventsBuf.readPos]);
277     }
278 }
279 
ProcessEvents(sptr<ReportDataCallback> dataCallback)280 int32_t SensorDataProcesser::ProcessEvents(sptr<ReportDataCallback> dataCallback)
281 {
282     CHKPR(dataCallback, INVALID_POINTER);
283     std::unique_lock<std::mutex> lk(ISensorHdiConnection::dataMutex_);
284     ISensorHdiConnection::dataCondition_.wait(lk, [this] { return ISensorHdiConnection::dataReady_.load(); });
285     ISensorHdiConnection::dataReady_.store(false);
286     auto &eventsBuf = dataCallback->GetEventData();
287     if (eventsBuf.eventNum <= 0) {
288         SEN_HILOGE("Data cannot be empty");
289         return NO_EVENT;
290     }
291     int32_t eventNum = eventsBuf.eventNum;
292     for (int32_t i = 0; i < eventNum; i++) {
293         EventFilter(eventsBuf);
294         eventsBuf.readPos++;
295         if (eventsBuf.readPos >= CIRCULAR_BUF_LEN) {
296             eventsBuf.readPos = 0;
297         }
298         eventsBuf.eventNum--;
299     }
300     return SUCCESS;
301 }
302 
SendEvents(sptr<SensorBasicDataChannel> & channel,SensorData & data)303 int32_t SensorDataProcesser::SendEvents(sptr<SensorBasicDataChannel> &channel, SensorData &data)
304 {
305     CHKPR(channel, INVALID_POINTER);
306     clientInfo_.UpdateDataQueue(data.sensorTypeId, data);
307     auto &cacheBuf = channel->GetDataCacheBuf();
308     if (cacheBuf.empty()) {
309         ReportData(channel, data);
310     } else {
311         CacheSensorEvent(data, channel);
312     }
313     clientInfo_.StoreEvent(data);
314     return SUCCESS;
315 }
316 
DataThread(sptr<SensorDataProcesser> dataProcesser,sptr<ReportDataCallback> dataCallback)317 int32_t SensorDataProcesser::DataThread(sptr<SensorDataProcesser> dataProcesser, sptr<ReportDataCallback> dataCallback)
318 {
319     CALL_LOG_ENTER;
320     prctl(PR_SET_NAME, SENSOR_REPORT_THREAD_NAME.c_str());
321     do {
322         if (dataProcesser == nullptr || dataCallback == nullptr) {
323             SEN_HILOGE("dataProcesser or dataCallback is nullptr");
324             return INVALID_POINTER;
325         }
326         if (dataProcesser->ProcessEvents(dataCallback) == INVALID_POINTER) {
327             SEN_HILOGE("Callback cannot be null");
328             return INVALID_POINTER;
329         }
330     } while (1);
331 }
332 }  // namespace Sensors
333 }  // namespace OHOS
334