diff --git a/interfaces/plugin/include/sensor_napi_utils.h b/interfaces/plugin/include/sensor_napi_utils.h index ecc8ad7fcf1b6cac35cd3e10c990133324b40c0a..80612bf1cc2cacfb64ad386ff7b91c39f7a5e525 100644 --- a/interfaces/plugin/include/sensor_napi_utils.h +++ b/interfaces/plugin/include/sensor_napi_utils.h @@ -100,6 +100,8 @@ struct AsyncCallbackInfo { using ConvertDataFunc = void(*)(napi_env env, AsyncCallbackInfo *asyncCallbackInfo, napi_value result[2]); +bool IsNapiValueSame(napi_env env, napi_value lhs, napi_value rhs); + bool IsMatchType(napi_env env, napi_value value, napi_valuetype type); napi_value GetNapiInt32(int32_t number, napi_env env); diff --git a/interfaces/plugin/src/sensor_js.cpp b/interfaces/plugin/src/sensor_js.cpp index c5c54884f04e1203e54c752eef0b81f51d46381f..e675dc0e59940fcdcad2bab7c9e61e1d12651ef9 100644 --- a/interfaces/plugin/src/sensor_js.cpp +++ b/interfaces/plugin/src/sensor_js.cpp @@ -40,7 +40,7 @@ using namespace OHOS::HiviewDFX; static constexpr HiLogLabel LABEL = {LOG_CORE, 0xD002708, "SensorJsAPI"}; static std::map g_onceCallbackInfos; -static std::map g_onCallbackInfos; +static std::map> g_onCallbackInfos; static void DataCallbackImpl(SensorEvent *event) { @@ -52,17 +52,19 @@ static void DataCallbackImpl(SensorEvent *event) int32_t sensorTypeId = event->sensorTypeId; float *data = (float *)(event->data); if (g_onCallbackInfos.find(sensorTypeId) != g_onCallbackInfos.end()) { - struct AsyncCallbackInfo *onCallbackInfo = g_onCallbackInfos[sensorTypeId]; - onCallbackInfo->data.sensorData.sensorTypeId = sensorTypeId; - onCallbackInfo->data.sensorData.dataLength = event->dataLen; - onCallbackInfo->data.sensorData.timestamp = event->timestamp; - errno_t ret = memcpy_s(onCallbackInfo->data.sensorData.data, event->dataLen, data, event->dataLen); - if (ret != EOK) { - HiLog::Error(LABEL, "%{public}s copy data failed", __func__); - return; + for (uint32_t i = 0; i < g_onCallbackInfos[sensorTypeId].size(); ++i) { + g_onCallbackInfos[sensorTypeId][i]->data.sensorData.sensorTypeId = sensorTypeId; + g_onCallbackInfos[sensorTypeId][i]->data.sensorData.dataLength = event->dataLen; + g_onCallbackInfos[sensorTypeId][i]->data.sensorData.timestamp = event->timestamp; + errno_t ret = memcpy_s(g_onCallbackInfos[sensorTypeId][i]->data.sensorData.data, + event->dataLen, data, event->dataLen); + if (ret != EOK) { + HiLog::Error(LABEL, "%{public}s copy data failed", __func__); + return; + } + g_onCallbackInfos[sensorTypeId][i]->type = ON_CALLBACK; + EmitUvEventLoop(&g_onCallbackInfos[sensorTypeId][i]); } - onCallbackInfo->type = ON_CALLBACK; - EmitUvEventLoop(&g_onCallbackInfos[sensorTypeId]); } if (g_onceCallbackInfos.find(sensorTypeId) == g_onceCallbackInfos.end()) { @@ -170,9 +172,43 @@ static napi_value Once(napi_env env, napi_callback_info info) return nullptr; } +static bool IsSubscribed(napi_env env, int32_t sensorTypeId, napi_value callback) +{ + if (g_onCallbackInfos.find(sensorTypeId) == g_onCallbackInfos.end()) { + return false; + } + std::vector callbackInfos = g_onCallbackInfos[sensorTypeId]; + for (auto callbackInfo : callbackInfos) { + napi_value sensorCallback = nullptr; + napi_get_reference_value(env, callbackInfo->callback[0], &sensorCallback); + if (IsNapiValueSame(env, callback, sensorCallback)) { + return true; + } + } + return false; +} + +static void UpdateCallbackInfos(napi_env env, int32_t sensorTypeId, napi_value callback) +{ + if (IsSubscribed(env, sensorTypeId, callback)) { + HiLog::Debug(LABEL, "%{public}s the callback has been subscribed", __func__); + return; + } + AsyncCallbackInfo *asyncCallbackInfo = new AsyncCallbackInfo { + .env = env, + .asyncWork = nullptr, + .deferred = nullptr, + .type = ON_CALLBACK, + }; + napi_create_reference(env, callback, 1, &asyncCallbackInfo->callback[0]); + std::vector callbackInfos = g_onCallbackInfos[sensorTypeId]; + callbackInfos.push_back(asyncCallbackInfo); + g_onCallbackInfos[sensorTypeId] = callbackInfos; +} + static napi_value On(napi_env env, napi_callback_info info) { - HiLog::Info(LABEL, "%{public}s in", __func__); + HiLog::Debug(LABEL, "%{public}s in", __func__); size_t argc = 3; napi_value args[3] = { 0 }; napi_value thisVar = nullptr; @@ -188,33 +224,59 @@ static napi_value On(napi_env env, napi_callback_info info) int32_t sensorTypeId = GetCppInt32(args[0], env); int64_t interval = 200000000; if (argc == 3) { - HiLog::Info(LABEL, "%{public}s argc = 3!", __func__); napi_value value = NapiGetNamedProperty(args[2], "interval", env); if (!IsMatchType(env, value, napi_number)) { HiLog::Error(LABEL, "%{public}s argument should be napi_number type!", __func__); return nullptr; } interval = GetCppInt64(value, env); + HiLog::Debug(LABEL, "%{public}s interval is %{public}lld", __func__, interval); } - AsyncCallbackInfo *asyncCallbackInfo = new AsyncCallbackInfo { - .env = env, - .asyncWork = nullptr, - .deferred = nullptr, - }; - napi_create_reference(env, args[1], 1, &asyncCallbackInfo->callback[0]); - g_onCallbackInfos[sensorTypeId] = asyncCallbackInfo; int32_t ret = SubscribeSensor(sensorTypeId, interval, DataCallbackImpl); if (ret < 0) { - HiLog::Error(LABEL, "%{public}s subscribeSensor failed", __func__); - asyncCallbackInfo->type = FAIL; - asyncCallbackInfo->error.code = ret; - EmitAsyncCallbackWork(asyncCallbackInfo); - g_onCallbackInfos.erase(sensorTypeId); + HiLog::Error(LABEL, "%{public}s subscribeSensor failed", __func__); + return nullptr; } - HiLog::Info(LABEL, "%{public}s out", __func__); + UpdateCallbackInfos(env, sensorTypeId, args[1]); + HiLog::Debug(LABEL, "%{public}s end", __func__); return nullptr; } +static void RemoveAllCallback(napi_env env, int32_t sensorTypeId) +{ + std::vector callbackInfos = g_onCallbackInfos[sensorTypeId]; + for (auto callbackInfo : callbackInfos) { + napi_delete_reference(env, callbackInfo->callback[0]); + callbackInfo->callback[0] = nullptr; + delete callbackInfo; + callbackInfo = nullptr; + } + g_onCallbackInfos.erase(sensorTypeId); +} + +static uint32_t RemoveCallback(napi_env env, int32_t sensorTypeId, napi_value callback) +{ + std::vector callbackInfos = g_onCallbackInfos[sensorTypeId]; + std::vector::iterator iter; + for (iter = callbackInfos.begin(); iter != callbackInfos.end(); iter++) { + napi_value sensorCallback = nullptr; + napi_get_reference_value(env, (*iter)->callback[0], &sensorCallback); + if (IsNapiValueSame(env, callback, sensorCallback)) { + napi_delete_reference(env, (*iter)->callback[0]); + (*iter)->callback[0] = nullptr; + delete *iter; + *iter = nullptr; + callbackInfos.erase(iter); + if (callbackInfos.empty()) { + g_onCallbackInfos.erase(sensorTypeId); + return 0; + } + } + } + g_onCallbackInfos[sensorTypeId] = callbackInfos; + return callbackInfos.size(); +} + static napi_value Off(napi_env env, napi_callback_info info) { HiLog::Info(LABEL, "%{public}s in", __func__); @@ -222,38 +284,27 @@ static napi_value Off(napi_env env, napi_callback_info info) napi_value args[2] = { 0 }; napi_value thisVar = nullptr; NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisVar, NULL)); - - if (argc < 1) { + if (argc < 1 || argc > 2 || !IsMatchType(env, args[0], napi_number)) { HiLog::Error(LABEL, "%{public}s Invalid input.", __func__); return nullptr; } - if (!IsMatchType(env, args[0], napi_number) || !IsMatchType(env, args[1], napi_function)) { - HiLog::Error(LABEL, "%{public}s argument is invalid", __func__); + int32_t sensorTypeId = GetCppInt32(args[0], env); + if (g_onCallbackInfos.find(sensorTypeId) == g_onCallbackInfos.end() + || (argc == 2 && !IsSubscribed(env, sensorTypeId, args[1]))) { + HiLog::Error(LABEL, "%{public}s should subscribe first", __func__); return nullptr; } - int32_t sensorTypeId = GetCppInt32(args[0], env); - AsyncCallbackInfo *asyncCallbackInfo = new AsyncCallbackInfo { - .env = env, - .asyncWork = nullptr, - .deferred = nullptr, - }; - napi_create_reference(env, args[1], 1, &asyncCallbackInfo->callback[0]); + if (argc == 2 && RemoveCallback(env, sensorTypeId, args[1]) != 0) { + HiLog::Debug(LABEL, "%{public}s there are other client registrations as well", __func__); + return nullptr; + } + if (argc == 1) { + RemoveAllCallback(env, sensorTypeId); + } int32_t ret = UnsubscribeSensor(sensorTypeId); if (ret < 0) { - asyncCallbackInfo->type = FAIL; - asyncCallbackInfo->error.code = ret; HiLog::Error(LABEL, "%{public}s UnsubscribeSensor failed", __func__); - } else { - HiLog::Error(LABEL, "%{public}s UnsubscribeSensor success", __func__); - asyncCallbackInfo->type = OFF_CALLBACK; - if (g_onCallbackInfos.find(sensorTypeId) != g_onCallbackInfos.end()) { - napi_delete_reference(env, g_onCallbackInfos[sensorTypeId]->callback[0]); - delete g_onCallbackInfos[sensorTypeId]; - g_onCallbackInfos[sensorTypeId] = nullptr; - g_onCallbackInfos.erase(sensorTypeId); - } } - EmitAsyncCallbackWork(asyncCallbackInfo); return nullptr; } diff --git a/interfaces/plugin/src/sensor_napi_utils.cpp b/interfaces/plugin/src/sensor_napi_utils.cpp index 047a15ccea9802056e1fd6b0ed77ff674b0dac93..c942707dc2dd7d61aebe31e3985266eba490d3e8 100644 --- a/interfaces/plugin/src/sensor_napi_utils.cpp +++ b/interfaces/plugin/src/sensor_napi_utils.cpp @@ -25,6 +25,13 @@ using namespace OHOS::HiviewDFX; static constexpr HiLogLabel LABEL = {LOG_CORE, 0xD002708, "SensorJsAPI"}; +bool IsNapiValueSame(napi_env env, napi_value lhs, napi_value rhs) +{ + bool result = false; + napi_strict_equals(env, lhs, rhs, &result); + return result; +} + bool IsMatchType(napi_env env, napi_value value, napi_valuetype type) { napi_valuetype paramType = napi_undefined; @@ -443,7 +450,7 @@ void EmitUvEventLoop(AsyncCallbackInfo **asyncCallbackInfo) return; } g_convertfuncList[asyncCallbackInfo->type](env, asyncCallbackInfo, result); - napi_call_function(env, undefined, callback, 2, result, &callResult); + napi_call_function(env, undefined, callback, 1, &result[1], &callResult); if (asyncCallbackInfo->type != ON_CALLBACK) { napi_delete_reference(env, asyncCallbackInfo->callback[0]); delete asyncCallbackInfo; diff --git a/services/sensor/hdi_connection/adapter/src/compatible_connection.cpp b/services/sensor/hdi_connection/adapter/src/compatible_connection.cpp index add28f3a84638b9d2b006d3d05d60f5a1660f734..a3d95b9d96251f406965d157067b89acc5090809 100644 --- a/services/sensor/hdi_connection/adapter/src/compatible_connection.cpp +++ b/services/sensor/hdi_connection/adapter/src/compatible_connection.cpp @@ -123,13 +123,11 @@ int32_t CompatibleConnection::SetOption(int32_t sensorId, int32_t option) int32_t CompatibleConnection::SensorDataCallback(const struct SensorEvents *event) { - HiLog::Debug(LABEL, "%{public}s begin", __func__); if ((event == nullptr) || (event->dataLen == 0)) { HiLog::Error(LABEL, "%{public}s event is NULL", __func__); return ERR_INVALID_VALUE; } - - if (reportDataCb_ == nullptr) { + if (reportDataCb_ == nullptr || reportDataCallback_ == nullptr) { HiLog::Error(LABEL, "%{public}s reportDataCb_ cannot be null", __func__); return ERR_NO_INIT; } @@ -146,9 +144,9 @@ int32_t CompatibleConnection::SensorDataCallback(const struct SensorEvents *even errno_t ret = memcpy_s(sensorEvent.data, event->dataLen, event->data, event->dataLen); if (ret != EOK) { HiLog::Error(LABEL, "%{public}s copy data failed", __func__); + delete[] sensorEvent.data; return COPY_ERR; } - (void)(reportDataCallback_->*reportDataCb_)(&sensorEvent, reportDataCallback_); ISensorHdiConnection::dataCondition_.notify_one(); return ERR_OK; diff --git a/services/sensor/hdi_connection/adapter/src/hdi_connection.cpp b/services/sensor/hdi_connection/adapter/src/hdi_connection.cpp index 4315873bf6aca73d7cd18e0b4c65e362f223b874..bc9c43ccc4abd5dc51b8d064345583bb2e0abb39 100644 --- a/services/sensor/hdi_connection/adapter/src/hdi_connection.cpp +++ b/services/sensor/hdi_connection/adapter/src/hdi_connection.cpp @@ -248,6 +248,7 @@ void HdiConnection::setSensorBasicInfoState(int32_t sensorId, SensorState state) auto it = sensorBasicInfoMap_.find(sensorId); if (it == sensorBasicInfoMap_.end()) { HiLog::Warn(LABEL, "%{public}s should set batch first", __func__); + return; } sensorBasicInfoMap_[sensorId].SetSensorState(state); } diff --git a/services/sensor/hdi_connection/adapter/src/sensor_event_callback.cpp b/services/sensor/hdi_connection/adapter/src/sensor_event_callback.cpp index ce7036e7e7b399eb32e1240d8a9355111ae23dc1..0c3d7c88069bffedadfd6a9589b72e0b647cc427 100644 --- a/services/sensor/hdi_connection/adapter/src/sensor_event_callback.cpp +++ b/services/sensor/hdi_connection/adapter/src/sensor_event_callback.cpp @@ -27,7 +27,17 @@ std::unique_ptr HdiConnection_ = std::make_unique( } int32_t SensorEventCallback::OnDataEvent(const HdfSensorEvents& event) { - HiLog::Debug(LABEL, "%{public}s begin", __func__); + ZReportDataCb reportDataCb_ = HdiConnection_->getReportDataCb(); + sptr reportDataCallback_ = HdiConnection_->getReportDataCallback(); + if (reportDataCb_ == nullptr || reportDataCallback_ == nullptr) { + HiLog::Error(LABEL, "%{public}s reportDataCb_ or reportDataCallback_ cannot be null", __func__); + return ERR_NO_INIT; + } + int32_t dataSize = static_cast(event.data.size()); + if (dataSize == 0) { + HiLog::Error(LABEL, "%{public}s data is empty", __func__); + return ERR_INVALID_VALUE; + } struct SensorEvent sensorEvent = { .sensorTypeId = event.sensorId, .version = event.version, @@ -37,15 +47,9 @@ int32_t SensorEventCallback::OnDataEvent(const HdfSensorEvents& event) .dataLen = event.dataLen }; sensorEvent.data = new uint8_t[SENSOR_DATA_LENGHT]; - for (int32_t i = 0; i < static_cast(event.data.size()); i++) { + for (int32_t i = 0; i < static_cast(dataSize); i++) { sensorEvent.data[i] = event.data[i]; } - ZReportDataCb reportDataCb_ = HdiConnection_->getReportDataCb(); - sptr reportDataCallback_ = HdiConnection_->getReportDataCallback(); - if (reportDataCb_ == nullptr || reportDataCallback_ == nullptr) { - HiLog::Error(LABEL, "%{public}s reportDataCb_ cannot be null", __func__); - return ERR_NO_INIT; - } (void)(reportDataCallback_->*(reportDataCb_))(&sensorEvent, reportDataCallback_); ISensorHdiConnection::dataCondition_.notify_one(); return ERR_OK; diff --git a/services/sensor/hdi_connection/interface/src/sensor_hdi_connection.cpp b/services/sensor/hdi_connection/interface/src/sensor_hdi_connection.cpp index 2384713d86dd68e8c9dd599d7466605f7f6c59bc..78e631623b4efe91ce2f5addaeaa063ad11117f3 100644 --- a/services/sensor/hdi_connection/interface/src/sensor_hdi_connection.cpp +++ b/services/sensor/hdi_connection/interface/src/sensor_hdi_connection.cpp @@ -138,7 +138,7 @@ int32_t SensorHdiConnection::DestroyHdiConnection() { int32_t ret = iSensorHdiConnection_->DestroyHdiConnection(); if (ret != 0) { - HiLog::Info(LABEL, "%{public}s destroy hdi connectionr failed", __func__); + HiLog::Info(LABEL, "%{public}s destroy hdi connection failed", __func__); return DEVICE_ERR; } return ret; diff --git a/services/sensor/src/sensor_data_processer.cpp b/services/sensor/src/sensor_data_processer.cpp index e60040d74130d39538a36334f9250a8ed68f569b..044b7364b90fe7adfbb12c90ef71680a22b9d838 100644 --- a/services/sensor/src/sensor_data_processer.cpp +++ b/services/sensor/src/sensor_data_processer.cpp @@ -373,8 +373,7 @@ int32_t SensorDataProcesser::ProcessEvents(sptr dataCallback int32_t eventNum = eventsBuf.eventNum; for (int32_t i = 0; i < eventNum; i++) { EventFilter(eventsBuf); - delete eventsBuf.circularBuf[eventsBuf.readPosition].data; - eventsBuf.circularBuf[eventsBuf.readPosition].data = nullptr; + delete[] eventsBuf.circularBuf[eventsBuf.readPosition].data; eventsBuf.readPosition++; if (eventsBuf.readPosition == CIRCULAR_BUF_LEN) { eventsBuf.readPosition = 0; diff --git a/utils/include/sensor_basic_data_channel.h b/utils/include/sensor_basic_data_channel.h old mode 100755 new mode 100644 index 2507a8fbaae79a75acd61d3bd11234fb3dcb61bf..47c9f99b1e518b56844f5c3ffb4fe70ac1bd7d58 --- a/utils/include/sensor_basic_data_channel.h +++ b/utils/include/sensor_basic_data_channel.h @@ -28,12 +28,12 @@ namespace Sensors { constexpr int32_t INVALID_FD = -1; constexpr int32_t SENSOR_MAX_LENGTH = 64; struct TransferSensorEvents { - uint32_t sensorTypeId; /**< Sensor type ID */ - int32_t version; /**< Sensor algorithm version */ - int64_t timestamp; /**< Time when sensor data was reported */ - int32_t option; /**< Sensor data options, including the measurement range and accuracy */ - int32_t mode; /**< Sensor data reporting mode (described in {@link SensorMode}) */ - uint32_t dataLen; /**< Sensor data length */ + uint32_t sensorTypeId; + int32_t version; + int64_t timestamp; + int32_t option; + int32_t mode; + uint32_t dataLen; uint8_t data[SENSOR_MAX_LENGTH]; }; class SensorBasicDataChannel : public RefBase { diff --git a/utils/src/report_data_callback.cpp b/utils/src/report_data_callback.cpp index 513de8e9a2357b011164ca469d4cc99479c106bd..719e76cc11c12e5e4f0c122e9d2ef2dee7a34aa8 100644 --- a/utils/src/report_data_callback.cpp +++ b/utils/src/report_data_callback.cpp @@ -53,8 +53,13 @@ ReportDataCallback::~ReportDataCallback() int32_t ReportDataCallback::ZReportDataCallback(const struct SensorEvent* event, sptr cb) { - if (cb == nullptr || cb->eventsBuf_.circularBuf == nullptr || event == nullptr) { + if (event == nullptr) { + HiLog::Error(LABEL, "%{public}s sensor data is null", __func__); + return ERROR; + } + if (cb == nullptr || cb->eventsBuf_.circularBuf == nullptr) { HiLog::Error(LABEL, "%{public}s callback or circularBuf or event cannot be null", __func__); + delete[] event->data; return ERROR; } int32_t leftSize = CIRCULAR_BUF_LEN - cb->eventsBuf_.eventNum;