From 4a29165609f8fe434f3b3de554c0ed7c977950e8 Mon Sep 17 00:00:00 2001 From: wuzhihuitmac Date: Wed, 18 Dec 2024 15:17:54 +0800 Subject: [PATCH] Motor time-consuming tasks into asynchronous threads Signed-off-by: wuzhihuitmac Change-Id: Id38bf5d8cb645d93c2328db4d44d37c9476cfae1 --- .../vibrator/include/vibrator_napi_utils.h | 32 ++++ .../js/napi/vibrator/src/vibrator_js.cpp | 80 ++++---- .../napi/vibrator/src/vibrator_napi_utils.cpp | 173 +++++++++++------- .../inner_api/vibrator/vibrator_agent.h | 4 +- 4 files changed, 186 insertions(+), 103 deletions(-) diff --git a/frameworks/js/napi/vibrator/include/vibrator_napi_utils.h b/frameworks/js/napi/vibrator/include/vibrator_napi_utils.h index 87a6191..9842013 100644 --- a/frameworks/js/napi/vibrator/include/vibrator_napi_utils.h +++ b/frameworks/js/napi/vibrator/include/vibrator_napi_utils.h @@ -39,6 +39,30 @@ enum CallbackType { IS_SUPPORT_EFFECT_CALLBACK, }; +enum class VibrateType { + CANCEL, + IS_SUPPORT_EFFECT_CALLBACK, + START_VIBRATE, + START_VIBRATE_TIME, + STOP_VIBRATOR, + VIBRATE_EFFECT_ID, + SYSTEM_VIBRATE_CALLBACK, +}; + +struct VibrateInfo { + std::string type; + std::string usage; + bool systemUsage; + int32_t duration = 0; + std::string effectId; + int32_t count = 0; + int32_t fd = -1; + int64_t offset = 0; + int64_t length = -1; + int32_t intensity = 0; + VibratorPattern vibratorPattern; +}; + class AsyncCallbackInfo : public RefBase { public: struct AsyncCallbackError { @@ -54,7 +78,12 @@ public: napi_ref callback[CALLBACK_NUM] = {0}; AsyncCallbackError error; CallbackType callbackType = COMMON_CALLBACK; + VibrateType vibrateType; bool isSupportEffect {false}; + VibrateInfo info; + std::string effectId; + std::string mode; + int32_t duration {0}; AsyncCallbackInfo(napi_env env) : env(env) {} ~AsyncCallbackInfo(); }; @@ -81,6 +110,9 @@ bool ConstructCommonResult(const napi_env &env, sptr asyncCal int32_t length); bool ConstructIsSupportEffectResult(const napi_env &env, sptr asyncCallbackInfo, napi_value result[], int32_t length); +void ExecuteAsyncWork(napi_env env, void *data); +void CompleteCallback(napi_env env, napi_status status, void *data); +void CompletePromise(napi_env env, napi_status status, void *data); void EmitAsyncCallbackWork(sptr async_callback_info); void EmitPromiseWork(sptr asyncCallbackInfo); } // namespace Sensors diff --git a/frameworks/js/napi/vibrator/src/vibrator_js.cpp b/frameworks/js/napi/vibrator/src/vibrator_js.cpp index 7524282..456db05 100644 --- a/frameworks/js/napi/vibrator/src/vibrator_js.cpp +++ b/frameworks/js/napi/vibrator/src/vibrator_js.cpp @@ -70,20 +70,6 @@ static std::map g_usageType = { static std::set g_allowedTypes = {"time", "preset", "file", "pattern"}; -struct VibrateInfo { - std::string type; - std::string usage; - bool systemUsage; - int32_t duration = 0; - std::string effectId; - int32_t count = 0; - int32_t fd = -1; - int64_t offset = 0; - int64_t length = -1; - int32_t intensity = 0; - VibratorPattern vibratorPattern; -}; - static napi_value EmitAsyncWork(napi_value param, sptr info) { CHKPP(info); @@ -116,7 +102,8 @@ static napi_value VibrateTime(napi_env env, napi_value args[], size_t argc) NAPI_ASSERT(env, GetInt32Value(env, args[0], duration), "Get int number fail"); sptr asyncCallbackInfo = new (std::nothrow) AsyncCallbackInfo(env); CHKPP(asyncCallbackInfo); - asyncCallbackInfo->error.code = StartVibratorOnce(duration); + asyncCallbackInfo->vibrateType = VibrateType::START_VIBRATE_TIME; + asyncCallbackInfo->duration = duration; if (argc >= PARAMETER_TWO && IsMatchType(env, args[1], napi_function)) { return EmitAsyncWork(args[1], asyncCallbackInfo); } @@ -130,7 +117,8 @@ static napi_value VibrateEffectId(napi_env env, napi_value args[], size_t argc) NAPI_ASSERT(env, GetStringValue(env, args[0], effectId), "Wrong argument type. String or function expected"); sptr asyncCallbackInfo = new (std::nothrow) AsyncCallbackInfo(env); CHKPP(asyncCallbackInfo); - asyncCallbackInfo->error.code = StartVibrator(effectId.c_str()); + asyncCallbackInfo->effectId = effectId; + asyncCallbackInfo->vibrateType = VibrateType::VIBRATE_EFFECT_ID; if (argc >= PARAMETER_TWO && IsMatchType(env, args[1], napi_function)) { return EmitAsyncWork(args[1], asyncCallbackInfo); } @@ -180,16 +168,14 @@ static napi_value VibrateMode(napi_env env, napi_value args[], size_t argc) sptr asyncCallbackInfo = new (std::nothrow) AsyncCallbackInfo(env); CHKPP(asyncCallbackInfo); asyncCallbackInfo->callbackType = SYSTEM_VIBRATE_CALLBACK; + asyncCallbackInfo->vibrateType = VibrateType::SYSTEM_VIBRATE_CALLBACK; string mode = "long"; if (!GetCallbackInfo(env, args, asyncCallbackInfo, mode)) { MISC_HILOGE("Get callback info fail"); return nullptr; } int32_t duration = ((mode == "long") ? VIBRATE_LONG_DURATION : VIBRATE_SHORT_DURATION); - asyncCallbackInfo->error.code = StartVibratorOnce(duration); - if (asyncCallbackInfo->error.code != SUCCESS) { - asyncCallbackInfo->error.message = "Vibrator vibrate fail"; - } + asyncCallbackInfo->duration = duration; EmitAsyncCallbackWork(asyncCallbackInfo); return nullptr; } @@ -463,7 +449,7 @@ bool SetUsage(const std::string &usage, bool systemUsage) return SetUsage(g_usageType[usage], systemUsage); } -int32_t StartVibrate(const VibrateInfo &info) +int32_t CheckVibrateMsg(const VibrateInfo &info) { CALL_LOG_ENTER; if (!SetUsage(info.usage, info.systemUsage)) { @@ -479,30 +465,43 @@ int32_t StartVibrate(const VibrateInfo &info) MISC_HILOGE("SetLoopCount fail"); return PARAMETER_ERROR; } - return PlayPrimitiveEffect(info.effectId.c_str(), info.intensity); + return SUCCESS; } else if (info.type == "file") { - return PlayVibratorCustom(info.fd, info.offset, info.length); +#ifdef OHOS_BUILD_ENABLE_VIBRATOR_CUSTOM + MISC_HILOGD("Time delay measurement:start time"); + if (info.fd < 0 || info.offset < 0 || info.length <= 0) { + MISC_HILOGE("Input parameter invalid, fd:%{public}d, offset:%{public}lld, length:%{public}lld", + fd, static_cast(offset), static_cast(length)); + return PARAMETER_ERROR; + } + return SUCCESS; +#else + MISC_HILOGE("The device does not support this operation"); + return IS_NOT_SUPPORTED; +#endif // OHOS_BUILD_ENABLE_VIBRATOR_CUSTOM } else if (info.type == "pattern") { return PlayPattern(info.vibratorPattern); } - return StartVibratorOnce(info.duration); + if (info.duration <= 0) { + MISC_HILOGE("duration is invalid"); + return PARAMETER_ERROR; + } + return SUCCESS; } static napi_value VibrateEffect(napi_env env, napi_value args[], size_t argc) { - VibrateInfo info; - if (!ParseParameter(env, args, argc, info)) { + sptr asyncCallbackInfo = new (std::nothrow) AsyncCallbackInfo(env); + CHKPP(asyncCallbackInfo); + asyncCallbackInfo->vibrateType = VibrateType::START_VIBRATE; + if (!ParseParameter(env, args, argc, asyncCallbackInfo->info)) { ThrowErr(env, PARAMETER_ERROR, "parameter fail"); return nullptr; } - sptr asyncCallbackInfo = new (std::nothrow) AsyncCallbackInfo(env); - CHKPP(asyncCallbackInfo); - asyncCallbackInfo->error.code = StartVibrate(info); - - if (info.vibratorPattern.events != nullptr) { - CHKCP(ClearVibratorPattern(info.vibratorPattern), "ClearVibratorPattern fail"); + if (asyncCallbackInfo->info.vibratorPattern.events != nullptr) { + CHKCP(ClearVibratorPattern(asyncCallbackInfo->info.vibratorPattern), "ClearVibratorPattern fail"); } - if ((asyncCallbackInfo->error.code != SUCCESS) && (asyncCallbackInfo->error.code == PARAMETER_ERROR)) { + if (CheckVibrateMsg(asyncCallbackInfo->info) == PARAMETER_ERROR) { ThrowErr(env, PARAMETER_ERROR, "parameters invalid"); return nullptr; } @@ -565,7 +564,7 @@ static napi_value Cancel(napi_env env, napi_callback_info info) } sptr asyncCallbackInfo = new (std::nothrow) AsyncCallbackInfo(env); CHKPP(asyncCallbackInfo); - asyncCallbackInfo->error.code = Cancel(); + asyncCallbackInfo->vibrateType = VibrateType::CANCEL; if ((argc > 0) && (IsMatchType(env, args[0], napi_function))) { return EmitAsyncWork(args[0], asyncCallbackInfo); } @@ -588,13 +587,15 @@ static napi_value Stop(napi_env env, napi_callback_info info) ThrowErr(env, PARAMETER_ERROR, "Parameters invalid"); return nullptr; } - sptr asyncCallbackInfo = new (std::nothrow) AsyncCallbackInfo(env); - CHKPP(asyncCallbackInfo); - asyncCallbackInfo->error.code = StopVibrator(mode.c_str()); - if ((asyncCallbackInfo->error.code != SUCCESS) && (asyncCallbackInfo->error.code == PARAMETER_ERROR)) { + if (mode != "time" && mode != "preset") { + MISC_HILOGE("Input parameter invalid, mode is %{public}s", mode.c_str()); ThrowErr(env, PARAMETER_ERROR, "Parameters invalid"); return nullptr; } + sptr asyncCallbackInfo = new (std::nothrow) AsyncCallbackInfo(env); + CHKPP(asyncCallbackInfo); + asyncCallbackInfo->mode = mode; + asyncCallbackInfo->vibrateType = VibrateType::STOP_VIBRATOR; if (argc >= PARAMETER_TWO && IsMatchType(env, args[1], napi_function)) { return EmitAsyncWork(args[1], asyncCallbackInfo); } @@ -658,7 +659,8 @@ static napi_value IsSupportEffect(napi_env env, napi_callback_info info) sptr asyncCallbackInfo = new (std::nothrow) AsyncCallbackInfo(env); CHKPP(asyncCallbackInfo); asyncCallbackInfo->callbackType = IS_SUPPORT_EFFECT_CALLBACK; - asyncCallbackInfo->error.code = IsSupportEffect(effectId.c_str(), &asyncCallbackInfo->isSupportEffect); + asyncCallbackInfo->vibrateType = VibrateType::IS_SUPPORT_EFFECT_CALLBACK; + asyncCallbackInfo->effectId = effectId; if ((argc > 1) && (IsMatchType(env, args[1], napi_function))) { return EmitAsyncWork(args[1], asyncCallbackInfo); } diff --git a/frameworks/js/napi/vibrator/src/vibrator_napi_utils.cpp b/frameworks/js/napi/vibrator/src/vibrator_napi_utils.cpp index 6e3c122..55ea117 100644 --- a/frameworks/js/napi/vibrator/src/vibrator_napi_utils.cpp +++ b/frameworks/js/napi/vibrator/src/vibrator_napi_utils.cpp @@ -20,6 +20,7 @@ #include "securec.h" #include "miscdevice_log.h" +#include "vibrator_agent.h" #include "vibrator_napi_error.h" #undef LOG_TAG @@ -308,6 +309,80 @@ void EmitSystemCallback(const napi_env &env, sptr asyncCallba NAPI_CALL_RETURN_VOID(env, napi_call_function(env, nullptr, callback, 1, result, &callResult)); } +void ExecuteAsyncWork(napi_env env, void *data) +{ + CALL_LOG_ENTER; + sptr asyncCallbackInfo(static_cast(data)); + if (asyncCallbackInfo->vibrateType == VibrateType::START_VIBRATE) { + if (asyncCallbackInfo->info.type == "preset") { + asyncCallbackInfo->error.code = PlayPrimitiveEffect(asyncCallbackInfo->info.effectId.c_str(), + asyncCallbackInfo->info.intensity); + } else if (asyncCallbackInfo->info.type == "file") { + asyncCallbackInfo->error.code = PlayVibratorCustom(asyncCallbackInfo->info.fd, + asyncCallbackInfo->info.offset, asyncCallbackInfo->info.length); + } else { + asyncCallbackInfo->error.code = StartVibratorOnce(asyncCallbackInfo->info.duration); + } + } else if (asyncCallbackInfo->vibrateType == VibrateType::START_VIBRATE_TIME) { + asyncCallbackInfo->error.code = StartVibratorOnce(asyncCallbackInfo->duration); + } else if (asyncCallbackInfo->vibrateType == VibrateType::VIBRATE_EFFECT_ID) { + asyncCallbackInfo->error.code = StartVibrator(asyncCallbackInfo->effectId.c_str()); + } else if (asyncCallbackInfo->vibrateType == VibrateType::SYSTEM_VIBRATE_CALLBACK) { + asyncCallbackInfo->error.code = StartVibratorOnce(asyncCallbackInfo->duration); + if (asyncCallbackInfo->error.code != SUCCESS) { + asyncCallbackInfo->error.message = "Vibrator vibrate fail"; + } + } else if (asyncCallbackInfo->vibrateType == VibrateType::IS_SUPPORT_EFFECT_CALLBACK) { + asyncCallbackInfo->error.code = IsSupportEffect(asyncCallbackInfo->effectId.c_str(), + &asyncCallbackInfo->isSupportEffect); + } else if (asyncCallbackInfo->vibrateType == VibrateType::STOP_VIBRATOR) { + asyncCallbackInfo->error.code = StopVibrator(asyncCallbackInfo->mode.c_str()); + } else if (asyncCallbackInfo->vibrateType == VibrateType::CANCEL) { + asyncCallbackInfo->error.code = Cancel(); + } +} + +void CompleteCallback(napi_env env, napi_status status, void *data) +{ + CALL_LOG_ENTER; + sptr asyncCallbackInfo(static_cast(data)); + /** + * 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); + if (asyncCallbackInfo->vibrateType == VibrateType::SYSTEM_VIBRATE_CALLBACK) { + EmitSystemCallback(env, asyncCallbackInfo); + return; + } + if (asyncCallbackInfo->error.code != SUCCESS) { + if (asyncCallbackInfo->vibrateType == VibrateType::IS_SUPPORT_EFFECT_CALLBACK) { + MISC_HILOGE("IsSupportEffect failed"); + } else if (asyncCallbackInfo->vibrateType == VibrateType::STOP_VIBRATOR) { + MISC_HILOGE("Stop vibtate failed"); + } else if (asyncCallbackInfo->vibrateType == VibrateType::CANCEL) { + MISC_HILOGE("Cancel vibtate failed"); + } + MISC_HILOGE("Start vibrate failed"); + } + CHKPV(asyncCallbackInfo->callback[0]); + napi_value callback = nullptr; + napi_status ret = napi_get_reference_value(env, asyncCallbackInfo->callback[0], &callback); + CHKCV((ret == napi_ok), "napi_get_reference_value fail"); + napi_value result[RESULT_LENGTH] = { 0 }; + CHKCV((g_convertFuncList.find(asyncCallbackInfo->callbackType) != g_convertFuncList.end()), + "Callback type invalid in async work"); + bool state = g_convertFuncList[asyncCallbackInfo->callbackType](env, asyncCallbackInfo, result, + sizeof(result) / sizeof(napi_value)); + CHKCV(state, "Create napi data fail in async work"); + napi_value callResult = nullptr; + CHKCV((napi_call_function(env, nullptr, callback, 2, result, &callResult) == napi_ok), + "napi_call_function fail"); +} + void EmitAsyncCallbackWork(sptr asyncCallbackInfo) { CALL_LOG_ENTER; @@ -319,37 +394,8 @@ void EmitAsyncCallbackWork(sptr asyncCallbackInfo) CHKCV((ret == napi_ok), "napi_create_string_latin1 fail"); asyncCallbackInfo->IncStrongRef(nullptr); napi_status status = napi_create_async_work( - env, nullptr, resourceName, [](napi_env env, void *data) {}, - [](napi_env env, napi_status status, void *data) { - CALL_LOG_ENTER; - sptr asyncCallbackInfo(static_cast(data)); - /** - * 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); - if (asyncCallbackInfo->callbackType == SYSTEM_VIBRATE_CALLBACK) { - EmitSystemCallback(env, asyncCallbackInfo); - return; - } - CHKPV(asyncCallbackInfo->callback[0]); - napi_value callback = nullptr; - napi_status ret = napi_get_reference_value(env, asyncCallbackInfo->callback[0], &callback); - CHKCV((ret == napi_ok), "napi_get_reference_value fail"); - napi_value result[RESULT_LENGTH] = { 0 }; - CHKCV((g_convertFuncList.find(asyncCallbackInfo->callbackType) != g_convertFuncList.end()), - "Callback type invalid in async work"); - bool state = g_convertFuncList[asyncCallbackInfo->callbackType](env, asyncCallbackInfo, result, - sizeof(result) / sizeof(napi_value)); - CHKCV(state, "Create napi data fail in async work"); - napi_value callResult = nullptr; - CHKCV((napi_call_function(env, nullptr, callback, 2, result, &callResult) == napi_ok), - "napi_call_function fail"); - }, - asyncCallbackInfo.GetRefPtr(), &asyncCallbackInfo->asyncWork); + env, nullptr, resourceName, ExecuteAsyncWork, CompleteCallback, asyncCallbackInfo.GetRefPtr(), + &asyncCallbackInfo->asyncWork); if (status != napi_ok || napi_queue_async_work_with_qos( asyncCallbackInfo->env, asyncCallbackInfo->asyncWork, napi_qos_default) != napi_ok) { @@ -358,6 +404,38 @@ void EmitAsyncCallbackWork(sptr asyncCallbackInfo) } } +void CompletePromise(napi_env env, napi_status status, void *data) +{ + CALL_LOG_ENTER; + sptr asyncCallbackInfo(static_cast(data)); + /** + * 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); + CHKPV(asyncCallbackInfo->deferred); + if (asyncCallbackInfo->vibrateType == VibrateType::SYSTEM_VIBRATE_CALLBACK) { + EmitSystemCallback(env, asyncCallbackInfo); + return; + } + napi_value result[RESULT_LENGTH] = { 0 }; + CHKCV((g_convertFuncList.find(asyncCallbackInfo->callbackType) != g_convertFuncList.end()), + "Callback type invalid in promise"); + bool ret = g_convertFuncList[asyncCallbackInfo->callbackType](env, asyncCallbackInfo, result, + sizeof(result) / sizeof(napi_value)); + CHKCV(ret, "Callback type invalid in promise"); + if (asyncCallbackInfo->error.code != SUCCESS) { + CHKCV((napi_reject_deferred(env, asyncCallbackInfo->deferred, result[0]) == napi_ok), + "napi_reject_deferred fail"); + } else { + CHKCV((napi_resolve_deferred(env, asyncCallbackInfo->deferred, result[1]) == napi_ok), + "napi_resolve_deferred fail"); + } +} + void EmitPromiseWork(sptr asyncCallbackInfo) { CALL_LOG_ENTER; @@ -370,37 +448,8 @@ void EmitPromiseWork(sptr asyncCallbackInfo) // Make the reference count of asyncCallbackInfo add 1, and the function exits the non-destructor asyncCallbackInfo->IncStrongRef(nullptr); napi_status status = napi_create_async_work( - env, nullptr, resourceName, [](napi_env env, void *data) {}, - [](napi_env env, napi_status status, void *data) { - CALL_LOG_ENTER; - sptr asyncCallbackInfo(static_cast(data)); - /** - * 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); - CHKPV(asyncCallbackInfo->deferred); - if (asyncCallbackInfo->callbackType == SYSTEM_VIBRATE_CALLBACK) { - EmitSystemCallback(env, asyncCallbackInfo); - return; - } - napi_value result[RESULT_LENGTH] = { 0 }; - CHKCV((g_convertFuncList.find(asyncCallbackInfo->callbackType) != g_convertFuncList.end()), - "Callback type invalid in promise"); - bool ret = g_convertFuncList[asyncCallbackInfo->callbackType](env, asyncCallbackInfo, result, - sizeof(result) / sizeof(napi_value)); - CHKCV(ret, "Callback type invalid in promise"); - if (asyncCallbackInfo->error.code != SUCCESS) { - CHKCV((napi_reject_deferred(env, asyncCallbackInfo->deferred, result[0]) == napi_ok), - "napi_reject_deferred fail"); - } else { - CHKCV((napi_resolve_deferred(env, asyncCallbackInfo->deferred, result[1]) == napi_ok), - "napi_resolve_deferred fail"); - } - }, asyncCallbackInfo.GetRefPtr(), &asyncCallbackInfo->asyncWork); + env, nullptr, resourceName, ExecuteAsyncWork, CompletePromise, + asyncCallbackInfo.GetRefPtr(), &asyncCallbackInfo->asyncWork); if (status != napi_ok || napi_queue_async_work_with_qos( asyncCallbackInfo->env, asyncCallbackInfo->asyncWork, napi_qos_default) != napi_ok) { diff --git a/interfaces/inner_api/vibrator/vibrator_agent.h b/interfaces/inner_api/vibrator/vibrator_agent.h index eb5b131..8948b38 100644 --- a/interfaces/inner_api/vibrator/vibrator_agent.h +++ b/interfaces/inner_api/vibrator/vibrator_agent.h @@ -43,14 +43,14 @@ namespace Sensors { * * @since 6 */ -const char *VIBRATOR_STOP_MODE_TIME = "time"; +static const char *VIBRATOR_STOP_MODE_TIME = "time"; /** * @brief Indicates the mode of stopping a preset vibration effect. * * @since 6 */ -const char *VIBRATOR_STOP_MODE_PRESET = "preset"; +static const char *VIBRATOR_STOP_MODE_PRESET = "preset"; /** * @brief Controls this vibrator to perform a vibration with a preset vibration effect. -- Gitee