From c8f0b9a9400bf07f48acdd639739429a629dc366 Mon Sep 17 00:00:00 2001 From: shenpeixing Date: Tue, 8 Jul 2025 18:17:57 +0800 Subject: [PATCH] =?UTF-8?q?arkts1.2=E4=BB=A3=E7=A0=81=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: shenpeixing --- bundle.json | 7 +- frameworks/{js/ani => ets/taihe}/BUILD.gn | 79 +- .../ets/taihe/author/src/ani_constructor.cpp | 30 + .../taihe/author/src/ohos.vibrator.impl.cpp | 455 ++++++++++ frameworks/ets/taihe/idl/ohos.vibrator.taihe | 703 +++++++++++++++ .../js/ani/vibrator/ets/@ohos.vibrator.ets | 156 ---- .../js/ani/vibrator/include/ani_utils.h | 564 ------------ .../js/ani/vibrator/src/vibrator_ani.cpp | 816 ------------------ 8 files changed, 1250 insertions(+), 1560 deletions(-) rename frameworks/{js/ani => ets/taihe}/BUILD.gn (43%) create mode 100644 frameworks/ets/taihe/author/src/ani_constructor.cpp create mode 100644 frameworks/ets/taihe/author/src/ohos.vibrator.impl.cpp create mode 100644 frameworks/ets/taihe/idl/ohos.vibrator.taihe delete mode 100644 frameworks/js/ani/vibrator/ets/@ohos.vibrator.ets delete mode 100644 frameworks/js/ani/vibrator/include/ani_utils.h delete mode 100644 frameworks/js/ani/vibrator/src/vibrator_ani.cpp diff --git a/bundle.json b/bundle.json index f1ff2da..2782b19 100644 --- a/bundle.json +++ b/bundle.json @@ -56,12 +56,12 @@ "base_group": [], "fwk_group": [ "//base/sensors/miscdevice/frameworks/js/napi:vibrator_js_target", - "//base/sensors/miscdevice/frameworks/js/ani:vibrator_ani_target", "//base/sensors/miscdevice/frameworks/cj:vibrator_cj_target", "//base/sensors/miscdevice/frameworks/native/vibrator:vibrator_target", "//base/sensors/miscdevice/frameworks/native/light:light_target", "//base/sensors/miscdevice/utils:miscdevice_utils_target", - "//base/sensors/miscdevice/frameworks/capi:ohvibrator" + "//base/sensors/miscdevice/frameworks/capi:ohvibrator", + "//base/sensors/miscdevice/frameworks/ets/taihe:vibrator_taihe" ], "service_group": [ "//base/sensors/miscdevice/services/miscdevice_service:miscdevice_service_target", @@ -69,6 +69,9 @@ ] }, "inner_kits": [ + { + "name": "//base/sensors/miscdevice/frameworks/ets/taihe:copy_taihe" + }, { "name": "//base/sensors/miscdevice/frameworks/native/vibrator:vibrator_interface_native", "header": { diff --git a/frameworks/js/ani/BUILD.gn b/frameworks/ets/taihe/BUILD.gn similarity index 43% rename from frameworks/js/ani/BUILD.gn rename to frameworks/ets/taihe/BUILD.gn index 9767407..ea361cb 100644 --- a/frameworks/js/ani/BUILD.gn +++ b/frameworks/ets/taihe/BUILD.gn @@ -12,56 +12,91 @@ # limitations under the License. import("//build/config/components/ets_frontend/ets2abc_config.gni") -import("//build/ohos.gni") import("./../../../miscdevice.gni") +import("//build/ohos.gni") +import("//build/ohos/taihe_idl/taihe.gni") + +subsystem_name = "sensors" +part_name = "miscdevice" +taihe_generated_file_path = "$taihe_file_path/out/$subsystem_name/$part_name" + +copy_taihe_idl("copy_taihe") { + sources = [ + "idl/ohos.vibrator.taihe", + ] + + external_deps = [] +} -ohos_shared_library("vibrator_ani") { +ohos_taihe("run_taihe") { + taihe_generated_file_path = "$taihe_generated_file_path" + deps = [ ":copy_taihe" ] + outputs = [ + "$taihe_generated_file_path/src/ohos.vibrator.abi.c", + "$taihe_generated_file_path/src/ohos.vibrator.ani.cpp", + ] +} + +taihe_shared_library("vibrator_taihe_native") { + branch_protector_ret = "pac_ret" sanitize = { - ubsan = true boundary_sanitize = true cfi = true cfi_cross_dso = true debug = false + integer_overflow = true + ubsan = true } - sources = [ "$SUBSYSTEM_DIR/frameworks/js/ani/vibrator/src/vibrator_ani.cpp" ] + taihe_generated_file_path = "$taihe_generated_file_path" + subsystem_name = "$subsystem_name" + part_name = "$part_name" include_dirs = [ - "$SUBSYSTEM_DIR/frameworks/js/ani/vibrator/include", + "$SUBSYSTEM_DIR/interfaces/inner_api/vibrator", + "$SUBSYSTEM_DIR/frameworks/js/napi/vibrator/include", "$SUBSYSTEM_DIR/utils/common/include", ] + defines = [ + "APP_LOG_TAG = \"VibratorImpl\"", + "LOG_DOMAIN = 0xD002700", + ] + sources = get_target_outputs(":run_taihe") + sources += [ + "author/src/ani_constructor.cpp", + "author/src/ohos.vibrator.impl.cpp", + ] deps = [ + ":run_taihe", "$SUBSYSTEM_DIR/frameworks/native/vibrator:vibrator_interface_native", "$SUBSYSTEM_DIR/utils/common:libmiscdevice_utils", ] external_deps = [ + "c_utils:utils", "hilog:libhilog", - "napi:ace_napi", - "runtime_core:ani", ] - subsystem_name = "sensors" - part_name = "miscdevice" - output_extension = "so" } generate_static_abc("vibrator_abc") { - base_url = "./vibrator/ets" - files = [ "./vibrator/ets/@ohos.vibrator.ets" ] - dst_file = "$target_out_dir/vibrator.abc" - out_puts = [ "$target_out_dir/vibrator.abc" ] + base_url = "$taihe_generated_file_path" + files = [ + "$taihe_generated_file_path/@ohos.base.ets", + "$taihe_generated_file_path/@ohos.vibrator.ets", + ] is_boot_abc = "True" - device_dst_file = "/system/framework/vibrator.abc" + device_dst_file = "/system/framework/vibrator_abc.abc" + dependencies = [ ":run_taihe" ] } -ohos_prebuilt_etc("vibrator_abc_etc") { - source = "$target_out_dir/vibrator.abc" +ohos_prebuilt_etc("vibrator_etc") { + source = "$target_out_dir/vibrator_abc.abc" module_install_dir = "framework" - subsystem_name = "sensors" - part_name = "miscdevice" + part_name = "$part_name" + subsystem_name = "$subsystem_name" deps = [ ":vibrator_abc" ] } -group("vibrator_ani_target") { +group("vibrator_taihe") { deps = [ - ":vibrator_abc_etc", - ":vibrator_ani", + ":vibrator_etc", + ":vibrator_taihe_native", ] } diff --git a/frameworks/ets/taihe/author/src/ani_constructor.cpp b/frameworks/ets/taihe/author/src/ani_constructor.cpp new file mode 100644 index 0000000..730b4ba --- /dev/null +++ b/frameworks/ets/taihe/author/src/ani_constructor.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2025 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 "taihe/runtime.hpp" +#include "ohos.vibrator.ani.hpp" +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + ani_env *env; + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + return ANI_ERROR; + } + if (ANI_OK != ohos::vibrator::ANIRegister(env)) { + std::cerr << "Error from ohos::vibrator::ANIRegister" << std::endl; + return ANI_ERROR; + } + *result = ANI_VERSION_1; + return ANI_OK; +} \ No newline at end of file diff --git a/frameworks/ets/taihe/author/src/ohos.vibrator.impl.cpp b/frameworks/ets/taihe/author/src/ohos.vibrator.impl.cpp new file mode 100644 index 0000000..ebb2d56 --- /dev/null +++ b/frameworks/ets/taihe/author/src/ohos.vibrator.impl.cpp @@ -0,0 +1,455 @@ +/* + * Copyright (c) 2025 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 +#include + +#include "ohos.vibrator.proj.hpp" +#include "ohos.vibrator.impl.hpp" +#include "stdexcept" +#include "taihe/runtime.hpp" + +#include "file_utils.h" +#include "miscdevice_log.h" +#include "sensors_errors.h" +#include "vibrator_agent.h" + +#undef LOG_TAG +#define LOG_TAG "VibratorImpl" + +namespace { +using namespace OHOS::Sensors; + +constexpr int32_t INTENSITY_ADJUST_MAX = 100; +constexpr int32_t EVENT_START_TIME_MAX = 1800000; +constexpr int32_t EVENT_NUM_MAX = 128; +constexpr int32_t INTENSITY_MIN = 0; +constexpr int32_t INTENSITY_MAX = 100; +constexpr int32_t FREQUENCY_MIN = 0; +constexpr int32_t FREQUENCY_MAX = 100; +constexpr int32_t CURVE_POINT_INTENSITY_MAX = 100; +constexpr int32_t CURVE_POINT_NUM_MIN = 4; +constexpr int32_t CURVE_POINT_NUM_MAX = 16; +constexpr int32_t CURVE_FREQUENCY_MIN = -100; +constexpr int32_t CURVE_FREQUENCY_MAX = 100; +constexpr int32_t CONTINUOUS_DURATION_MAX = 5000; +constexpr int32_t EVENT_INDEX_MAX = 2; + +static std::map g_usageType = { + {"unknown", USAGE_UNKNOWN}, + {"alarm", USAGE_ALARM}, + {"ring", USAGE_RING}, + {"notification", USAGE_NOTIFICATION}, + {"communication", USAGE_COMMUNICATION}, + {"touch", USAGE_TOUCH}, + {"media", USAGE_MEDIA}, + {"physicalFeedback", USAGE_PHYSICAL_FEEDBACK}, + {"simulateReality", USAGE_SIMULATE_REALITY}, +}; + +static std::set g_allowedTypes = {"time", "preset", "file", "pattern"}; + +struct VibrateInfo { + std::string type; + std::string usage; + bool systemUsage {false}; + 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; +}; + +void stopVibrationByModeSync(::ohos::vibrator::VibratorStopMode stopMode) +{ + CALL_LOG_ENTER; + StopVibrator(stopMode.get_value()); +} + +static bool ParseVibratorCurvePoint(::taihe::array<::ohos::vibrator::VibratorCurvePoint> pointsArray, uint32_t index, + VibratorCurvePoint &point) +{ + CALL_LOG_ENTER; + point.time = pointsArray[index].time; + point.intensity = pointsArray[index].intensity.has_value() ? pointsArray[index].intensity.value() : 0; + point.frequency = pointsArray[index].frequency.has_value() ? pointsArray[index].frequency.value() : 0; + return true; +} + +static bool ParseVibratorCurvePointArray(::taihe::array<::ohos::vibrator::VibratorCurvePoint> pointsArray, + uint32_t pointsLength, VibratorEvent &event) +{ + CALL_LOG_ENTER; + if (pointsLength <= 0 || pointsLength > CURVE_POINT_NUM_MAX) { + MISC_HILOGE("pointsLength should not be less than or equal to 0 or greater than CURVE_POINT_NUM_MAX"); + return false; + } + VibratorCurvePoint *points = + static_cast(malloc(sizeof(VibratorCurvePoint) * pointsLength)); + if (points == nullptr) { + MISC_HILOGE("points is nullptr"); + return false; + } + for (uint32_t i = 0; i < pointsLength; ++i) { + if (!ParseVibratorCurvePoint(pointsArray, i, points[i])) { + MISC_HILOGE("ParseVibratorCurvePoint failed"); + free(points); + points = nullptr; + return false; + } + } + event.points = points; + return true; +} + +static bool ParseVibrateEvent(::taihe::array<::ohos::vibrator::VibratorEvent> eventArray, int32_t index, + VibratorEvent &event) +{ + CALL_LOG_ENTER; + ::ohos::vibrator::VibratorEvent vibratorEvent = eventArray[index]; + event.type = static_cast(static_cast(vibratorEvent.eventType)); + event.time = vibratorEvent.time; + event.duration = vibratorEvent.duration.has_value() ? vibratorEvent.duration.value() : 0; + event.intensity = vibratorEvent.intensity.has_value() ? vibratorEvent.intensity.value() : 0; + event.frequency = vibratorEvent.frequency.has_value() ? vibratorEvent.frequency.value() : 0; + event.index = vibratorEvent.index.has_value() ? vibratorEvent.index.value() : 0; + if (!vibratorEvent.points.has_value()) { + MISC_HILOGI("has no points"); + return true; + } + ::taihe::array<::ohos::vibrator::VibratorCurvePoint> points = vibratorEvent.points.value(); + std::size_t size = points.size(); + event.pointNum = static_cast(size); + if (size <= 0) { + MISC_HILOGI("has zero points"); + return true; + } + if (!ParseVibratorCurvePointArray(points, event.pointNum, event)) { + MISC_HILOGE("ParseVibratorCurvePointArray failed"); + return false; + } + return true; +} + +static bool ParseVibratorPattern(::ohos::vibrator::VibratorPattern pattern, VibrateInfo &vibrateInfo) +{ + CALL_LOG_ENTER; + vibrateInfo.vibratorPattern.time = pattern.time; + vibrateInfo.vibratorPattern.eventNum = static_cast(pattern.events.size()); + if (vibrateInfo.vibratorPattern.eventNum <= 0 || vibrateInfo.vibratorPattern.eventNum > EVENT_NUM_MAX) { + MISC_HILOGE("length should not be less than or equal to 0 or greater than EVENT_NUM_MAX"); + return false; + } + VibratorEvent *events = + static_cast(malloc(sizeof(VibratorEvent) * vibrateInfo.vibratorPattern.eventNum)); + if (events == nullptr) { + MISC_HILOGE("Events is nullptr"); + return false; + } + for (int32_t j = 0; j < vibrateInfo.vibratorPattern.eventNum; ++j) { + new (&events[j]) VibratorEvent(); + if (!ParseVibrateEvent(pattern.events, j, events[j])) { + MISC_HILOGE("ParseVibrateEvent failed"); + free(events); + events = nullptr; + return false; + } + } + vibrateInfo.vibratorPattern.events = events; + return true; +} + +static void PrintVibratorPattern(::ohos::vibrator::VibratorPattern &vibratorPattern) +{ + CALL_LOG_ENTER; + if (vibratorPattern.events.empty()) { + MISC_HILOGE("Events is empty"); + return; + } + MISC_HILOGD("PrintVibratorPattern, time:%{public}d, eventNum:%{public}u", + vibratorPattern.time, vibratorPattern.events.size()); + for (int32_t i = 0; i < static_cast(vibratorPattern.events.size()); ++i) { + MISC_HILOGD("PrintVibratorPattern, type:%{public}d, time:%{public}d, duration:%{public}d, \ + intensity:%{public}d, frequency:%{public}d, index:%{public}d, pointNum:%{public}u", + static_cast(vibratorPattern.events[i].eventType), vibratorPattern.events[i].time, + vibratorPattern.events[i].duration.value(), vibratorPattern.events[i].intensity.value(), + vibratorPattern.events[i].frequency.value(), vibratorPattern.events[i].index.value(), + vibratorPattern.events[i].points.value().size()); + if ((!vibratorPattern.events[i].points.has_value()) || vibratorPattern.events[i].points.value().size() <= 0) { + MISC_HILOGE("points is empty"); + return; + } + ::taihe::array<::ohos::vibrator::VibratorCurvePoint> point = vibratorPattern.events[i].points.value(); + for (int32_t j = 0; j < static_cast(vibratorPattern.events[i].points.value().size()); ++j) { + MISC_HILOGD("PrintVibratorPattern, time:%{public}d, intensity:%{public}d, frequency:%{public}d", + point[j].time, point[j].intensity.value(), point[j].frequency.value()); + } + } +} + +static bool CheckVibratorCurvePoint(const ::ohos::vibrator::VibratorEvent &event) +{ + CALL_LOG_ENTER; + if ((!event.points.has_value()) || (event.points.value().size() < CURVE_POINT_NUM_MIN) || + (event.points.value().size() > CURVE_POINT_NUM_MAX)) { + MISC_HILOGE("The points size is out of range, pointNum:%{public}u", event.points.value().size()); + return false; + } + for (int32_t j = 0; j < static_cast(event.points.value().size()); ++j) { + if ((event.points.value()[j].time < 0) || (event.points.value()[j].time > event.duration.value())) { + MISC_HILOGE("time in points is out of range, time:%{public}d", event.points.value()[j].time); + return false; + } + if ((event.points.value()[j].intensity.value() < 0) || + (event.points.value()[j].intensity.value() > CURVE_POINT_INTENSITY_MAX)) { + MISC_HILOGE("intensity in points is out of range, intensity:%{public}d", + event.points.value()[j].intensity.value()); + return false; + } + if ((event.points.value()[j].frequency.value() < CURVE_FREQUENCY_MIN) || + (event.points.value()[j].frequency.value() > CURVE_FREQUENCY_MAX)) { + MISC_HILOGE("frequency in points is out of range, frequency:%{public}d", + event.points.value()[j].frequency.value()); + return false; + } + } + return true; +} + +static bool CheckVibratorEvent(const ::ohos::vibrator::VibratorEvent &event) +{ + CALL_LOG_ENTER; + if ((event.time < 0) || (event.time > EVENT_START_TIME_MAX)) { + MISC_HILOGE("The event time is out of range, time:%{public}d", event.time); + return false; + } + if ((!event.frequency.has_value()) || (event.frequency.value() < FREQUENCY_MIN) || + (event.frequency.value() > FREQUENCY_MAX)) { + MISC_HILOGE("The event frequency is out of range, frequency:%{public}d", event.frequency.value()); + return false; + } + if ((!event.intensity.has_value()) || (event.intensity.value() < INTENSITY_MIN) || + (event.intensity.value() > INTENSITY_MAX)) { + MISC_HILOGE("The event intensity is out of range, intensity:%{public}d", event.intensity.value()); + return false; + } + if ((!event.duration.has_value()) || (event.duration.value() <= 0) || + (event.duration.value() > CONTINUOUS_DURATION_MAX)) { + MISC_HILOGE("The event duration is out of range, duration:%{public}d", event.duration.value()); + return false; + } + if ((!event.index.has_value()) || (event.index.value() < 0) || (event.index.value() > EVENT_INDEX_MAX)) { + MISC_HILOGE("The event index is out of range, index:%{public}d", event.index.value()); + return false; + } + if ((event.eventType == VibratorEventType::EVENT_TYPE_CONTINUOUS) && (event.points.value().size() > 0)) { + if (!CheckVibratorCurvePoint(event)) { + MISC_HILOGE("CheckVibratorCurvePoint failed"); + return false; + } + } + return true; +} + +static bool CheckVibratorPatternParameter(::ohos::vibrator::VibratorPattern &vibratorPattern) +{ + CALL_LOG_ENTER; + if (vibratorPattern.events.empty()) { + MISC_HILOGE("Events is empty"); + return false; + } + if ((vibratorPattern.events.size() <= 0) || (vibratorPattern.events.size() > EVENT_NUM_MAX)) { + MISC_HILOGE("The event num is out of range, eventNum:%{public}u", vibratorPattern.events.size()); + return false; + } + for (int32_t i = 0; i < static_cast(vibratorPattern.events.size()); ++i) { + if (!CheckVibratorEvent(vibratorPattern.events[i])) { + MISC_HILOGE("CheckVibratorEvent failed"); + return false; + } + } + return true; +} + +bool ParseParameter(::ohos::vibrator::VibrateEffect const& effect, ::ohos::vibrator::VibrateAttribute const& attribute, + VibrateInfo &vibrateInfo) +{ + CALL_LOG_ENTER; + if (effect.holds_VibrateTime_type()) { + vibrateInfo.type = "time"; + ::ohos::vibrator::VibrateTime vibrateTime = effect.get_VibrateTime_type_ref(); + vibrateInfo.duration = vibrateTime.duration; + } else if (effect.holds_VibratePreset_type()) { + vibrateInfo.type = "preset"; + ::ohos::vibrator::VibratePreset vibratePreset = effect.get_VibratePreset_type_ref(); + vibrateInfo.effectId = vibratePreset.effectId; + vibrateInfo.count = vibratePreset.count.has_value() ? vibratePreset.count.value() : 1; + vibrateInfo.intensity = vibratePreset.intensity.has_value() ? vibratePreset.intensity.value() : + INTENSITY_ADJUST_MAX; + } else if (effect.holds_VibrateFromFile_type()) { + vibrateInfo.type = "file"; + ::ohos::vibrator::VibrateFromFile vibrateFromFile = effect.get_VibrateFromFile_type_ref(); + vibrateInfo.fd = vibrateFromFile.hapticFd.fd; + vibrateInfo.offset = vibrateFromFile.hapticFd.offset.has_value() ? vibrateFromFile.hapticFd.offset.value() : 0; + int64_t fdSize = GetFileSize(vibrateInfo.fd); + CHKCR((vibrateInfo.offset >= 0) && (vibrateInfo.offset <= fdSize), false, "The parameter of offset is invalid"); + vibrateInfo.length = vibrateFromFile.hapticFd.length.has_value() ? vibrateFromFile.hapticFd.length.value() : + fdSize - vibrateInfo.offset; + } else if (effect.holds_VibrateFromPattern_type()) { + vibrateInfo.type = "pattern"; + ::ohos::vibrator::VibrateFromPattern vibrateFromPattern = effect.get_VibrateFromPattern_type_ref(); + ParseVibratorPattern(vibrateFromPattern.pattern, vibrateInfo); + PrintVibratorPattern(vibrateFromPattern.pattern); + CHKCF(CheckVibratorPatternParameter(vibrateFromPattern.pattern), "CheckVibratorPatternParameter fail"); + } + vibrateInfo.usage = attribute.usage; + vibrateInfo.systemUsage = attribute.systemUsage.has_value() ? attribute.systemUsage.value() : false; + return true; +} + +bool SetUsageInner(const std::string &usage, bool systemUsage) +{ + CALL_LOG_ENTER; + if (auto iter = g_usageType.find(usage); iter == g_usageType.end()) { + taihe::set_business_error(PARAMETER_ERROR, "Wrong usage type " + usage); + return false; + } + return SetUsage(g_usageType[usage], systemUsage); +} + +int32_t CheckParameters(const VibrateInfo &info) +{ + CALL_LOG_ENTER; + if (!SetUsageInner(info.usage, info.systemUsage)) { + MISC_HILOGE("SetUsage fail"); + taihe::set_business_error(PARAMETER_ERROR, "Parameters invalid"); + return PARAMETER_ERROR; + } + if (g_allowedTypes.find(info.type) == g_allowedTypes.end()) { + MISC_HILOGE("Invalid vibrate type, type:%{public}s", info.type.c_str()); + taihe::set_business_error(PARAMETER_ERROR, "Parameters invalid"); + return PARAMETER_ERROR; + } + return OHOS::ERR_OK; +} + +int32_t StartVibrate(const VibrateInfo &info) +{ + CALL_LOG_ENTER; + if (CheckParameters(info) != OHOS::ERR_OK) { + taihe::set_business_error(PARAMETER_ERROR, "Parameters invalid"); + MISC_HILOGE("CheckParameters fail"); + return PARAMETER_ERROR; + } + if (info.type == "file") { + return PlayVibratorCustom(info.fd, info.offset, info.length); + } else if (info.type == "pattern") { + return PlayPattern(info.vibratorPattern); + } + return StartVibratorOnce(info.duration); +} + +bool ClearVibratorPattern(VibratorPattern &vibratorPattern) +{ + CALL_LOG_ENTER; + int32_t eventSize = vibratorPattern.eventNum; + if ((eventSize <= 0) || (vibratorPattern.events == nullptr)) { + MISC_HILOGW("events is not need to free, eventSize:%{public}d", eventSize); + return false; + } + auto events = vibratorPattern.events; + for (int32_t j = 0; j < eventSize; ++j) { + if (events[j].points != nullptr) { + free(events[j].points); + events[j].points = nullptr; + } + } + free(events); + events = nullptr; + return true; +} + +void startVibrationSync(::ohos::vibrator::VibrateEffect const& effect, + ::ohos::vibrator::VibrateAttribute const& attribute) +{ + CALL_LOG_ENTER; + VibrateInfo vibrateInfo = {}; + if (!ParseParameter(effect, attribute, vibrateInfo)) { + MISC_HILOGE("ParseParameter fail"); + taihe::set_business_error(PARAMETER_ERROR, "ParseParameter fail"); + return; + } + if (vibrateInfo.type == "preset") { + if (!SetLoopCount(vibrateInfo.count) || CheckParameters(vibrateInfo) != OHOS::ERR_OK || + vibrateInfo.effectId.empty()) { + MISC_HILOGE("SetLoopCount fail or parameter invalid"); + taihe::set_business_error(PARAMETER_ERROR, "SetLoopCount fail or parameter invalid"); + return; + } + int32_t ret = PlayPrimitiveEffect(vibrateInfo.effectId.c_str(), vibrateInfo.intensity); + if (ret != SUCCESS) { + taihe::set_business_error(PARAMETER_ERROR, "start vibrator failed"); + return; + } + } else { + int32_t ret = StartVibrate(vibrateInfo); + if (vibrateInfo.vibratorPattern.events != nullptr) { + CHKCV(ClearVibratorPattern(vibrateInfo.vibratorPattern), "ClearVibratorPattern fail"); + } + if (ret == PARAMETER_ERROR) { + taihe::set_business_error(PARAMETER_ERROR, "Parameters invalid"); + return; + } + } +} + +bool isHdHapticSupported() +{ + CALL_LOG_ENTER; + return IsHdHapticSupported(); +} + +void stopVibrationSync() +{ + CALL_LOG_ENTER; + int32_t ret = Cancel(); + if (ret != SUCCESS) { + taihe::set_business_error(ret, "Cancel execution fail"); + } +} + +bool isSupportEffectSync(::taihe::string_view effectId) +{ + CALL_LOG_ENTER; + bool isSupportEffect = false; + int32_t ret = IsSupportEffect(effectId.c_str(), &isSupportEffect); + if (ret != SUCCESS) { + taihe::set_business_error(ret, "IsSupportEffect execution failed"); + } + return isSupportEffect; +} +} // namespace + +// Since these macros are auto-generate, lint will cause false positive. +// NOLINTBEGIN +TH_EXPORT_CPP_API_stopVibrationByModeSync(stopVibrationByModeSync); +TH_EXPORT_CPP_API_startVibrationSync(startVibrationSync); +TH_EXPORT_CPP_API_isHdHapticSupported(isHdHapticSupported); +TH_EXPORT_CPP_API_stopVibrationSync(stopVibrationSync); +TH_EXPORT_CPP_API_isSupportEffectSync(isSupportEffectSync); +// NOLINTEND diff --git a/frameworks/ets/taihe/idl/ohos.vibrator.taihe b/frameworks/ets/taihe/idl/ohos.vibrator.taihe new file mode 100644 index 0000000..bf4e15c --- /dev/null +++ b/frameworks/ets/taihe/idl/ohos.vibrator.taihe @@ -0,0 +1,703 @@ +/* + * Copyright (c) 2025 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. + */ + +@!namespace("@ohos.vibrator", "vibrator") +@!sts_inject(""" +static { loadLibrary("vibrator_taihe_native.z") } +""") + +/** + * Preset vibration type vibration effect. + * + * @interface VibratePreset + * @syscap SystemCapability.Sensors.MiscDevice + * @since 9 + */ +struct VibratePreset { + /** + * The value is "preset", which triggers motor vibration according to preset vibration effect. + * + * @type { String } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 9 + */ + type: String; + + /** + * Preset type vibration. + * + * @type { String } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 9 + */ + effectId: String; + + /** + * The number of vibration repetitions. + * + * @syscap SystemCapability.Sensors.MiscDevice + * @since 9 + */ + /** + * The number of vibration repetitions. + * + * @type { Optional } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 12 + */ + count: Optional; + + /** + * The intensity of vibration effect. + * + * @type { Optional } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 12 + */ + intensity: Optional; +} + +/** + * Vibrate continuously for a period of time at the default intensity of the system. + * + * @interface VibrateTime + * @syscap SystemCapability.Sensors.MiscDevice + * @since 9 + */ +/** + * Vibrate continuously for a period of time at the default intensity of the system. + * + * @interface VibrateTime + * @syscap SystemCapability.Sensors.MiscDevice + * @atomicservice + * @since 11 + */ +struct VibrateTime { + /** + * The value is "time", which triggers the motor vibration according to the specified duration. + * + * @syscap SystemCapability.Sensors.MiscDevice + * @since 9 + */ + /** + * The value is "time", which triggers the motor vibration according to the specified duration. + * + * @type { String } + * @syscap SystemCapability.Sensors.MiscDevice + * @atomicservice + * @since 11 + */ + type: String; + + /** + * The duration of the vibration, in ms. + * + * @syscap SystemCapability.Sensors.MiscDevice + * @since 9 + */ + /** + * The duration of the vibration, in ms. + * + * @type { f64 } + * @syscap SystemCapability.Sensors.MiscDevice + * @atomicservice + * @since 11 + */ + duration: f64; /** The duration of the vibration, in ms */ +} + +/** + * The use of vibration. + * + * @typedef {'unknown' | 'alarm' | 'ring' | 'notification' | 'communication' | + * 'touch' | 'media' | 'physicalFeedback' | 'simulateReality'} + * @syscap SystemCapability.Sensors.MiscDevice + * @since 9 + */ +/** + * The use of vibration. + * + * @typedef {'unknown' | 'alarm' | 'ring' | 'notification' | 'communication' | + * 'touch' | 'media' | 'physicalFeedback' | 'simulateReality'} + * @syscap SystemCapability.Sensors.MiscDevice + * @atomicservice + * @since 11 + */ +@!sts_inject(""" + type Usage = 'unknown' | 'alarm' | 'ring' | 'notification' | 'communication' | + 'touch' | 'media' | 'physicalFeedback' | 'simulateReality'; +""") + +/** + * The attribute of vibration. + * + * @interface VibrateAttribute + * @syscap SystemCapability.Sensors.MiscDevice + * @since 9 + */ +/** + * The attribute of vibration. + * + * @interface VibrateAttribute + * @syscap SystemCapability.Sensors.MiscDevice + * @atomicservice + * @since 11 + */ +struct VibrateAttribute { + /** + * Vibrator id, default is 0. + * + * @syscap SystemCapability.Sensors.MiscDevice + * @since 9 + */ + /** + * Vibrator id, default is 0. + * + * @type { Optional } + * @syscap SystemCapability.Sensors.MiscDevice + * @atomicservice + * @since 11 + */ + id: Optional; + + /** + * The use of vibration. + * + * @syscap SystemCapability.Sensors.MiscDevice + * @since 9 + */ + /** + * The use of vibration. + * + * @type { String } + * @syscap SystemCapability.Sensors.MiscDevice + * @atomicservice + * @since 11 + */ + usage: String; + + /** + * Indicates whether to bypass system management switches. + * + * @type { Optional } + * @syscap SystemCapability.Sensors.MiscDevice + * @systemapi + * @since 12 + */ + systemUsage: Optional; +} + +/** + * Preset vibration effect string. + * + * @enum { String } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 8 + */ +enum EffectId: String { + /** + * Describes the vibration effect of the vibrator when a user adjusts the timer. + * + * @syscap SystemCapability.Sensors.MiscDevice + * @since 8 + */ + EFFECT_CLOCK_TIMER = "haptic.clock.timer" +} + +/** + * Vibrator vibration stop mode. + * + * @enum { string } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 8 + */ +enum VibratorStopMode: String { + /** + * Indicates the mode of stopping a one-shot vibration effect. + * + * @syscap SystemCapability.Sensors.MiscDevice + * @since 8 + */ + VIBRATOR_STOP_MODE_TIME = "time", + + /** + * Indicates the mode of stopping a preset vibration effect. + * + * @syscap SystemCapability.Sensors.MiscDevice + * @since 8 + */ + VIBRATOR_STOP_MODE_PRESET = "preset" +} + +/** + * Trigger motor vibration with custom vibration effects. + * + * @interface VibrateFromPattern + * @syscap SystemCapability.Sensors.MiscDevice + * @since 18 + */ +struct VibrateFromPattern { + /** + * The value is "pattern", which triggers motor vibration based on the combination pattern. + * + * @type { String } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 18 + */ + type: String; + + /** + * Customize the sequence of motor vibration events, the VibratorPattern object returned by the build() method. + * + * @type { VibratorPattern } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 18 + */ + pattern: VibratorPattern; +} + +/** + * Each 'events' attribute in the vibration sequence represents one vibration event + * + * @interface VibratorPattern + * @syscap SystemCapability.Sensors.MiscDevice + * @since 18 + */ +struct VibratorPattern { + /** + * Absolute starting time of vibration + * + * @type { i32 } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 18 + */ + time: i32; + + /** + * Vibration event array, where each 'events' attribute represents one vibration event. + * + * @type { Array } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 18 + */ + events: Array; +} + +/** + * Vibration event. + * + * @interface VibratorEvent + * @syscap SystemCapability.Sensors.MiscDevice + * @since 18 + */ +struct VibratorEvent { + /** + * Types of vibration events + * + * @type { VibratorEventType } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 18 + */ + eventType: VibratorEventType; + + /** + * Relative starting time of vibration + * + * @type { i32 } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 18 + */ + time: i32; + + /** + * The duration of vibration + * + * @type { Optional } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 18 + */ + duration: Optional; + + /** + * Intensity of vibration events + * + * @type { Optional } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 18 + */ + intensity: Optional; + + /** + * Vibration event frequency + * + * @type { Optional } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 18 + */ + frequency: Optional; + + /** + * Channel number + * + * @type { Optional } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 18 + */ + index: Optional; + + /** + * An array representing vibration adjustment curves. + * + * @type { Optional> } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 18 + */ + points: Optional>; +} + +/** + * Types of vibration events + * + * @enum { number } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 18 + */ +enum VibratorEventType: i32 { + /** + * Steady state long vibration + * + * @syscap SystemCapability.Sensors.MiscDevice + * @since 18 + */ + CONTINUOUS = 0, + + /** + * Transient short vibration + * + * @syscap SystemCapability.Sensors.MiscDevice + * @since 18 + */ + TRANSIENT = 1, +} + +/** + * The vibration curve is valid when the vibration event type is 'continuous' + * + * @interface VibratorCurvePoint + * @syscap SystemCapability.Sensors.MiscDevice + * @since 18 + */ +struct VibratorCurvePoint { + /** + * The offset of the starting time of the relative event. + * + * @type { i32 } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 18 + */ + time: i32; + + /** + * Gain in relative event vibration intensity + * + * @type { Optional } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 18 + */ + intensity: Optional; + /** + * Changes in relative event vibration frequency + * + * @type { Optional } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 18 + */ + frequency: Optional; +} + +/** + * The transient vibration parameters + * + * @interface TransientParam + * @syscap SystemCapability.Sensors.MiscDevice + * @since 18 + */ +struct TransientParam { + /** + * Intensity of vibration + * + * @type { Optional } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 18 + */ + intensity: Optional; + + /** + * Frequency of vibration + * + * @type { Optional } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 18 + */ + frequency: Optional; + + /** + * Index of vibration + * + * @type { Optional } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 18 + */ + index: Optional; +} + +/** + * The continuous vibration parameters + * + * @interface ContinuousParam + * @syscap SystemCapability.Sensors.MiscDevice + * @since 18 + */ +struct ContinuousParam { + /** + * Intensity of vibration + * + * @type { Optional } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 18 + */ + intensity: Optional; + + /** + * Frequency of vibration + * + * @type { Optional } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 18 + */ + frequency: Optional; + + /** + * The points of vibration + * + * @type { Optional> } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 18 + */ + points: Optional>; + + /** + * Index of vibration + * + * @type { Optional } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 18 + */ + index: Optional; +} + +/** + * Describes the effect of vibration. + * + * @typedef { VibrateTime | VibratePreset } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 9 + */ +/** + * Describes the effect of vibration. + * + * @typedef { VibrateTime | VibratePreset | VibrateFromFile } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 10 + */ +/** + * Describes the effect of vibration. + * + * @typedef { VibrateTime | VibratePreset | VibrateFromFile } + * @syscap SystemCapability.Sensors.MiscDevice + * @atomicservice + * @since 11 + */ +/** + * Describes the effect of vibration. + * + * @typedef { VibrateTime | VibratePreset | VibrateFromFile | VibrateFromPattern } + * @syscap SystemCapability.Sensors.MiscDevice + * @atomicservice + * @since 18 + */ +union VibrateEffect { + VibrateTime_type: VibrateTime; + VibratePreset_type: VibratePreset; + VibrateFromFile_type: VibrateFromFile; + VibrateFromPattern_type: VibrateFromPattern; +} + +/** + * Custom vibration, vibrate the effect from a haptic file. + * + * @interface VibrateFromFile + * @syscap SystemCapability.Sensors.MiscDevice + * @since 10 + */ +struct VibrateFromFile { + /** + * The value is "file", which triggers motor vibration according to the vibration profile. + * + * @type { String } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 10 + */ + type: String; + + /** + * Haptic file descriptor, some formats are supported. + * + * @type { HapticFileDescriptor } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 10 + */ + hapticFd: HapticFileDescriptor; +} + +/** + * Haptic file descriptor. The caller needs to ensure that the fd is valid and + * the offset and length are correct. + * + * @interface HapticFileDescriptor + * @syscap SystemCapability.Sensors.MiscDevice + * @since 10 + */ +struct HapticFileDescriptor { + /** + * The file descriptor of haptic effect source from file system. The caller + * is responsible to close the file descriptor. + * + * @type { i32 } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 10 + */ + fd: i32; + + /** + * The offset into the file where the data to be read, in bytes. By default, + * the offset is zero. + * + * @type { Optional } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 10 + */ + offset: Optional; + + /** + * The length in bytes of the data to be read. By default, the length is the + * rest of bytes in the file from the offset. + * + * @type { Optional } + * @syscap SystemCapability.Sensors.MiscDevice + * @since 10 + */ + length: Optional; +} + +/** + * Stop the vibrator from vibrating. + * + * @permission ohos.permission.VIBRATE + * @param { VibratorStopMode } stopMode - Indicate the stop mode in which the motor vibrates, {@code VibratorStopMode}. + * @returns { void } Promise used to return the result. + * @throws { BusinessError } 201 - Permission denied. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types; 3. Parameter verification failed. + * @syscap SystemCapability.Sensors.MiscDevice + * @since 9 + */ +@gen_async("stopVibration") +@gen_promise("stopVibration") +function stopVibrationByModeSync(stopMode: VibratorStopMode): void; + +/** + * Trigger vibrator vibration. + * + * @permission ohos.permission.VIBRATE + * @param { VibrateEffect } effect - Indicate vibrate effect, {@code VibrateEffect}. + * @param { VibrateAttribute } attribute - Indicate vibrate attribute, {@code VibrateAttribute}. + * @param { AsyncCallback } callback - The callback of startVibration. + * @throws { BusinessError } 201 - Permission denied. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types; 3. Parameter verification failed. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 14600101 - Device operation failed. + * @syscap SystemCapability.Sensors.MiscDevice + * @since 9 + */ +/** + * Trigger vibrator vibration. + * + * @permission ohos.permission.VIBRATE + * @param { VibrateEffect } effect - Indicate vibrate effect, {@code VibrateEffect} + * @param { VibrateAttribute } attribute - Indicate vibrate attribute, {@code VibrateAttribute} + * @param { void } callback - The callback of startVibration + * @throws { BusinessError } 201 - Permission denied + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types; 3. Parameter verification failed. + * @throws { BusinessError } 801 - Capability not supported + * @throws { BusinessError } 14600101 - Device operation failed + * @syscap SystemCapability.Sensors.MiscDevice + * @atomicservice + * @since 11 + */ +@gen_async("startVibration") +@gen_promise("startVibration") +function startVibrationSync(effect: VibrateEffect, attribute: VibrateAttribute): void; + +/** + * Whether the high-definition haptic is supported. + * + * @returns { bool } Returns whether the high-definition haptic is supported. + * @throws { BusinessError } 14600101 - Device operation failed. + * @syscap SystemCapability.Sensors.MiscDevice + * @since 12 + */ +function isHdHapticSupported(): bool; + +/** + * Stop any type of vibration. + * + * @permission ohos.permission.VIBRATE + * @throws { BusinessError } 201 - Permission denied. + * @throws { BusinessError } 14600101 - Device operation failed. + * @syscap SystemCapability.Sensors.MiscDevice + * @atomicservice + * @since 12 + */ +@gen_async("stopVibration") +@gen_promise("stopVibration") +function stopVibrationSync(): void; + +/** + * Whether the preset vibration effect is supported. + * + * @param { String } effectId Indicate the specified effect of the preset, {@code EffectId}. + * @returns { bool } Promise used to return the result. + * @throws { BusinessError } 201 - Permission denied. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types; 3. Parameter verification failed. + * @syscap SystemCapability.Sensors.MiscDevice + * @since 10 + */ +@gen_async("isSupportEffect") +@gen_promise("isSupportEffect") +function isSupportEffectSync(effectId: String): bool; \ No newline at end of file diff --git a/frameworks/js/ani/vibrator/ets/@ohos.vibrator.ets b/frameworks/js/ani/vibrator/ets/@ohos.vibrator.ets deleted file mode 100644 index 3104e87..0000000 --- a/frameworks/js/ani/vibrator/ets/@ohos.vibrator.ets +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2025 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. - */ - -import type { AsyncCallback } from '@ohos.base'; -import { BusinessError } from '@ohos.base'; - -export default namespace vibrator { - loadLibrary("vibrator_ani"); - - native function startVibrationSync(effect: VibrateEffect, attribute: VibrateAttribute): void; - export function startVibrationIntSync(effect: VibrateEffect, attribute: VibrateAttribute): int { - startVibrationSync(effect, attribute); - return 0; - } - - export function startVibration(effect: VibrateEffect, attribute: VibrateAttribute, callback: AsyncCallback): void { - let p1 = taskpool.execute(startVibrationIntSync, effect, attribute); - p1.then((e: NullishType)=>{ - console.log("in callback startVibration then.") - let err1 : BusinessError - callback(err1, undefined); - }); - p1.catch((err: NullishType) => { - console.log("startVibration catch in callback thread."); - let err2 = err as BusinessError; - callback(err2, undefined); - }) - } - - export function startVibration(effect: VibrateEffect, attribute: VibrateAttribute): Promise { - let p = new Promise((resolve: (v: undefined) => void, reject: (error: Object) => void) : void => { - let p1 = taskpool.execute(startVibrationIntSync, effect, attribute); - p1.then((e: NullishType) : void =>{ - console.log("in Promise startVibration then. e is ", e) - resolve(undefined); - }); - p1.catch((err: Error) : void => { - console.log("startVibration catch in promise thread."); - reject(err); - }); - }); - return p; - } - - export native function isSupportEffectInterally(effectId: string): boolean; - - export function isSupportEffect(effectId: string, callback: AsyncCallback): void { - let p1 = taskpool.execute(isSupportEffectInterally, effectId); - p1.then((e: NullishType)=>{ - let r = e as boolean; - console.log("in callback isSupportEffectInterally then. e is ", e) - let err : BusinessError - callback(err, r); - }); - p1.catch((error: NullishType) => { - console.log("isSupportEffect catch in callback thread."); - let err = error as BusinessError; - let e : boolean; - callback(err, e); - }); - } - - export function isSupportEffect(effectId: string): Promise { - let p = new Promise((resolve: (v: boolean) => void, reject: (error: Object) => void) : boolean => { - let p1 = taskpool.execute(isSupportEffectInterally, effectId); - p1.then((e: NullishType) : boolean=>{ - let r = e as boolean; - console.log("in promise isSupportEffectInterally then. e is ", e) - resolve(r); - }); - p1.catch((err: Error) : boolean => { - console.log("isSupportEffect catch in promise thread."); - reject(err); - }); - }); - return p; - } - - export type Usage = 'unknown' | 'alarm' | 'ring' | 'notification' | 'communication' | - 'touch' | 'media' | 'physicalFeedback' | 'simulateReality'; - - export interface VibrateAttribute { - id?: number; - usage: Usage; - systemUsage?: boolean; - } - - export type VibrateEffect = VibrateTime | VibratePreset | VibrateFromFile | VibrateFromPattern; - - export interface VibrateTime { - type: 'time'; - duration: number; - } - - export interface VibratePreset { - type: 'preset'; - effectId: string; - count?: number; - intensity?: number; - } - - export interface VibrateFromFile { - type: 'file'; - hapticFd: HapticFileDescriptor; - } - - export interface HapticFileDescriptor { - fd: number; - offset?: number; - length?: number; - } - - export interface VibrateFromPattern { - type: 'pattern'; - pattern: VibratorPattern; - } - - export interface VibratorPattern { - time: number; - events: Array; - } - - export interface VibratorEvent { - eventType: VibratorEventType; - time: number; - duration?: number; - intensity?: number; - frequency?: number; - index?: number; - points?: Array; - } - - export enum VibratorEventType { - CONTINUOUS = 0, - TRANSIENT = 1, - } - - export interface VibratorCurvePoint { - time: number; - intensity?: number; - frequency?: number; - } - -} diff --git a/frameworks/js/ani/vibrator/include/ani_utils.h b/frameworks/js/ani/vibrator/include/ani_utils.h deleted file mode 100644 index 663a794..0000000 --- a/frameworks/js/ani/vibrator/include/ani_utils.h +++ /dev/null @@ -1,564 +0,0 @@ -/* - * Copyright (c) 2025 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. - */ - -#ifndef ANI_UTILS_H -#define ANI_UTILS_H - -#include - -#include -#include -#include -#include -#include -#include -#include -class AniStringUtils { -public: - static std::string ToStd(ani_env *env, ani_string ani_str) - { - ani_size strSize; - env->String_GetUTF8Size(ani_str, &strSize); - - std::vector buffer(strSize + 1); // +1 for null terminator - char* utf8_buffer = buffer.data(); - - //String_GetUTF8 Supportted by https://gitee.com/openharmony/arkcompiler_runtime_core/pulls/3416 - ani_size bytes_written = 0; - env->String_GetUTF8(ani_str, utf8_buffer, strSize + 1, &bytes_written); - - utf8_buffer[bytes_written] = '\0'; - std::string content = std::string(utf8_buffer); - return content; - } - - static ani_string ToAni(ani_env* env, const std::string& str) - { - ani_string aniStr = nullptr; - if (ANI_OK != env->String_NewUTF8(str.data(), str.size(), &aniStr)) { - std::cerr << "[ANI] Unsupported ANI_VERSION_1" << std::endl; - return nullptr; - } - return aniStr; - } -}; - -class UnionAccessor { -public: - UnionAccessor(ani_env *env, ani_object &obj) : env_(env), obj_(obj) - { - } - - bool IsInstanceOf(const std::string& cls_name) - { - ani_class cls; - env_->FindClass(cls_name.c_str(), &cls); - - ani_boolean ret; - env_->Object_InstanceOf(obj_, cls, &ret); - return ret; - } - - template - bool IsInstanceOfType(); - - template - bool TryConvert(T &value); - - template - bool TryConvertArray(std::vector &value); - -private: - ani_env *env_; - ani_object obj_; -}; - -template<> -bool UnionAccessor::IsInstanceOfType() -{ - return IsInstanceOf("Lstd/core/Boolean;"); -} - -template<> -bool UnionAccessor::IsInstanceOfType() -{ - return IsInstanceOf("Lstd/core/Int;"); -} - -template<> -bool UnionAccessor::IsInstanceOfType() -{ - return IsInstanceOf("Lstd/core/Double;"); -} - -template<> -bool UnionAccessor::IsInstanceOfType() -{ - return IsInstanceOf("Lstd/core/String;"); -} - -template<> -bool UnionAccessor::TryConvert(bool &value) -{ - if (!IsInstanceOfType()) { - return false; - } - - ani_boolean aniValue; - auto ret = env_->Object_CallMethodByName_Boolean(obj_, "unboxed", nullptr, &aniValue); - if (ret != ANI_OK) { - return false; - } - value = static_cast(aniValue); - return true; -} - -template<> -bool UnionAccessor::TryConvert(int &value) -{ - if (!IsInstanceOfType()) { - return false; - } - - ani_int aniValue; - auto ret = env_->Object_CallMethodByName_Int(obj_, "unboxed", nullptr, &aniValue); - if (ret != ANI_OK) { - return false; - } - value = static_cast(aniValue); - return true; -} - -template<> -bool UnionAccessor::TryConvert(double &value) -{ - if (!IsInstanceOfType()) { - return false; - } - - ani_double aniValue; - auto ret = env_->Object_CallMethodByName_Double(obj_, "unboxed", nullptr, &aniValue); - if (ret != ANI_OK) { - return false; - } - value = static_cast(aniValue); - return true; -} - -template<> -bool UnionAccessor::TryConvert(std::string &value) -{ - if (!IsInstanceOfType()) { - return false; - } - - value = AniStringUtils::ToStd(env_, static_cast(obj_)); - return true; -} - -template<> -bool UnionAccessor::TryConvertArray(std::vector &value) -{ - ani_double length; - if (ANI_OK != env_->Object_GetPropertyByName_Double(obj_, "length", &length)) { - std::cerr << "Object_GetPropertyByName_Double length failed" << std::endl; - return false; - } - for (int i = 0; i < int(length); i++) { - ani_ref ref; - if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i)) { - std::cerr << "Object_GetPropertyByName_Ref failed" << std::endl; - return false; - } - ani_boolean val; - if (ANI_OK != env_->Object_CallMethodByName_Boolean(static_cast(ref), "unboxed", nullptr, &val)) { - std::cerr << "Object_CallMethodByName_Double unbox failed" << std::endl; - return false; - } - value.push_back(static_cast(val)); - } - return true; -} - -template<> -bool UnionAccessor::TryConvertArray(std::vector &value) -{ - ani_double length; - if (ANI_OK != env_->Object_GetPropertyByName_Double(obj_, "length", &length)) { - std::cerr << "Object_GetPropertyByName_Double length failed" << std::endl; - return false; - } - for (int i = 0; i < int(length); i++) { - ani_ref ref; - if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i)) { - std::cerr << "Object_GetPropertyByName_Ref failed" << std::endl; - return false; - } - ani_int intValue; - if (ANI_OK != env_->Object_CallMethodByName_Int(static_cast(ref), "unboxed", nullptr, &intValue)) { - std::cerr << "Object_CallMethodByName_Double unbox failed" << std::endl; - return false; - } - value.push_back(static_cast(intValue)); - } - return true; -} - -template<> -bool UnionAccessor::TryConvertArray(std::vector &value) -{ - ani_double length; - if (ANI_OK != env_->Object_GetPropertyByName_Double(obj_, "length", &length)) { - std::cerr << "Object_GetPropertyByName_Double length failed" << std::endl; - return false; - } - for (int i = 0; i < int(length); i++) { - ani_ref ref; - if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i)) { - std::cerr << "Object_GetPropertyByName_Ref failed" << std::endl; - return false; - } - ani_double val; - if (ANI_OK != env_->Object_CallMethodByName_Double(static_cast(ref), "unboxed", nullptr, &val)) { - std::cerr << "Object_CallMethodByName_Double unbox failed" << std::endl; - return false; - } - value.push_back(static_cast(val)); - } - return true; -} - -template<> -bool UnionAccessor::TryConvertArray(std::vector &value) -{ - std::cout << "TryConvertArray std::vector" << std::endl; - ani_ref buffer; - if (ANI_OK != env_->Object_GetFieldByName_Ref(obj_, "buffer", &buffer)) { - std::cout << "Object_GetFieldByName_Ref failed" << std::endl; - return false; - } - void* data; - size_t length; - if (ANI_OK != env_->ArrayBuffer_GetInfo(static_cast(buffer), &data, &length)) { - std::cerr << "ArrayBuffer_GetInfo failed" << std::endl; - return false; - } - std::cout << "Length of buffer is " << length << std::endl; - for (size_t i = 0; i < length; i++) { - value.push_back(static_cast(data)[i]); - } - return true; -} - -template<> -bool UnionAccessor::TryConvertArray(std::vector &value) -{ - ani_double length; - if (ANI_OK != env_->Object_GetPropertyByName_Double(obj_, "length", &length)) { - std::cerr << "Object_GetPropertyByName_Double length failed" << std::endl; - return false; - } - - for (int i = 0; i < int(length); i++) { - ani_ref ref; - if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i)) { - std::cerr << "Object_GetPropertyByName_Double length failed" << std::endl; - return false; - } - value.push_back(AniStringUtils::ToStd(env_, static_cast(ref))); - } - return true; -} - -class OptionalAccessor { -public: - OptionalAccessor(ani_env *env, ani_object &obj) : env_(env), obj_(obj) - { - } - - bool IsUndefined() - { - ani_boolean isUndefined; - env_->Reference_IsUndefined(obj_, &isUndefined); - return isUndefined; - } - - template - std::optional Convert(); - -private: - ani_env *env_; - ani_object obj_; -}; - -template<> -std::optional OptionalAccessor::Convert() -{ - if (IsUndefined()) { - return std::nullopt; - } - - ani_double aniValue; - auto ret = env_->Object_CallMethodByName_Double(obj_, "doubleValue", nullptr, &aniValue); - if (ret != ANI_OK) { - return std::nullopt; - } - auto value = static_cast(aniValue); - return value; -} - -template<> -std::optional OptionalAccessor::Convert() -{ - if (IsUndefined()) { - return std::nullopt; - } - - ani_size strSize; - env_->String_GetUTF8Size(static_cast(obj_), &strSize); - - std::vector buffer(strSize + 1); - char* utf8_buffer = buffer.data(); - - ani_size bytes_written = 0; - env_->String_GetUTF8(static_cast(obj_), utf8_buffer, strSize + 1, &bytes_written); - - utf8_buffer[bytes_written] = '\0'; - std::string content = std::string(utf8_buffer); - return content; -} - -template -class expected { -private: - std::variant data_; - bool has_value_; - -public: - expected(const T &value) - : data_(value), has_value_(true) - { - } - - expected(T &&value) - : data_(std::move(value)), has_value_(true) - { - } - - expected(const E &error) - : data_(error), has_value_(false) - { - } - - expected(E &&error) - : data_(std::move(error)), has_value_(false) - { - } - - bool has_value() const noexcept - { - return has_value_; - } - - explicit operator bool() const noexcept - { - return has_value(); - } - - T &value() & - { - if (!has_value()) { - std::terminate(); - } - return std::get(data_); - } - - const T &value() const & - { - if (!has_value()) { - std::terminate(); - } - return std::get(data_); - } - - T &&value() && - { - if (!has_value()) { - std::terminate(); - } - return std::get(std::move(data_)); - } - - E &error() & - { - if (has_value()) { - std::terminate(); - } - return std::get(data_); - } - - const E &error() const & - { - if (has_value()) { - std::terminate(); - } - return std::get(data_); - } - - E &&error() && - { - if (has_value()) { - std::terminate(); - } - return std::get(std::move(data_)); - } - - T &operator*() & - { - return value(); - } - - const T &operator*() const & - { - return value(); - } - - T &&operator*() && - { - return std::move(*this).value(); - } - - T *operator->() - { - return &value(); - } - - const T *operator->() const - { - return &value(); - } - - template - T value_or(U &&default_value) const & - { - return has_value() ? value() : static_cast(std::forward(default_value)); - } - - template - T value_or(U &&default_value) && - { - return has_value() ? std::move(*this).value() : static_cast(std::forward(default_value)); - } -}; - -class EnumAccessor { - public: - EnumAccessor(ani_env *env, const char* className, ani_int index) : env_(env) - { - initStatus_ = ANI_ERROR; - ani_enum_item item; - initStatus_ = GetItem(className, index, item); - if (ANI_OK == initStatus_) { - item_ = item; - } - } - - EnumAccessor(ani_env *env, ani_enum_item item) : env_(env), item_(item) - { - initStatus_ = ANI_ERROR; - } - - template - expected To() - { - int32_t value{}; - ani_status status = ToInt(value); - if (ANI_OK != status) { - return status; - } - return static_cast(value); - } - - ani_status ToInt(int32_t &value) - { - if (!item_) { - return initStatus_; - } - - ani_status status = env_->EnumItem_GetValue_Int(item_.value(), &value); - if (ANI_OK != status) { - return status; - } - return ANI_OK; - } - - expected ToInt() - { - int32_t value; - ani_status status = ToInt(value); - if (ANI_OK != status) { - return status; - } - return value; - } - - ani_status ToString(std::string &value) - { - if (!item_) { - return initStatus_; - } - - ani_string strValue; - ani_status status = env_->EnumItem_GetValue_String(item_.value(), &strValue); - if (ANI_OK != status) { - return status; - } - value = AniStringUtils::ToStd(env_, strValue); - return ANI_OK; - } - - expected ToString() - { - std::string value; - ani_status status = ToString(value); - if (ANI_OK != status) { - return status; - } - return value; - } - - private: - ani_status GetItem(const char* className, ani_int index, ani_enum_item &item) - { - ani_status status = ANI_ERROR; - ani_enum enumType; - status = env_->FindEnum(className, &enumType); - if (ANI_OK != status) { - return status; - } - - status = env_->Enum_GetEnumItemByIndex(enumType, index, &item); - if (ANI_OK != status) { - return status; - } - return ANI_OK; - } - - private: - ani_env *env_; - std::optional item_; - ani_status initStatus_; -}; -#endif diff --git a/frameworks/js/ani/vibrator/src/vibrator_ani.cpp b/frameworks/js/ani/vibrator/src/vibrator_ani.cpp deleted file mode 100644 index a7da738..0000000 --- a/frameworks/js/ani/vibrator/src/vibrator_ani.cpp +++ /dev/null @@ -1,816 +0,0 @@ -/* - * Copyright (c) 2025 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 -#include -#include -#include "napi/native_api.h" -#include "ani_utils.h" -#include "file_utils.h" -#include -#include "miscdevice_log.h" -#include "vibrator_agent.h" - -#undef LOG_TAG -#define LOG_TAG "VibratorAni" - -using namespace OHOS::Sensors; - -constexpr int32_t INTENSITY_ADJUST_MAX = 100; -constexpr int32_t EVENT_START_TIME_MAX = 1800000; -constexpr int32_t EVENT_NUM_MAX = 128; -constexpr int32_t INTENSITY_MIN = 0; -constexpr int32_t INTENSITY_MAX = 100; -constexpr int32_t FREQUENCY_MIN = 0; -constexpr int32_t FREQUENCY_MAX = 100; -constexpr int32_t CURVE_POINT_INTENSITY_MAX = 100; -constexpr int32_t CURVE_POINT_NUM_MIN = 4; -constexpr int32_t CURVE_POINT_NUM_MAX = 16; -constexpr int32_t CURVE_FREQUENCY_MIN = -100; -constexpr int32_t CURVE_FREQUENCY_MAX = 100; -constexpr int32_t CONTINUOUS_DURATION_MAX = 5000; -constexpr int32_t EVENT_INDEX_MAX = 2; - -static std::map g_usageType = { - {"unknown", USAGE_UNKNOWN}, - {"alarm", USAGE_ALARM}, - {"ring", USAGE_RING}, - {"notification", USAGE_NOTIFICATION}, - {"communication", USAGE_COMMUNICATION}, - {"touch", USAGE_TOUCH}, - {"media", USAGE_MEDIA}, - {"physicalFeedback", USAGE_PHYSICAL_FEEDBACK}, - {"simulateReality", USAGE_SIMULATE_REALITY}, -}; - -static std::set g_allowedTypes = {"time", "preset", "file", "pattern"}; - -typedef 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; -} VibrateInfo; - -static void ThrowBusinessError(ani_env *env, int errCode, std::string&& errMsg) -{ - MISC_HILOGD("Begin ThrowBusinessError."); - static const char *errorClsName = "L@ohos/base/BusinessError;"; - ani_class cls {}; - if (ANI_OK != env->FindClass(errorClsName, &cls)) { - MISC_HILOGE("find class BusinessError %{public}s failed", errorClsName); - return; - } - ani_method ctor; - if (ANI_OK != env->Class_FindMethod(cls, "", ":V", &ctor)) { - MISC_HILOGE("find method BusinessError.constructor failed"); - return; - } - ani_object errorObject; - if (ANI_OK != env->Object_New(cls, ctor, &errorObject)) { - MISC_HILOGE("create BusinessError object failed"); - return; - } - ani_double aniErrCode = static_cast(errCode); - ani_string errMsgStr; - if (ANI_OK != env->String_NewUTF8(errMsg.c_str(), errMsg.size(), &errMsgStr)) { - MISC_HILOGE("convert errMsg to ani_string failed"); - return; - } - if (ANI_OK != env->Object_SetFieldByName_Double(errorObject, "code", aniErrCode)) { - MISC_HILOGE("set error code failed"); - return; - } - if (ANI_OK != env->Object_SetPropertyByName_Ref(errorObject, "message", errMsgStr)) { - MISC_HILOGE("set error message failed"); - return; - } - env->ThrowError(static_cast(errorObject)); - return; -} - -static bool ParserParamFromVibrateTime(ani_env *env, ani_object effect, VibrateInfo &vibrateInfo) -{ - ani_ref type; - if (ANI_OK != env->Object_GetPropertyByName_Ref(effect, "type", &type)) { - MISC_HILOGE("Failed to get property named type"); - return false; - } - auto typeStr = AniStringUtils::ToStd(env, static_cast(type)); - vibrateInfo.type = typeStr; - MISC_HILOGD("vibrateInfo.type: %{public}s", typeStr.c_str()); - - ani_double duration; - if (ANI_OK != env->Object_GetPropertyByName_Double(effect, "duration", &duration)) { - MISC_HILOGE("Failed to get property named duration"); - return false; - } - vibrateInfo.duration = static_cast(duration); - MISC_HILOGD("vibrateInfo.duration: %{public}d", vibrateInfo.duration); - return true; -} - -static bool SetVibrateProperty(ani_env* env, ani_object effect, const char* propertyName, int32_t& propertyValue) -{ - ani_ref propertyRef; - ani_boolean isUndefined = false; - if (env->Object_GetPropertyByName_Ref(effect, propertyName, &propertyRef) != ANI_OK) { - MISC_HILOGD("Can not find \"%{public}s\" property", propertyName); - return false; - } - - env->Reference_IsUndefined(propertyRef, &isUndefined); - if (isUndefined) { - MISC_HILOGD("\"%{public}s\" is undefined", propertyName); - return false; - } - - ani_double result; - if (ANI_OK != env->Object_CallMethodByName_Double(static_cast(propertyRef), "doubleValue", nullptr, - &result)) { - MISC_HILOGE("Failed to call Method named doubleValue on property \"%{public}s\"", propertyName); - return false; - } - - propertyValue = static_cast(result); - MISC_HILOGD("\"%{public}s\": %{public}d", propertyName, propertyValue); - - return true; -} - -static bool ParserParamFromVibratePreset(ani_env *env, ani_object effect, VibrateInfo &vibrateInfo) -{ - ani_ref type; - if (ANI_OK != env->Object_GetPropertyByName_Ref(effect, "type", &type)) { - MISC_HILOGE("Failed to get property named type"); - return false; - } - auto typeStr = AniStringUtils::ToStd(env, static_cast(type)); - vibrateInfo.type = typeStr; - MISC_HILOGD("vibrateInfo.type: %{public}s", typeStr.c_str()); - - ani_ref effectId; - if (ANI_OK != env->Object_GetPropertyByName_Ref(effect, "effectId", &effectId)) { - MISC_HILOGE("Failed to get property named effectId"); - return false; - } - auto effectIdStr = AniStringUtils::ToStd(env, static_cast(effectId)); - vibrateInfo.effectId = effectIdStr; - MISC_HILOGD("effectId: %{public}s", vibrateInfo.effectId.c_str()); - - if (!SetVibrateProperty(env, effect, "count", vibrateInfo.count)) { - vibrateInfo.count = 1; - } - MISC_HILOGD("count: %{public}d", vibrateInfo.count); - - if (!SetVibrateProperty(env, effect, "intensity", vibrateInfo.intensity)) { - vibrateInfo.intensity = INTENSITY_ADJUST_MAX; - } - MISC_HILOGD("intensity: %{public}d", vibrateInfo.intensity); - return true; -} - -static bool SetVibratePropertyInt64(ani_env* env, ani_object effect, const char* propertyName, int64_t& propertyValue) -{ - ani_ref propertyRef; - ani_boolean isUndefined = false; - if (env->Object_GetPropertyByName_Ref(effect, propertyName, &propertyRef) != ANI_OK) { - MISC_HILOGD("Can not find \"%{public}s\" property", propertyName); - return false; - } - - env->Reference_IsUndefined(propertyRef, &isUndefined); - if (isUndefined) { - MISC_HILOGD("\"%{public}s\" is undefined", propertyName); - return false; - } - - ani_double result; - if (ANI_OK != env->Object_CallMethodByName_Double(static_cast(propertyRef), "doubleValue", nullptr, - &result)) { - MISC_HILOGE("Failed to call Method named doubleValue on property \"%{public}s\"", propertyName); - return false; - } - - propertyValue = static_cast(result); - MISC_HILOGD("\"%{public}s\": %{public}lld", propertyName, propertyValue); - - return true; -} - -static bool ParserParamFromVibrateFromFile(ani_env *env, ani_object effect, VibrateInfo &vibrateInfo) -{ - ani_ref type; - if (ANI_OK != env->Object_GetPropertyByName_Ref(effect, "type", &type)) { - MISC_HILOGE("Failed to get property named type"); - return false; - } - auto typeStr = AniStringUtils::ToStd(env, static_cast(type)); - vibrateInfo.type = typeStr; - - ani_ref hapticFd; - if (ANI_OK != env->Object_GetPropertyByName_Ref(effect, "hapticFd", &hapticFd)) { - MISC_HILOGE("Failed to get property named hapticFd"); - return false; - } - - ani_double fd; - if (ANI_OK != env->Object_GetPropertyByName_Double(static_cast(hapticFd), "fd", &fd)) { - MISC_HILOGE("Failed to get property named fd"); - return false; - } - vibrateInfo.fd = static_cast(fd); - MISC_HILOGD("vibrateInfo.type: %{public}s, vibrateInfo.fd: %{public}d", typeStr.c_str(), vibrateInfo.fd); - - SetVibratePropertyInt64(env, static_cast(hapticFd), "offset", vibrateInfo.offset); - MISC_HILOGD("vibrateInfo.offset: %{public}lld", vibrateInfo.offset); - int64_t fdSize = GetFileSize(vibrateInfo.fd); - if (!(vibrateInfo.offset >= 0) && (vibrateInfo.offset <= fdSize)) { - MISC_HILOGE("The parameter of offset is invalid"); - return false; - } - vibrateInfo.length = fdSize - vibrateInfo.offset; - SetVibratePropertyInt64(env, static_cast(hapticFd), "length", vibrateInfo.length); - MISC_HILOGD("vibrateInfo.length: %{public}lld", vibrateInfo.length); - return true; -} - -static bool SetVibrateBooleanProperty(ani_env* env, ani_object attribute, const char* propertyName, - VibrateInfo& vibrateInfo) -{ - ani_ref propertyRef; - ani_boolean isUndefined = false; - if (env->Object_GetPropertyByName_Ref(attribute, propertyName, &propertyRef) != ANI_OK) { - MISC_HILOGE("Failed to get \"%{public}s\" property", propertyName); - return false; - } - - env->Reference_IsUndefined(propertyRef, &isUndefined); - if (isUndefined) { - MISC_HILOGE("\"%{public}s\" is not undefined", propertyName); - return false; - } - - ani_boolean result; - if (ANI_OK != env->Object_CallMethodByName_Boolean(static_cast(propertyRef), "unboxed", nullptr, - &result)) { - MISC_HILOGE("Failed to call Method named unboxed on property \"%{public}s\"", propertyName); - return false; - } - - vibrateInfo.systemUsage = static_cast(result); - return true; -} - -static bool ParserParamFromVibrateAttribute(ani_env *env, ani_object attribute, VibrateInfo &vibrateInfo) -{ - ani_ref usage; - if (ANI_OK != env->Object_GetPropertyByName_Ref(attribute, "usage", &usage)) { - MISC_HILOGE("Object_GetPropertyByName_Ref Fail"); - return false; - } - auto usageStr = AniStringUtils::ToStd(env, static_cast(usage)); - vibrateInfo.usage = usageStr; - MISC_HILOGD("vibrateInfo.usage: %{public}s", vibrateInfo.usage.c_str()); - - if (!SetVibrateBooleanProperty(env, attribute, "systemUsage", vibrateInfo)) { - vibrateInfo.systemUsage = false; - } - MISC_HILOGD("vibrateInfo.systemUsage: %{public}d", vibrateInfo.systemUsage); - return true; -} - -static bool GetPropertyAsDouble(ani_env* env, ani_object obj, const char* propertyName, ani_double* outValue) -{ - ani_ref propRef = nullptr; - ani_boolean isUndefined = false; - - if (env->Object_GetPropertyByName_Ref(obj, propertyName, &propRef) != ANI_OK) { - MISC_HILOGE("GetPropertyAsDouble: Failed to get property '%{punlic}s'", propertyName); - return false; - } - - env->Reference_IsUndefined(propRef, &isUndefined); - if (isUndefined) { - MISC_HILOGE("GetPropertyAsDouble: Property '%{punlic}s' is undefined", propertyName); - return false; - } - - if (env->Object_CallMethodByName_Double(static_cast(propRef), "doubleValue", nullptr, outValue) != - ANI_OK) { - MISC_HILOGE("GetPropertyAsDouble: Failed to call 'doubleValue' on property '%{punlic}s'", propertyName); - return false; - } - - return true; -} - -static bool ParseVibratorCurvePoint(ani_env *env, ani_object pointsArray, uint32_t index, VibratorCurvePoint &point) -{ - auto array = static_cast(pointsArray); - ani_ref arrayRef; - if (env->Array_Get_Ref(array, index, &arrayRef) != ANI_OK) { - MISC_HILOGE("Array_Get_Ref Fail"); - return false; - } - ani_double time = 0; - if (ANI_OK != env->Object_GetPropertyByName_Double(static_cast(arrayRef), "time", &time)) { - MISC_HILOGE("Object_GetPropertyByName_Double Fail"); - return false; - } - point.time = static_cast(time); - MISC_HILOGD("ParseVibrateEvent point.time: %{public}d", point.time); - - ani_double intensity = 0; - ani_double frequency = 0; - if (GetPropertyAsDouble(env, static_cast(arrayRef), "intensity", &intensity)) { - point.intensity = static_cast(intensity); - MISC_HILOGD("ParseVibrateEvent point.intensity: %{public}d", point.intensity); - } - - if (GetPropertyAsDouble(env, static_cast(arrayRef), "frequency", &frequency)) { - point.frequency = static_cast(frequency); - MISC_HILOGD("ParseVibrateEvent point.frequency: %{public}d", point.frequency); - } - - return true; -} - -static bool ParseVibratorCurvePointArray(ani_env *env, ani_object pointsArray, uint32_t pointsLength, - VibratorEvent &event) -{ - if (pointsLength <= 0 || pointsLength > CURVE_POINT_NUM_MAX) { - MISC_HILOGE("pointsLength should not be less than or equal to 0 or greater than CURVE_POINT_NUM_MAX"); - return false; - } - VibratorCurvePoint *points = - static_cast(malloc(sizeof(VibratorCurvePoint) * pointsLength)); - if (points == nullptr) { - MISC_HILOGE("malloc failed"); - return false; - } - for (uint32_t i = 0; i < pointsLength; ++i) { - if (!ParseVibratorCurvePoint(env, pointsArray, i, points[i])) { - MISC_HILOGE("ParseVibratorCurvePoint failed"); - free(points); - points = nullptr; - return false; - } - } - event.points = points; - return true; -} - -static bool ParsePointsArray(ani_env *env, ani_object parentObject, VibratorEvent &event) -{ - ani_ref points = nullptr; - ani_boolean isUndefined = false; - if (env->Object_GetPropertyByName_Ref(parentObject, "points", &points) != ANI_OK) { - MISC_HILOGE("Can not find \"points\" property"); - return false; - } - - env->Reference_IsUndefined(points, &isUndefined); - if (isUndefined) { - MISC_HILOGE("\"points\" is undefined"); - return true; - } - - ani_size sizePoints = 0; - if (env->Array_GetLength(static_cast(points), &sizePoints) != ANI_OK) { - MISC_HILOGE("Get point array length failed"); - return false; - } - - event.pointNum = static_cast(sizePoints); - - if (static_cast(sizePoints) > 0) { - if (!ParseVibratorCurvePointArray(env, static_cast(points), - static_cast(sizePoints), event)) { - MISC_HILOGE("ParseVibratorCurvePointArray failed"); - return false; - } - } - - return true; -} - -static bool ParseVibrateEvent(ani_env *env, ani_object eventArray, int32_t index, VibratorEvent &event) -{ - auto array = static_cast(eventArray); - ani_ref arrayRef; - if (env->Array_Get_Ref(array, index, &arrayRef) != ANI_OK) { - MISC_HILOGE("Array_Get_Ref Fail"); - return false; - } - ani_ref aniEventType; - if (ANI_OK != env->Object_GetPropertyByName_Ref(static_cast(arrayRef), "eventType", &aniEventType)) { - MISC_HILOGE("Can not find \"eventType\" property"); - return false; - } - - EnumAccessor eventTypeAccessor(env, static_cast(aniEventType)); - expected eventTypeExpected = eventTypeAccessor.To(); - if (!eventTypeExpected) { - return false; - } - VibratorEventType eventType = eventTypeExpected.value(); - event.type = eventType; - - ani_double time; - if (ANI_OK != env->Object_GetPropertyByName_Double(static_cast(arrayRef), "time", &time)) { - MISC_HILOGE("Failed to get property named time"); - return false; - } - event.time = static_cast(time); - - ani_double duration; - if (GetPropertyAsDouble(env, static_cast(arrayRef), "duration", &duration)) { - event.duration = static_cast(duration); - } - - ani_double intensity; - if (GetPropertyAsDouble(env, static_cast(arrayRef), "intensity", &intensity)) { - event.intensity = static_cast(intensity); - MISC_HILOGD("intensity: %{public}d", event.intensity); - } - - ani_double frequency; - if (GetPropertyAsDouble(env, static_cast(arrayRef), "frequency", &frequency)) { - event.frequency = static_cast(frequency); - MISC_HILOGD("frequency: %{public}d", event.frequency); - } - - ani_double aniIndex; - if (GetPropertyAsDouble(env, static_cast(arrayRef), "index", &aniIndex)) { - event.index = static_cast(aniIndex); - MISC_HILOGD("index: %{public}d", event.index); - } - - if (!ParsePointsArray(env, static_cast(arrayRef), event)) { - return false; - } - - return true; -} - -static void PrintVibratorPattern(VibratorPattern &vibratorPattern) -{ - CALL_LOG_ENTER; - if (vibratorPattern.events == nullptr) { - MISC_HILOGE("Events is nullptr"); - return; - } - MISC_HILOGD("PrintVibratorPattern, time:%{public}d, eventNum:%{public}d", - vibratorPattern.time, vibratorPattern.eventNum); - for (int32_t i = 0; i < vibratorPattern.eventNum; ++i) { - MISC_HILOGD("PrintVibratorPattern, type:%{public}d, time:%{public}d, duration:%{public}d, \ - intensity:%{public}d, frequency:%{public}d, index:%{public}d, pointNum:%{public}d", - static_cast(vibratorPattern.events[i].type), vibratorPattern.events[i].time, - vibratorPattern.events[i].duration, vibratorPattern.events[i].intensity, - vibratorPattern.events[i].frequency, vibratorPattern.events[i].index, vibratorPattern.events[i].pointNum); - if (vibratorPattern.events[i].pointNum > 0) { - VibratorCurvePoint *point = vibratorPattern.events[i].points; - for (int32_t j = 0; j < vibratorPattern.events[i].pointNum; ++j) { - MISC_HILOGD("PrintVibratorPattern, time:%{public}d, intensity:%{public}d, frequency:%{public}d", - point[j].time, point[j].intensity, point[j].frequency); - } - } - } -} - -static bool CheckVibratorCurvePoint(const VibratorEvent &event) -{ - if ((event.pointNum < CURVE_POINT_NUM_MIN) || (event.pointNum > CURVE_POINT_NUM_MAX)) { - MISC_HILOGE("The points size is out of range, pointNum:%{public}d", event.pointNum); - return false; - } - for (int32_t j = 0; j < event.pointNum; ++j) { - if ((event.points[j].time < 0) || (event.points[j].time > event.duration)) { - MISC_HILOGE("time in points is out of range, time:%{public}d", event.points[j].time); - return false; - } - if ((event.points[j].intensity < 0) || (event.points[j].intensity > CURVE_POINT_INTENSITY_MAX)) { - MISC_HILOGE("intensity in points is out of range, intensity:%{public}d", event.points[j].intensity); - return false; - } - if ((event.points[j].frequency < CURVE_FREQUENCY_MIN) || (event.points[j].frequency > CURVE_FREQUENCY_MAX)) { - MISC_HILOGE("frequency in points is out of range, frequency:%{public}d", event.points[j].frequency); - return false; - } - } - return true; -} - -static bool CheckVibratorEvent(const VibratorEvent &event) -{ - if ((event.time < 0) || (event.time > EVENT_START_TIME_MAX)) { - MISC_HILOGE("The event time is out of range, time:%{public}d", event.time); - return false; - } - if ((event.frequency < FREQUENCY_MIN) || (event.frequency > FREQUENCY_MAX)) { - MISC_HILOGE("The event frequency is out of range, frequency:%{public}d", event.frequency); - return false; - } - if ((event.intensity < INTENSITY_MIN) || (event.intensity > INTENSITY_MAX)) { - MISC_HILOGE("The event intensity is out of range, intensity:%{public}d", event.intensity); - return false; - } - if ((event.duration <= 0) || (event.duration > CONTINUOUS_DURATION_MAX)) { - MISC_HILOGE("The event duration is out of range, duration:%{public}d", event.duration); - return false; - } - if ((event.index < 0) || (event.index > EVENT_INDEX_MAX)) { - MISC_HILOGE("The event index is out of range, index:%{public}d", event.index); - return false; - } - if ((event.type == VibratorEventType::EVENT_TYPE_CONTINUOUS) && (event.pointNum > 0)) { - if (!CheckVibratorCurvePoint(event)) { - MISC_HILOGE("CheckVibratorCurvePoint failed"); - return false; - } - } - return true; -} - -static bool CheckVibratorPatternParameter(VibratorPattern &vibratorPattern) -{ - CALL_LOG_ENTER; - if (vibratorPattern.events == nullptr) { - MISC_HILOGE("Events is nullptr"); - return false; - } - if ((vibratorPattern.eventNum <= 0) || (vibratorPattern.eventNum > EVENT_NUM_MAX)) { - MISC_HILOGE("The event num is out of range, eventNum:%{public}d", vibratorPattern.eventNum); - return false; - } - for (int32_t i = 0; i < vibratorPattern.eventNum; ++i) { - if (!CheckVibratorEvent(vibratorPattern.events[i])) { - MISC_HILOGE("CheckVibratorEvent failed"); - return false; - } - } - return true; -} - -static bool ParseVibratorPatternEvents(ani_env *env, ani_object patternObj, VibratorPattern &pattern) -{ - ani_ref eventArray; - if (ANI_OK != env->Object_GetPropertyByName_Ref(static_cast(patternObj), "events", &eventArray)) { - MISC_HILOGE("Failed to get property named events"); - return false; - } - - ani_size size; - if (ANI_OK != env->Array_GetLength(static_cast(eventArray), &size)) { - MISC_HILOGE("Array_GetLength failed"); - return false; - } - - pattern.eventNum = static_cast(size); - MISC_HILOGD("ProcessVibratorPattern eventNum: %{public}d", pattern.eventNum); - - if (size <= 0 || size > EVENT_NUM_MAX) { - MISC_HILOGE("length should not be less than or equal to 0 or greater than EVENT_NUM_MAX"); - return false; - } - VibratorEvent *eventsAlloc = - static_cast(malloc(sizeof(VibratorEvent) * static_cast(size))); - if (eventsAlloc == nullptr) { - MISC_HILOGE("Events is nullptr"); - return false; - } - - for (uint32_t j = 0; j < size; ++j) { - new (&eventsAlloc[j]) VibratorEvent(); - if (!ParseVibrateEvent(env, static_cast(eventArray), j, eventsAlloc[j])) { - MISC_HILOGE("ParseVibrateEvent failed"); - free(eventsAlloc); - eventsAlloc = nullptr; - return false; - } - } - pattern.events = eventsAlloc; - return true; -} - -static bool ParserParamFromVibratePattern(ani_env *env, ani_object effect, VibrateInfo &vibrateInfo) -{ - MISC_HILOGD("ParserParamFromVibratePattern enter"); - ani_ref type; - if (ANI_OK != env->Object_GetPropertyByName_Ref(effect, "type", &type)) { - MISC_HILOGE("Failed to get property named type"); - return false; - } - auto typeStr = AniStringUtils::ToStd(env, static_cast(type)); - vibrateInfo.type = typeStr; - - ani_ref pattern; - if (ANI_OK != env->Object_GetPropertyByName_Ref(effect, "pattern", &pattern)) { - MISC_HILOGE("Failed to get property named pattern"); - return false; - } - - ani_double time; - if (ANI_OK != env->Object_GetPropertyByName_Double(static_cast(pattern), "time", &time)) { - MISC_HILOGE("Failed to get property named time"); - return false; - } - - vibrateInfo.vibratorPattern.time = static_cast(time); - MISC_HILOGD("ProcessVibratorPattern time: %{public}d", vibrateInfo.vibratorPattern.time); - - if (!ParseVibratorPatternEvents(env, static_cast(pattern), vibrateInfo.vibratorPattern)) { - return false; - } - - PrintVibratorPattern(vibrateInfo.vibratorPattern); - - if (!CheckVibratorPatternParameter(vibrateInfo.vibratorPattern)) { - MISC_HILOGE("CheckVibratorPatternParameter fail"); - return false; - } - return true; -} - -bool SetUsage(const std::string &usage, bool systemUsage) -{ - if (auto iter = g_usageType.find(usage); iter == g_usageType.end()) { - MISC_HILOGE("Wrong usage type"); - return false; - } - return SetUsage(g_usageType[usage], systemUsage); -} - -static int32_t StartVibrate(const VibrateInfo &info) -{ - if (!SetUsage(info.usage, info.systemUsage)) { - MISC_HILOGE("SetUsage fail"); - return PARAMETER_ERROR; - } - if (g_allowedTypes.find(info.type) == g_allowedTypes.end()) { - MISC_HILOGE("Invalid vibrate type, type:%{public}s", info.type.c_str()); - return PARAMETER_ERROR; - } - if (info.type == "preset") { - if (!SetLoopCount(info.count)) { - MISC_HILOGE("SetLoopCount fail"); - return PARAMETER_ERROR; - } - return PlayPrimitiveEffect(info.effectId.c_str(), info.intensity); - } else if (info.type == "file") { - return PlayVibratorCustom(info.fd, info.offset, info.length); - } else if (info.type == "pattern") { - return PlayPattern(info.vibratorPattern); - } - return StartVibratorOnce(info.duration); -} - -static ani_class FindClassInNamespace(ani_env *env, ani_namespace &ns, const char *className) -{ - ani_class cls; - if (ANI_OK != env->Namespace_FindClass(ns, className, &cls)) { - MISC_HILOGE("Not found '%{public}s'", className); - return nullptr; - } - return cls; -} - -static bool ParseEffectTypeAndParameters(ani_env *env, ani_object effect, VibrateInfo &vibrateInfo) -{ - ani_namespace ns; - static const char *namespaceName = "L@ohos/vibrator/vibrator;"; - if (ANI_OK != env->FindNamespace(namespaceName, &ns)) { - MISC_HILOGE("Not found '%{public}s'", namespaceName); - return false; - } - - ani_class vibrateTimeClass = FindClassInNamespace(env, ns, "LVibrateTime;"); - ani_class vibratePresetClass = FindClassInNamespace(env, ns, "LVibratePreset;"); - ani_class vibrateFromFileClass = FindClassInNamespace(env, ns, "LVibrateFromFile;"); - ani_class vibratePatternClass = FindClassInNamespace(env, ns, "LVibrateFromPattern;"); - if (!vibrateTimeClass || !vibratePresetClass || !vibrateFromFileClass || !vibratePatternClass) { - return false; - } - - ani_boolean isInstanceOfTime = ANI_FALSE; - env->Object_InstanceOf(effect, vibrateTimeClass, &isInstanceOfTime); - ani_boolean isInstanceOfPreset = ANI_FALSE; - env->Object_InstanceOf(effect, vibratePresetClass, &isInstanceOfPreset); - ani_boolean isInstanceOfFile = ANI_FALSE; - env->Object_InstanceOf(effect, vibrateFromFileClass, &isInstanceOfFile); - ani_boolean isInstanceOfPattern = ANI_FALSE; - env->Object_InstanceOf(effect, vibratePatternClass, &isInstanceOfPattern); - - if (isInstanceOfTime) { - if (!ParserParamFromVibrateTime(env, effect, vibrateInfo)) { - ThrowBusinessError(env, PARAMETER_ERROR, "ParserParamFromVibrateTime failed!"); - return false; - } - } else if (isInstanceOfPreset) { - if (!ParserParamFromVibratePreset(env, effect, vibrateInfo)) { - ThrowBusinessError(env, PARAMETER_ERROR, "ParserParamFromVibratePreset failed!"); - return false; - } - } else if (isInstanceOfFile) { - if (!ParserParamFromVibrateFromFile(env, effect, vibrateInfo)) { - ThrowBusinessError(env, PARAMETER_ERROR, "ParserParamFromVibrateFromFile failed!"); - return false; - } - } else if (isInstanceOfPattern) { - if (!ParserParamFromVibratePattern(env, effect, vibrateInfo)) { - ThrowBusinessError(env, PARAMETER_ERROR, "ParserParamFromVibratePattern failed!"); - return false; - } - } else { - ThrowBusinessError(env, PARAMETER_ERROR, "Unknown effect type"); - return false; - } - - return true; -} - -static void StartVibrationSync([[maybe_unused]] ani_env *env, ani_object effect, ani_object attribute) -{ - ani_namespace ns; - static const char *namespaceName = "L@ohos/vibrator/vibrator;"; - if (ANI_OK != env->FindNamespace(namespaceName, &ns)) { - MISC_HILOGE("Not found '%{public}s'", namespaceName); - return; - } - - ani_class vibrateAttributeClass = FindClassInNamespace(env, ns, "LVibrateAttribute;"); - if (!vibrateAttributeClass) { - return; - } - - VibrateInfo vibrateInfo; - if (!ParseEffectTypeAndParameters(env, effect, vibrateInfo)) { - return; - } - if (!ParserParamFromVibrateAttribute(env, attribute, vibrateInfo)) { - ThrowBusinessError(env, PARAMETER_ERROR, "ParserParamFromVibrateAttribute failed!"); - return; - } - StartVibrate(vibrateInfo); -} - -static bool IsSupportEffectInterally([[maybe_unused]] ani_env *env, ani_string effectId) -{ - auto effectIdStr = AniStringUtils::ToStd(env, static_cast(effectId)); - MISC_HILOGD("effectId:%{public}s", effectIdStr.c_str()); - - bool isSupportEffect = false; - if (IsSupportEffect(effectIdStr.c_str(), &isSupportEffect) != 0) { - MISC_HILOGE("Query effect support failed"); - } - return isSupportEffect; -} - -ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) -{ - ani_env *env; - if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { - MISC_HILOGE("Unsupported ANI_VERSION_1"); - return ANI_ERROR; - } - - static const char *namespaceName = "L@ohos/vibrator/vibrator;"; - ani_namespace ns; - if (ANI_OK != env->FindNamespace(namespaceName, &ns)) { - MISC_HILOGE("Not found '%{public}s'", namespaceName); - return ANI_NOT_FOUND; - } - - std::array methods = { - ani_native_function {"startVibrationSync", nullptr, reinterpret_cast(StartVibrationSync)}, - ani_native_function {"isSupportEffectInterally", nullptr, reinterpret_cast(IsSupportEffectInterally)}, - }; - - if (ANI_OK != env->Namespace_BindNativeFunctions(ns, methods.data(), methods.size())) { - MISC_HILOGE("Cannot bind native methods to '%{public}s'", namespaceName); - return ANI_NOT_FOUND; - }; - - *result = ANI_VERSION_1; - return ANI_OK; -} \ No newline at end of file -- Gitee