* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "sensor_data_processer.h"
#include <cinttypes>
#include <sys/prctl.h>
#include <sys/socket.h>
#ifdef HIVIEWDFX_HISYSEVENT_ENABLE
#include "hisysevent.h"
#endif
#include "motion_plugin.h"
#include "print_sensor_data.h"
#include "sensor_data_manager.h"
#include "sensor_data_block_policy.h"
#include "sensor_shake_control_manager.h"
#include "sensor_utils.h"
#undef LOG_TAG
#define LOG_TAG "SensorDataProcesser"
namespace OHOS {
namespace Sensors {
using namespace OHOS::HiviewDFX;
namespace {
const std::string SENSOR_REPORT_THREAD_NAME = "OS_SenProducer";
const std::set<int32_t> g_noNeedMotionTransform = {
SENSOR_TYPE_ID_POSTURE, SENSOR_TYPE_ID_HALL, SENSOR_TYPE_ID_HALL_EXT,
SENSOR_TYPE_ID_PROXIMITY, SENSOR_TYPE_ID_PROXIMITY1, SENSOR_TYPE_ID_AMBIENT_LIGHT,
SENSOR_TYPE_ID_BAROMETER, SENSOR_TYPE_ID_TEMPERATURE, SENSOR_TYPE_ID_GESTURE,
SENSOR_TYPE_ID_PEDOMETER
};
const std::set<int32_t> g_shakeSensorControlList = {
SENSOR_TYPE_ID_ACCELEROMETER, SENSOR_TYPE_ID_MAGNETIC_FIELD, SENSOR_TYPE_ID_GYROSCOPE,
SENSOR_TYPE_ID_GRAVITY, SENSOR_TYPE_ID_LINEAR_ACCELERATION, SENSOR_TYPE_ID_ROTATION_VECTOR,
SENSOR_TYPE_ID_GAME_ROTATION_VECTOR, SENSOR_TYPE_ID_GYROSCOPE_UNCALIBRATED,
SENSOR_TYPE_ID_GEOMAGNETIC_ROTATION_VECTOR
};
}
SensorDataProcesser::SensorDataProcesser(const std::unordered_map<SensorDescription, Sensor> &sensorMap)
{
std::lock_guard<std::mutex> sensorLock(sensorMutex_);
sensorMap_.insert(sensorMap.begin(), sensorMap.end());
SEN_HILOGD("sensorMap_.size:%{public}d", int32_t { sensorMap_.size() });
}
SensorDataProcesser::~SensorDataProcesser()
{
{
std::lock_guard<std::mutex> dataCountLock(dataCountMutex_);
dataCountMap_.clear();
}
std::lock_guard<std::mutex> sensorLock(sensorMutex_);
sensorMap_.clear();
}
void SensorDataProcesser::UpdateSensorMap(const std::unordered_map<SensorDescription, Sensor> &sensorMap)
{
std::lock_guard<std::mutex> sensorLock(sensorMutex_);
sensorMap_.clear();
sensorMap_.insert(sensorMap.begin(), sensorMap.end());
SEN_HILOGD("sensorMap_.size:%{public}d", int32_t { sensorMap_.size() });
}
void SensorDataProcesser::SendNoneFifoCacheData(std::unordered_map<SensorDescription, SensorData> &cacheBuf,
sptr<SensorBasicDataChannel> &channel, SensorData &data,
uint64_t periodCount)
{
std::vector<SensorData> sendEvents;
std::lock_guard<std::mutex> dataCountLock(dataCountMutex_);
sendEvents.push_back(data);
auto dataCountIt = dataCountMap_.find({data.deviceId, data.sensorTypeId, data.sensorId, data.location});
if (dataCountIt == dataCountMap_.end()) {
std::vector<sptr<FifoCacheData>> channelFifoList;
sptr<FifoCacheData> fifoCacheData = new (std::nothrow) FifoCacheData();
CHKPV(fifoCacheData);
fifoCacheData->SetChannel(channel);
channelFifoList.push_back(fifoCacheData);
dataCountMap_.insert(std::pair<SensorDescription, std::vector<sptr<FifoCacheData>>>(
{data.deviceId, data.sensorTypeId, data.sensorId, data.location}, channelFifoList));
SendRawData(cacheBuf, channel, sendEvents);
return;
}
bool channelExist = false;
for (auto fifoIt = dataCountIt->second.begin(); fifoIt != dataCountIt->second.end();) {
auto fifoCacheData = *fifoIt;
CHKPC(fifoCacheData);
auto fifoChannel = fifoCacheData->GetChannel();
if (fifoChannel == nullptr) {
fifoIt = dataCountIt->second.erase(fifoIt);
continue;
}
++fifoIt;
if (fifoChannel != channel) {
continue;
}
channelExist = true;
uint64_t curCount = fifoCacheData->GetPeriodCount();
curCount++;
fifoCacheData->SetPeriodCount(curCount);
if (periodCount != 0 && fifoCacheData->GetPeriodCount() % periodCount != 0UL) {
continue;
}
SendRawData(cacheBuf, channel, sendEvents);
fifoCacheData->SetPeriodCount(0);
return;
}
if (!channelExist) {
sptr<FifoCacheData> fifoCacheData = new (std::nothrow) FifoCacheData();
CHKPV(fifoCacheData);
fifoCacheData->SetChannel(channel);
dataCountIt->second.push_back(fifoCacheData);
SendRawData(cacheBuf, channel, sendEvents);
}
}
void SensorDataProcesser::SendFifoCacheData(std::unordered_map<SensorDescription, SensorData> &cacheBuf,
sptr<SensorBasicDataChannel> &channel, SensorData &data,
uint64_t periodCount, uint64_t fifoCount)
{
std::lock_guard<std::mutex> dataCountLock(dataCountMutex_);
auto dataCountIt = dataCountMap_.find({data.deviceId, data.sensorTypeId, data.sensorId, data.location});
if (dataCountIt == dataCountMap_.end()) {
std::vector<sptr<FifoCacheData>> channelFifoList;
sptr<FifoCacheData> fifoCacheData = new (std::nothrow) FifoCacheData();
CHKPV(fifoCacheData);
fifoCacheData->SetChannel(channel);
channelFifoList.push_back(fifoCacheData);
dataCountMap_.insert(std::pair<SensorDescription, std::vector<sptr<FifoCacheData>>>(
{data.deviceId, data.sensorTypeId, data.sensorId, data.location}, channelFifoList));
return;
}
bool channelExist = false;
for (auto fifoIt = dataCountIt->second.begin(); fifoIt != dataCountIt->second.end();) {
auto fifoData = *fifoIt;
CHKPC(fifoData);
auto fifoChannel = fifoData->GetChannel();
if (fifoChannel == nullptr) {
fifoIt = dataCountIt->second.erase(fifoIt);
continue;
}
++fifoIt;
if (fifoChannel != channel) {
continue;
}
channelExist = true;
uint64_t curCount = fifoData->GetPeriodCount();
curCount++;
fifoData->SetPeriodCount(curCount);
if (fifoData->GetPeriodCount() % periodCount != 0UL) {
continue;
}
fifoData->SetPeriodCount(0);
std::vector<SensorData> fifoDataList = fifoData->GetFifoCacheData();
fifoDataList.push_back(data);
fifoData->SetFifoCacheData(fifoDataList);
if ((fifoData->GetFifoCacheData()).size() != fifoCount) {
continue;
}
SendRawData(cacheBuf, channel, fifoData->GetFifoCacheData());
fifoData->InitFifoCache();
return;
}
if (!channelExist) {
UpdataFifoDataChannel(channel, dataCountIt->second);
}
}
void SensorDataProcesser::UpdataFifoDataChannel(sptr<SensorBasicDataChannel> &channel,
std::vector<sptr<FifoCacheData>> &dataCount)
{
sptr<FifoCacheData> fifoCacheData = new (std::nothrow) FifoCacheData();
CHKPV(fifoCacheData);
fifoCacheData->SetChannel(channel);
dataCount.push_back(fifoCacheData);
}
void SensorDataProcesser::ReportData(sptr<SensorBasicDataChannel> &channel, SensorData &data)
{
CHKPV(channel);
int32_t sensorTypeId = data.sensorTypeId;
if (sensorTypeId == SENSOR_TYPE_ID_HALL_EXT) {
PrintSensorData::GetInstance().PrintSensorDataLog("ReportData", data);
}
auto &cacheBuf = const_cast<std::unordered_map<SensorDescription, SensorData> &>(channel->GetDataCacheBuf());
if (ReportNotContinuousData(cacheBuf, channel, data)) {
return;
}
uint64_t periodCount = clientInfo_.ComputeBestPeriodCount({data.deviceId, data.sensorTypeId, data.sensorId,
data.location}, channel);
if (periodCount == 0UL) {
SEN_HILOGE("periodCount is zero");
return;
}
auto fifoCount = clientInfo_.ComputeBestFifoCount({data.deviceId, data.sensorTypeId, data.sensorId,
data.location}, channel);
if (fifoCount <= 1) {
SendNoneFifoCacheData(cacheBuf, channel, data, periodCount);
return;
}
SendFifoCacheData(cacheBuf, channel, data, periodCount, fifoCount);
}
bool SensorDataProcesser::ReportNotContinuousData(std::unordered_map<SensorDescription, SensorData> &cacheBuf,
sptr<SensorBasicDataChannel> &channel, SensorData &data)
{
int32_t sensorTypeId = data.sensorTypeId;
std::lock_guard<std::mutex> sensorLock(sensorMutex_);
auto sensor = sensorMap_.find({data.deviceId, data.sensorTypeId, data.sensorId, data.location});
if (sensor == sensorMap_.end()) {
SEN_HILOGE("Data's SensorDesc is not supported");
return false;
}
sensor->second.SetFlags(data.mode);
if (((SENSOR_ON_CHANGE & sensor->second.GetFlags()) == SENSOR_ON_CHANGE) ||
((SENSOR_ONE_SHOT & sensor->second.GetFlags()) == SENSOR_ONE_SHOT)) {
std::vector<SensorData> sendEvents;
sendEvents.push_back(data);
if (sensorTypeId == SENSOR_TYPE_ID_HALL_EXT) {
PrintSensorData::GetInstance().PrintSensorDataLog("ReportNotContinuousData", data);
}
SendRawData(cacheBuf, channel, sendEvents);
return true;
}
return false;
}
void SensorDataProcesser::SendRawData(std::unordered_map<SensorDescription, SensorData> &cacheBuf,
sptr<SensorBasicDataChannel> channel, std::vector<SensorData> events)
{
CHKPV(channel);
if (events.empty()) {
return;
}
size_t eventSize = events.size();
auto ret = channel->SendData(events.data(), eventSize * sizeof(SensorData));
if (ret != ERR_OK) {
SEN_HILOGE("Send data failed, ret:%{public}d, sensorTypeId:%{public}d, timestamp:%{public}" PRId64,
ret, events[eventSize - 1].sensorTypeId, events[eventSize - 1].timestamp);
cacheBuf[{events[eventSize - 1].deviceId, events[eventSize - 1].sensorTypeId,
events[eventSize - 1].sensorId, events[eventSize - 1].location}] = events[eventSize - 1];
}
}
int32_t SensorDataProcesser::CacheSensorEvent(const SensorData &data, sptr<SensorBasicDataChannel> &channel)
{
CHKPR(channel, INVALID_POINTER);
int32_t ret = ERR_OK;
auto &cacheBuf = const_cast<std::unordered_map<SensorDescription, SensorData> &>(channel->GetDataCacheBuf());
if (data.sensorTypeId == SENSOR_TYPE_ID_HALL_EXT) {
PrintSensorData::GetInstance().PrintSensorDataLog("CacheSensorEvent", data);
}
auto cacheEvent = cacheBuf.find({data.deviceId, data.sensorTypeId, data.sensorId, data.location});
if (cacheEvent != cacheBuf.end()) {
const SensorData &cacheData = cacheEvent->second;
ret = channel->SendData(&cacheData, sizeof(SensorData));
if (ret != ERR_OK) {
SEN_HILOGE("retry send cacheData failed, ret:%{public}d, sensorType:%{public}d, timestamp:%{public}" PRId64,
ret, cacheData.sensorTypeId, cacheData.timestamp);
}
ret = channel->SendData(&data, sizeof(SensorData));
if (ret != ERR_OK) {
SEN_HILOGE("retry send data failed, ret:%{public}d, sensorType:%{public}d, timestamp:%{public}" PRId64,
ret, data.sensorTypeId, data.timestamp);
cacheBuf[{data.deviceId, data.sensorTypeId, data.sensorId, data.location}] = data;
} else {
cacheBuf.erase(cacheEvent);
}
} else {
ret = channel->SendData(&data, sizeof(SensorData));
if (ret != ERR_OK) {
SEN_HILOGE("directly retry failed, ret:%{public}d, sensorType:%{public}d, timestamp:%{public}" PRId64,
ret, data.sensorTypeId, data.timestamp);
cacheBuf[{data.deviceId, data.sensorTypeId, data.sensorId, data.location}] = data;
}
}
return ret;
}
void SensorDataProcesser::TransformSensorDataProcess(sptr<SensorBasicDataChannel> channel, SensorData &sensorData)
{
if (channel == nullptr) {
SEN_HILOGE("channel is null");
return;
}
if (!channel->GetSensorStatus()) {
SEN_HILOGW("Sensor status is not active");
return;
}
uint32_t state = clientInfo_.GetDeviceStatus();
MotionTransformIfRequired(channel->GetPackageName(), state, &sensorData);
std::vector<CompatibleAppData> appList = SENSOR_DATA_MGR->GetCompatibleAppStrategyList();
auto it = std::find_if(appList.begin(), appList.end(), [this, channel](const CompatibleAppData &app) {
return app.name == channel->GetPackageName();
});
if (it != appList.end()) {
int32_t deviceType = clientInfo_.GetDeviceType();
if ((static_cast<Sensors::DMDeviceStatus>(state) == Sensors::DMDeviceStatus::STATUS_GLOBAL_FULL &&
(deviceType == SINGLE_DISPLAY_THREE_FOLD || deviceType == SINGLE_DISPLAY_LAP_FOLD)) ||
(static_cast<Sensors::DMDeviceStatus>(state) == Sensors::DMDeviceStatus::STATUS_EXPAND &&
deviceType == SINGLE_DISPLAY_HP_FOLD)) {
sensorHdiConnection_.TransformSensorData(state, it->policy, &sensorData);
}
}
}
bool SensorDataProcesser::IsBlockSensorData(sptr<SensorBasicDataChannel> channel, int32_t sensorTypeId)
{
auto clientInfo = clientInfo_.GetAppInfoByChannel(channel);
if (clientInfo.pid > 0 && blockPolicy_.IsSensorDataBlocked(clientInfo.pid, sensorTypeId)) {
SEN_HILOGD("Sensor data blocked for pid:%{public}d, sensorType:%{public}d",
clientInfo.pid, sensorTypeId);
return true;
}
return false;
}
void SensorDataProcesser::EventFilter(CircularEventBuf &eventsBuf)
{
if (eventsBuf.circularBuf[eventsBuf.readPos].sensorTypeId == SENSOR_TYPE_ID_HALL_EXT) {
PrintSensorData::GetInstance().PrintSensorDataLog("EventFilter", eventsBuf.circularBuf[eventsBuf.readPos]);
}
std::vector<sptr<SensorBasicDataChannel>> channelList = clientInfo_.GetSensorChannel({
eventsBuf.circularBuf[eventsBuf.readPos].deviceId, eventsBuf.circularBuf[eventsBuf.readPos].sensorTypeId,
eventsBuf.circularBuf[eventsBuf.readPos].sensorId, eventsBuf.circularBuf[eventsBuf.readPos].location});
for (auto &channel : channelList) {
if (channel == nullptr) {
SEN_HILOGE("channel is null");
continue;
}
if (!channel->GetSensorStatus()) {
SEN_HILOGW("Sensor status is not active");
continue;
}
SensorData sensorData = eventsBuf.circularBuf[eventsBuf.readPos];
if (g_noNeedMotionTransform.find(sensorData.sensorTypeId) == g_noNeedMotionTransform.end()) {
TransformSensorDataProcess(channel, sensorData);
}
if ((g_shakeSensorControlList.find(sensorData.sensorTypeId) != g_shakeSensorControlList.end())
&& (SENSOR_SHAKE_CONTROL_MGR->CheckAppIsNeedControl(channel->GetPackageName(), channel->GetAccessTokenId(),
channel->GetUserId()))) {
SEN_HILOGD("Shake the sensor data for control, bundleName:%{public}s", channel->GetPackageName().c_str());
continue;
}
if (IsBlockSensorData(channel, sensorData.sensorTypeId)) {
continue;
}
SendEvents(channel, sensorData);
}
}
int32_t SensorDataProcesser::ProcessEvents(sptr<ReportDataCallback> dataCallback)
{
CHKPR(dataCallback, INVALID_POINTER);
std::unique_lock<std::mutex> lk(ISensorHdiConnection::dataMutex_);
ISensorHdiConnection::dataCondition_.wait(lk, [this] { return ISensorHdiConnection::dataReady_.load(); });
ISensorHdiConnection::dataReady_.store(false);
auto &eventsBuf = dataCallback->GetEventData();
if (eventsBuf.eventNum <= 0) {
SEN_HILOGE("Data cannot be empty");
return NO_EVENT;
}
int32_t eventNum = eventsBuf.eventNum;
for (int32_t i = 0; i < eventNum; i++) {
EventFilter(eventsBuf);
eventsBuf.readPos++;
if (eventsBuf.readPos >= CIRCULAR_BUF_LEN) {
eventsBuf.readPos = 0;
}
eventsBuf.eventNum--;
}
return SUCCESS;
}
int32_t SensorDataProcesser::SendEvents(sptr<SensorBasicDataChannel> &channel, SensorData &data)
{
CHKPR(channel, INVALID_POINTER);
clientInfo_.UpdateDataQueue(data.sensorTypeId, data);
auto &cacheBuf = channel->GetDataCacheBuf();
if (cacheBuf.empty()) {
ReportData(channel, data);
} else {
CacheSensorEvent(data, channel);
}
clientInfo_.StoreEvent(data);
return SUCCESS;
}
int32_t SensorDataProcesser::DataThread(sptr<SensorDataProcesser> dataProcesser, sptr<ReportDataCallback> dataCallback)
{
CALL_LOG_ENTER;
prctl(PR_SET_NAME, SENSOR_REPORT_THREAD_NAME.c_str());
do {
if (dataProcesser == nullptr || dataCallback == nullptr) {
SEN_HILOGE("dataProcesser or dataCallback is nullptr");
return INVALID_POINTER;
}
if (dataProcesser->ProcessEvents(dataCallback) == INVALID_POINTER) {
SEN_HILOGE("Callback cannot be null");
return INVALID_POINTER;
}
} while (1);
}
}
}