diff --git a/frameworks/js/napi/include/sensor_napi_utils.h b/frameworks/js/napi/include/sensor_napi_utils.h index 1b5ce939f644d65ea47bb6140789a2ab684d7631..96d2c7e262f71d97194e20d3e011d79fa4cb92a2 100644 --- a/frameworks/js/napi/include/sensor_napi_utils.h +++ b/frameworks/js/napi/include/sensor_napi_utils.h @@ -42,6 +42,7 @@ napi_value GetNapiInt32(const napi_env &env, int32_t number); bool GetStringValue(const napi_env &env, const napi_value &value, string &result); void EmitAsyncCallbackWork(sptr asyncCallbackInfo); void EmitUvEventLoop(sptr asyncCallbackInfo); +void EmitOnUvEventLoop(sptr asyncCallbackInfo, std::shared_ptr cb); void EmitPromiseWork(sptr asyncCallbackInfo); bool ConvertToFailData(const napi_env &env, sptr asyncCallbackInfo, napi_value result[2]); bool ConvertToGeomagneticData(const napi_env &env, sptr asyncCallbackInfo, napi_value result[2]); @@ -53,6 +54,8 @@ bool CreateNapiArray(const napi_env &env, float *data, int32_t dataLength, napi_ bool ConvertToSensorInfos(const napi_env &env, sptr asyncCallbackInfo, napi_value result[2]); bool ConvertToSingleSensor(const napi_env &env, sptr asyncCallbackInfo, napi_value result[2]); bool ConvertToSensorInfo(const napi_env &env, const SensorInfo &sensorInfo, napi_value &result); +bool ConvertOnSensorData(const napi_env &env, sptr asyncCallbackInfo, napi_value result[2], + std::shared_ptr data); bool ConvertToBodyData(const napi_env &env, sptr asyncCallbackInfo, napi_value result[2]); bool CreateFailMessage(CallbackDataType type, int32_t code, string message, sptr &asyncCallbackInfo); diff --git a/frameworks/js/napi/src/sensor_js.cpp b/frameworks/js/napi/src/sensor_js.cpp index e8945a0fd8684548229bce006425626e7cfb2134..40562d5c5e2205815c8890e57a5c65ff401c1a65 100644 --- a/frameworks/js/napi/src/sensor_js.cpp +++ b/frameworks/js/napi/src/sensor_js.cpp @@ -109,6 +109,41 @@ static bool copySensorData(sptr callbackInfo, SensorEvent *ev return true; } +static bool copyOnSensorData(sptr callbackInfo, SensorEvent *event, + std::shared_ptr cb) +{ + CHKPF(callbackInfo); + CHKPF(event); + CHKPF(cb); + int32_t sensorTypeId = event->sensorTypeId; + cb->sensorTypeId = sensorTypeId; + cb->dataLength = event->dataLen; + cb->timestamp = event->timestamp; + cb->sensorAccuracy = event->option; + CHKPF(event->data); + if (event->dataLen < sizeof(float)) { + SEN_HILOGE("Event dataLen less than float size"); + return false; + } + auto data = reinterpret_cast(event->data); + if (sensorTypeId == SENSOR_TYPE_ID_WEAR_DETECTION && callbackInfo->type == SUBSCRIBE_CALLBACK) { + std::lock_guard onBodyLock(g_bodyMutex); + g_bodyState = *data; + cb->data[0] = (fabs(g_bodyState - BODY_STATE_EXCEPT) < THRESHOLD) ? true : false; + return true; + } + if (sizeof(cb->data) < event->dataLen) { + SEN_HILOGE("callbackInfo space is insufficient"); + return false; + } + if (memcpy_s(cb->data, sizeof(cb->data), + data, event->dataLen) != EOK) { + SEN_HILOGE("Copy data failed"); + return false; + } + return true; +} + static bool CheckSystemSubscribe(SensorDescription sensorDesc) { std::lock_guard subscribeLock(g_mutex); @@ -142,11 +177,12 @@ static void EmitOnCallback(SensorEvent *event) std::lock_guard onCallbackLock(g_onMutex); auto onCallbackInfos = g_onCallbackInfos[{event->deviceId, event->sensorTypeId, event->sensorId, event->location}]; for (auto &onCallbackInfo : onCallbackInfos) { - if (!copySensorData(onCallbackInfo, event)) { + std::shared_ptr cb = std::make_shared(); + if (!copyOnSensorData(onCallbackInfo, event, cb)) { SEN_HILOGE("Copy sensor data failed"); continue; } - EmitUvEventLoop(onCallbackInfo); + EmitOnUvEventLoop(onCallbackInfo, cb); } } diff --git a/frameworks/js/napi/src/sensor_napi_utils.cpp b/frameworks/js/napi/src/sensor_napi_utils.cpp index 20adf402d3345e29afc6bdff49a42e39b994a4c8..050bf36f3c620a54ed76362d9b1f9db5745be1a4 100644 --- a/frameworks/js/napi/src/sensor_napi_utils.cpp +++ b/frameworks/js/napi/src/sensor_napi_utils.cpp @@ -398,6 +398,46 @@ bool ConvertToSensorData(const napi_env &env, sptr asyncCallb return true; } +bool ConvertOnSensorData(const napi_env &env, sptr asyncCallbackInfo, napi_value result[2], + std::shared_ptr data) +{ + CHKPF(asyncCallbackInfo); + CHKPF(data); + int32_t sensorTypeId = data->sensorTypeId; + std::lock_guard sensorAttrListLock(g_sensorAttrListMutex); + CHKNCF(env, (g_sensorAttributeList.find(sensorTypeId) != g_sensorAttributeList.end()), "Invalid sensor type"); + if (sensorTypeId == SENSOR_TYPE_ID_WEAR_DETECTION && asyncCallbackInfo->type == SUBSCRIBE_CALLBACK) { + CHKNRF(env, napi_create_object(env, &result[1]), "napi_create_object"); + napi_value status = nullptr; + CHKNRF(env, napi_get_boolean(env, data->data[0], &status), + "napi_get_boolean"); + CHKNRF(env, napi_set_named_property(env, result[1], "value", status), "napi_set_named_property"); + return true; + } + size_t size = g_sensorAttributeList[sensorTypeId].size(); + uint32_t dataLength = data->dataLength / sizeof(float); + CHKNCF(env, (size <= dataLength), "Data length mismatch"); + + CHKNRF(env, napi_create_object(env, &result[1]), "napi_create_object"); + napi_value message = nullptr; + auto sensorAttributes = g_sensorAttributeList[sensorTypeId]; + for (uint32_t i = 0; i < size; ++i) { + CHKNRF(env, napi_create_double(env, data->data[i], &message), + "napi_create_double"); + CHKNRF(env, napi_set_named_property(env, result[1], sensorAttributes[i].c_str(), message), + "napi_set_named_property"); + message = nullptr; + } + CHKNRF(env, napi_create_int64(env, data->timestamp, &message), + "napi_create_int64"); + CHKNRF(env, napi_set_named_property(env, result[1], "timestamp", message), "napi_set_named_property"); + message = nullptr; + CHKNRF(env, napi_create_int32(env, data->sensorAccuracy, &message), + "napi_create_int32"); + CHKNRF(env, napi_set_named_property(env, result[1], "accuracy", message), "napi_set_named_property"); + return true; +} + bool ConvertToGeomagneticData(const napi_env &env, sptr asyncCallbackInfo, napi_value result[2]) { CALL_LOG_ENTER; @@ -618,6 +658,58 @@ void EmitUvEventLoop(sptr asyncCallbackInfo) } } +void EmitOnUvEventLoop(sptr asyncCallbackInfo, std::shared_ptr cb) +{ + CHKPV(asyncCallbackInfo); + CHKPV(cb); + asyncCallbackInfo->IncStrongRef(nullptr); + auto event = asyncCallbackInfo.GetRefPtr(); + auto task = [event, cb]() { + sptr asyncCallbackInfo(static_cast(event)); + /** + * After the asynchronous task is created, the asyncCallbackInfo reference count is reduced + * to 0 destruction, so you need to add 1 to the asyncCallbackInfo reference count when the + * asynchronous task is created, and subtract 1 from the reference count after the naked + * pointer is converted to a pointer when the asynchronous task is executed, the reference + * count of the smart pointer is guaranteed to be 1. + */ + asyncCallbackInfo->DecStrongRef(nullptr); + napi_handle_scope scope = nullptr; + napi_open_handle_scope(asyncCallbackInfo->env, &scope); + if (scope == nullptr) { + SEN_HILOGE("napi_handle_scope is nullptr"); + ReleaseCallback(asyncCallbackInfo); + return; + } + napi_env env = asyncCallbackInfo->env; + napi_value callback = nullptr; + if (napi_get_reference_value(env, asyncCallbackInfo->callback[0], &callback) != napi_ok) { + SEN_HILOGE("napi_get_reference_value fail"); + napi_throw_error(env, nullptr, "napi_get_reference_value fail"); + ReleaseCallback(asyncCallbackInfo); + napi_close_handle_scope(asyncCallbackInfo->env, scope); + return; + } + napi_value callResult = nullptr; + napi_value result[2] = {0}; + ConvertOnSensorData(env, asyncCallbackInfo, result, cb); + if (napi_call_function(env, nullptr, callback, 1, &result[1], &callResult) != napi_ok) { + SEN_HILOGE("napi_call_function callback fail"); + napi_throw_error(env, nullptr, "napi_call_function callback fail"); + ReleaseCallback(asyncCallbackInfo); + napi_close_handle_scope(asyncCallbackInfo->env, scope); + return; + } + ReleaseCallback(asyncCallbackInfo); + napi_close_handle_scope(asyncCallbackInfo->env, scope); + }; + auto ret = napi_send_event(asyncCallbackInfo->env, task, napi_eprio_immediate); + if (ret != napi_ok) { + SEN_HILOGE("Failed to SendEvent, ret:%{public}d", ret); + asyncCallbackInfo->DecStrongRef(nullptr); + } +} + void EmitPromiseWork(sptr asyncCallbackInfo) { CALL_LOG_ENTER;