* 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 <ani.h>
#include <array>
#include <iostream>
#include <sstream>
#include <vector>
#include <charconv>
#include "hilog_wrapper.h"
#include "ani_utils.h"
#include <ani_signature_builder.h>
using namespace OHOS::Accessibility;
using namespace arkts::ani_signature;
constexpr const char* CLASSNAME_DOUBLE = "std.core.Double";
const std::string HALF_VALUE = "0";
const std::string FULL_VALUE = "1";
std::string ANIUtils::ANIStringToStdString(ani_env *env, ani_string ani_str)
{
ani_size strSize;
env->String_GetUTF8Size(ani_str, &strSize);
std::vector<char> buffer(strSize + 1);
char* utf8_buffer = buffer.data();
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;
}
ani_string ANIUtils::StdStringToAniString(ani_env *env, std::string str)
{
ani_string result_string{};
env->String_NewUTF8(str.c_str(), str.size(), &result_string);
return result_string;
}
bool ANIUtils::GetStringField(ani_env *env, std::string fieldName, ani_object object, std::string &fieldValue,
bool isProperty)
{
ani_ref ref;
if (isProperty) {
if (env->Object_GetPropertyByName_Ref(object, fieldName.c_str(), &ref) != ANI_OK) {
HILOG_ERROR("get field %{public}s failed", fieldName.c_str());
return false;
}
fieldValue = ANIStringToStdString(env, static_cast<ani_string>(ref));
return true;
}
if (env->Object_GetFieldByName_Ref(object, fieldName.c_str(), &ref) != ANI_OK) {
HILOG_ERROR("get field %{public}s failed", fieldName.c_str());
return false;
}
ani_boolean isUndefined;
if (env->Reference_IsUndefined(ref, &isUndefined) != ANI_OK) {
HILOG_ERROR("get field %{public}s undefined failed", fieldName.c_str());
return false;
}
if (!isUndefined) {
fieldValue = ANIStringToStdString(env, static_cast<ani_string>(ref));
return true;
}
return false;
}
bool ANIUtils::GetBoolField(ani_env *env, std::string fieldName, ani_object object, bool &fieldValue)
{
ani_boolean booleanValue;
if (env->Object_GetPropertyByName_Boolean(object, fieldName.c_str(), &booleanValue) != ANI_OK) {
HILOG_ERROR("get field %{public}s failed", fieldName.c_str());
return false;
}
fieldValue = static_cast<bool>(booleanValue);
return false;
}
bool ANIUtils::GetIntField(ani_env *env, std::string fieldName, ani_object object, int32_t &fieldValue)
{
ani_ref ref;
if (env->Object_GetFieldByName_Ref(object, fieldName.c_str(), &ref) != ANI_OK) {
HILOG_ERROR("get field %{public}s failed", fieldName.c_str());
return false;
}
ani_boolean isUndefined;
if (env->Reference_IsUndefined(ref, &isUndefined) != ANI_OK) {
HILOG_ERROR("get field %{public}s undefined failed", fieldName.c_str());
return false;
}
if (!isUndefined) {
if (env->Object_CallMethodByName_Int(static_cast<ani_object>(ref), "toInt", nullptr, &fieldValue) ==
ANI_OK) {
return true;
}
}
return false;
}
bool ANIUtils::GetLongProperty(ani_env *env, std::string fieldName, ani_object object, int64_t &fieldValue)
{
ani_long longValue;
if (env->Object_GetPropertyByName_Long(object, fieldName.c_str(), &longValue) != ANI_OK) {
HILOG_ERROR("get field %{public}s failed", fieldName.c_str());
return false;
}
fieldValue = static_cast<int64_t>(longValue);
return true;
}
bool ANIUtils::GetArrayStringField(ani_env *env, std::string fieldName, ani_object object,
std::vector<std::string> &fieldValue)
{
ani_ref ref;
if (env->Object_GetFieldByName_Ref(object, fieldName.c_str(), &ref) != ANI_OK) {
HILOG_ERROR("get field %{public}s failed", fieldName.c_str());
return false;
}
ani_boolean isUndefined;
if (env->Reference_IsUndefined(ref, &isUndefined) != ANI_OK) {
HILOG_ERROR("get field %{public}s undefined failed", fieldName.c_str());
return false;
}
if (isUndefined) {
return false;
}
fieldValue.clear();
if (!ParseStringArray(env, static_cast<ani_object>(ref), fieldValue)) {
HILOG_ERROR("ParseStringArray fail");
return false;
}
return true;
}
bool ANIUtils::SetLongPropertyRef(ani_env *env, ani_object &object, const std::string &propName, int64_t propValue)
{
if (env == nullptr) {
HILOG_ERROR("SetLongField null env");
return false;
}
ani_object value;
if (CreateAniLong(env, propValue, value) != ANI_OK) {
HILOG_ERROR("CreateAniLong failed");
return false;
}
ani_status status;
if ((status = env->Object_SetPropertyByName_Ref(object, propName.c_str(), value)) != ANI_OK) {
HILOG_ERROR("set long field failed %{public}s %{public}d", propName.c_str(), status);
return false;
}
return true;
}
bool ANIUtils::SetStringProperty(ani_env *env, ani_object ¶m, const std::string &name, const std::string &value)
{
if (env == nullptr) {
HILOG_ERROR("SetStringProperty null env");
return false;
}
ani_string string = nullptr;
ani_status status;
if (value.empty()) {
ani_ref nullRef = nullptr;
if ((status = env->GetNull(&nullRef)) != ANI_OK) {
HILOG_ERROR("get null status : %{public}d", status);
return false;
}
if ((status = env->Object_SetPropertyByName_Ref(param, name.c_str(), nullRef)) != ANI_OK) {
HILOG_ERROR("set null status : %{public}d", status);
return false;
}
return true;
}
if ((status = env->String_NewUTF8(value.c_str(), value.size(), &string)) != ANI_OK) {
HILOG_ERROR("change to ani string status : %{public}d", status);
return false;
}
if ((status = env->Object_SetPropertyByName_Ref(param, name.c_str(), string)) != ANI_OK) {
HILOG_ERROR("set ref status : %{public}d", status);
return false;
}
return true;
}
bool ANIUtils::SetStringArrayProperty(ani_env *env, ani_object &object, const std::string &name,
const std::vector<std::string> &values)
{
ani_array arrayObj = CreateEmptyAniArray(env, values.size());
if (arrayObj == nullptr) {
HILOG_ERROR("SetStringArrayProperty array is null");
return false;
}
ani_size index = 0;
for (auto &str : values) {
if (env->Array_Set(arrayObj, index, StdStringToAniString(env, str)) != ANI_OK) {
HILOG_ERROR("Object_CallMethodByName_Void failed name=%{public}s index=%{public}zu str=%{public}s",
name.c_str(), index, str.c_str());
return false;
}
index++;
}
ani_status status = env->Object_SetPropertyByName_Ref(object, name.c_str(), arrayObj);
if (status != ANI_OK) {
HILOG_ERROR("status : %{public}d", status);
return false;
}
return true;
}
ani_array ANIUtils::CreateEmptyAniArray(ani_env *env, uint32_t size)
{
if (env == nullptr) {
HILOG_ERROR("create ani array env is null");
return nullptr;
}
ani_ref undefinedRef = nullptr;
if (env->GetUndefined(&undefinedRef) != ANI_OK) {
HILOG_ERROR("GetUndefined Failed.");
}
ani_array resultArray;
env->Array_New(size, undefinedRef, &resultArray);
return resultArray;
}
bool ANIUtils::GetEnumInt(ani_env *env, const char *enum_descriptor, ani_int enumIndex, int32_t& fieldValue)
{
HILOG_INFO("processEnumInt enum=%{public}s, index=%{public}d", enum_descriptor, enumIndex);
ani_enum enumType;
if (ANI_OK != env->FindEnum(enum_descriptor, &enumType)) {
HILOG_ERROR("Find Enum Failed");
return false;
}
ani_enum_item enumItem;
if (ANI_OK != env->Enum_GetEnumItemByIndex(enumType, enumIndex, &enumItem)) {
HILOG_ERROR("Enum_GetEnumItemByIndex FAILED");
return false;
}
if (ANI_OK != env->EnumItem_GetValue_Int(enumItem, &fieldValue)) {
HILOG_ERROR("Enum_GetEnumItemByIndex FAILED");
return false;
}
return true;
}
bool ANIUtils::CheckObserverEqual(ani_env *env, ani_ref fnRef, ani_env *iterEnv, ani_ref iterFn)
{
if (env != iterEnv) {
HILOG_DEBUG("not the same env");
return false;
}
ani_boolean isEquals = false;
if (env->Reference_StrictEquals(fnRef, iterFn, &isEquals) != ANI_OK) {
HILOG_ERROR("check observer equal failed!");
return false;
}
return isEquals;
}
EventType ANIUtils::ConvertStringToEventInfoTypes(const std::string &type)
{
static const std::map<const std::string, EventType> eventInfoTypesTable = {
{"click", EventType::TYPE_VIEW_CLICKED_EVENT},
{"longClick", EventType::TYPE_VIEW_LONG_CLICKED_EVENT},
{"select", EventType::TYPE_VIEW_SELECTED_EVENT},
{"focus", EventType::TYPE_VIEW_FOCUSED_EVENT},
{"textUpdate", EventType::TYPE_VIEW_TEXT_UPDATE_EVENT},
{"hoverEnter", EventType::TYPE_VIEW_HOVER_ENTER_EVENT},
{"hoverExit", EventType::TYPE_VIEW_HOVER_EXIT_EVENT},
{"scroll", EventType::TYPE_VIEW_SCROLLED_EVENT},
{"textSelectionUpdate", EventType::TYPE_VIEW_TEXT_SELECTION_UPDATE_EVENT},
{"accessibilityFocus", EventType::TYPE_VIEW_ACCESSIBILITY_FOCUSED_EVENT},
{"accessibilityFocusClear", EventType::TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED_EVENT},
{"requestFocusForAccessibility", EventType::TYPE_VIEW_REQUEST_FOCUS_FOR_ACCESSIBILITY},
{"requestFocusForAccessibilityNotInterrupt",
EventType::TYPE_VIEW_REQUEST_FOCUS_FOR_ACCESSIBILITY_NOT_INTERRUPT},
{"announceForAccessibility", EventType::TYPE_VIEW_ANNOUNCE_FOR_ACCESSIBILITY},
{"announceForAccessibilityNotInterrupt", EventType::TYPE_VIEW_ANNOUNCE_FOR_ACCESSIBILITY_NOT_INTERRUPT},
{"scrolling", EventType::TYPE_VIEW_SCROLLING_EVENT},
{"pageActive", EventType::TYPE_PAGE_ACTIVE},
{"notificationUpdate", EventType::TYPE_NOTIFICATION_UPDATE_EVENT},
{"focusInvisible", EventType::TYPE_FOCUS_INVISIBLE}};
if (eventInfoTypesTable.find(type) == eventInfoTypesTable.end()) {
HILOG_WARN("invalid key[%{public}s]", type.c_str());
return TYPE_VIEW_INVALID;
}
return eventInfoTypesTable.at(type);
}
ActionType ANIUtils::ConvertStringToAccessibleOperationType(const std::string &type)
{
std::map<const std::string, ActionType> accessibleOperationTypeTable = {
{"focus", ActionType::ACCESSIBILITY_ACTION_FOCUS},
{"clearFocus", ActionType::ACCESSIBILITY_ACTION_CLEAR_FOCUS},
{"select", ActionType::ACCESSIBILITY_ACTION_SELECT},
{"clearSelection", ActionType::ACCESSIBILITY_ACTION_CLEAR_SELECTION},
{"click", ActionType::ACCESSIBILITY_ACTION_CLICK},
{"longClick", ActionType::ACCESSIBILITY_ACTION_LONG_CLICK},
{"accessibilityFocus", ActionType::ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS},
{"clearAccessibilityFocus", ActionType::ACCESSIBILITY_ACTION_CLEAR_ACCESSIBILITY_FOCUS},
{"scrollForward", ActionType::ACCESSIBILITY_ACTION_SCROLL_FORWARD},
{"scrollBackward", ActionType::ACCESSIBILITY_ACTION_SCROLL_BACKWARD},
{"copy", ActionType::ACCESSIBILITY_ACTION_COPY},
{"paste", ActionType::ACCESSIBILITY_ACTION_PASTE},
{"cut", ActionType::ACCESSIBILITY_ACTION_CUT},
{"setSelection", ActionType::ACCESSIBILITY_ACTION_SET_SELECTION},
{"setCursorPosition", ActionType::ACCESSIBILITY_ACTION_SET_CURSOR_POSITION},
{"common", ActionType::ACCESSIBILITY_ACTION_COMMON},
{"setText", ActionType::ACCESSIBILITY_ACTION_SET_TEXT},
{"delete", ActionType::ACCESSIBILITY_ACTION_DELETED},
{"home", ActionType::ACCESSIBILITY_ACTION_HOME},
{"back", ActionType::ACCESSIBILITY_ACTION_BACK},
{"recentTask", ActionType::ACCESSIBILITY_ACTION_RECENTTASK},
{"notificationCenter", ActionType::ACCESSIBILITY_ACTION_NOTIFICATIONCENTER},
{"controlCenter", ActionType::ACCESSIBILITY_ACTION_CONTROLCENTER},
{"injectAction", ActionType::ACCESSIBILITY_ACTION_INJECT_ACTION},
{"executeCustomAction", ActionType::ACCESSIBILITY_ACTION_CUSTOM}
};
if (accessibleOperationTypeTable.find(type) == accessibleOperationTypeTable.end()) {
HILOG_WARN("invalid key[%{public}s]", type.c_str());
return ACCESSIBILITY_ACTION_INVALID;
}
return accessibleOperationTypeTable.at(type);
}
WindowUpdateType ANIUtils::ConvertStringToWindowUpdateTypes(const std::string &type)
{
static const std::map<const std::string, WindowUpdateType> windowsUpdateTypesTable = {
{"accessibilityFocus", WindowUpdateType::WINDOW_UPDATE_ACCESSIBILITY_FOCUSED},
{"focus", WindowUpdateType::WINDOW_UPDATE_FOCUSED},
{"active", WindowUpdateType::WINDOW_UPDATE_ACTIVE},
{"add", WindowUpdateType::WINDOW_UPDATE_ADDED},
{"remove", WindowUpdateType::WINDOW_UPDATE_REMOVED},
{"bounds", WindowUpdateType::WINDOW_UPDATE_BOUNDS},
{"title", WindowUpdateType::WINDOW_UPDATE_TITLE},
{"layer", WindowUpdateType::WINDOW_UPDATE_LAYER},
{"parent", WindowUpdateType::WINDOW_UPDATE_PARENT},
{"children", WindowUpdateType::WINDOW_UPDATE_CHILDREN},
{"pip", WindowUpdateType::WINDOW_UPDATE_PIP},
{"property", WindowUpdateType::WINDOW_UPDATE_PROPERTY}};
if (windowsUpdateTypesTable.find(type) == windowsUpdateTypesTable.end()) {
HILOG_WARN("invalid key[%{public}s]", type.c_str());
return WINDOW_UPDATE_INVALID;
}
return windowsUpdateTypesTable.at(type);
}
TextMoveUnit ANIUtils::ConvertStringToTextMoveUnit(const std::string &type)
{
static const std::map<const std::string, TextMoveUnit> textMoveUnitTable = {{"char", TextMoveUnit::STEP_CHARACTER},
{"word", TextMoveUnit::STEP_WORD},
{"line", TextMoveUnit::STEP_LINE},
{"page", TextMoveUnit::STEP_PAGE},
{"paragraph", TextMoveUnit::STEP_PARAGRAPH}};
if (textMoveUnitTable.find(type) == textMoveUnitTable.end()) {
HILOG_WARN("invalid key[%{public}s]", type.c_str());
return STEP_INVALID;
}
return textMoveUnitTable.at(type);
}
NAccessibilityErrMsg ANIUtils::QueryRetMsg(RetError errorCode)
{
switch (errorCode) {
case RetError::RET_OK:
return { NAccessibilityErrorCode::ACCESSIBILITY_OK, "" };
case RetError::RET_ERR_FAILED:
return { NAccessibilityErrorCode::ACCESSIBILITY_ERROR_SYSTEM_ABNORMALITY,
ERROR_MESSAGE_SYSTEM_ABNORMALITY_FAILED };
case RetError::RET_ERR_NULLPTR:
return { NAccessibilityErrorCode::ACCESSIBILITY_ERROR_SYSTEM_ABNORMALITY,
ERROR_MESSAGE_SYSTEM_ABNORMALITY_NULLPTR };
case RetError::RET_ERR_IPC_FAILED:
return { NAccessibilityErrorCode::ACCESSIBILITY_ERROR_SYSTEM_ABNORMALITY,
ERROR_MESSAGE_SYSTEM_ABNORMALITY_IPC_FAILED };
case RetError::RET_ERR_SAMGR:
return { NAccessibilityErrorCode::ACCESSIBILITY_ERROR_SYSTEM_ABNORMALITY,
ERROR_MESSAGE_SYSTEM_ABNORMALITY_SAMGR };
case RetError::RET_ERR_TIME_OUT:
return { NAccessibilityErrorCode::ACCESSIBILITY_ERROR_SYSTEM_ABNORMALITY,
ERROR_MESSAGE_SYSTEM_ABNORMALITY_TIMEOUT };
case RetError::RET_ERR_REGISTER_EXIST:
return { NAccessibilityErrorCode::ACCESSIBILITY_ERROR_SYSTEM_ABNORMALITY,
ERROR_MESSAGE_SYSTEM_ABNORMALITY_REGISTER_EXIST };
case RetError::RET_ERR_NO_REGISTER:
return { NAccessibilityErrorCode::ACCESSIBILITY_ERROR_SYSTEM_ABNORMALITY,
ERROR_MESSAGE_SYSTEM_ABNORMALITY_NO_REGISTER };
case RetError::RET_ERR_NO_CONNECTION:
return { NAccessibilityErrorCode::ACCESSIBILITY_ERROR_SYSTEM_ABNORMALITY,
ERROR_MESSAGE_SYSTEM_ABNORMALITY_NO_CONNECTION };
case RetError::RET_ERR_NO_WINDOW_CONNECTION:
return { NAccessibilityErrorCode::ACCESSIBILITY_ERROR_SYSTEM_ABNORMALITY,
ERROR_MESSAGE_SYSTEM_ABNORMALITY_NO_WINDOW_CONNECTION };
case RetError::RET_ERR_INVALID_ELEMENT_INFO_FROM_ACE:
return { NAccessibilityErrorCode::ACCESSIBILITY_ERROR_SYSTEM_ABNORMALITY,
ERROR_MESSAGE_SYSTEM_ABNORMALITY_INVALID_ELEMENT_INFO };
case RetError::RET_ERR_PERFORM_ACTION_FAILED_BY_ACE:
return { NAccessibilityErrorCode::ACCESSIBILITY_ERROR_SYSTEM_ABNORMALITY,
ERROR_MESSAGE_SYSTEM_ABNORMALITY_PERFORM_ACTION_FAILED };
case RetError::RET_ERR_NO_INJECTOR:
return { NAccessibilityErrorCode::ACCESSIBILITY_ERROR_SYSTEM_ABNORMALITY,
ERROR_MESSAGE_SYSTEM_ABNORMALITY_NO_INJECTOR };
case RetError::RET_ERR_INVALID_PARAM:
return { NAccessibilityErrorCode::ACCESSIBILITY_ERROR_INVALID_PARAM, ERROR_MESSAGE_PARAMETER_ERROR };
case RetError::RET_ERR_NO_PERMISSION:
return { NAccessibilityErrorCode::ACCESSIBILITY_ERROR_NO_PERMISSION, ERROR_MESSAGE_NO_PERMISSION };
case RetError::RET_ERR_CONNECTION_EXIST:
return { NAccessibilityErrorCode::ACCESSIBILITY_ERROR_TARGET_ABILITY_ALREADY_ENABLED,
ERROR_MESSAGE_TARGET_ABILITY_ALREADY_ENABLED };
case RetError::RET_ERR_NO_CAPABILITY:
return { NAccessibilityErrorCode::ACCESSIBILITY_ERROR_NO_RIGHT, ERROR_MESSAGE_NO_RIGHT };
case RetError::RET_ERR_NOT_INSTALLED:
return { NAccessibilityErrorCode::ACCESSIBILITY_ERROR_ERROR_EXTENSION_NAME,
ERROR_MESSAGE_EXTENSION_NOT_INSTALLED };
case RetError::RET_ERR_NOT_ENABLED:
return { NAccessibilityErrorCode::ACCESSIBILITY_ERROR_ERROR_EXTENSION_NAME,
ERROR_MESSAGE_EXTENSION_NOT_ENABLED };
case RetError::RET_ERR_PROPERTY_NOT_EXIST:
return { NAccessibilityErrorCode::ACCESSIBILITY_ERROR_PROPERTY_NOT_EXIST,
ERROR_MESSAGE_PROPERTY_NOT_EXIST };
case RetError::RET_ERR_ACTION_NOT_SUPPORT:
return { NAccessibilityErrorCode::ACCESSIBILITY_ERROR_ACTION_NOT_SUPPORT,
ERROR_MESSAGE_ACTION_NOT_SUPPORT };
case RetError::RET_ERR_NOT_SYSTEM_APP:
return { NAccessibilityErrorCode::ACCESSIBILITY_ERROR_NOT_SYSTEM_APP,
ERROR_MESSAGE_NOT_SYSTEM_APP };
case OHOS::Accessibility::RetError::RET_ERR_INVILID_APPINDEX:
return { NAccessibilityErrorCode::ACCESSIBILITY_ERROR_INVILID_APPINDEX,
ERROR_MESSAGE_INVILID_APPINDEX };
default:
return { NAccessibilityErrorCode::ACCESSIBILITY_ERROR_SYSTEM_ABNORMALITY,
ERROR_MESSAGE_SYSTEM_ABNORMALITY };
}
}
void ANIUtils::ThrowBusinessError(ani_env *env, NAccessibilityErrMsg errMsg)
{
Type errorClass = Builder::BuildClass("@ohos.base.BusinessError");
ani_class cls {};
if (env->FindClass(errorClass.Descriptor().c_str(), &cls) != ANI_OK) {
HILOG_ERROR("find class BusinessError failed");
return;
}
ani_method ctor;
std::string ctorName = Builder::BuildConstructorName();
SignatureBuilder sb{};
if (env->Class_FindMethod(cls, ctorName.c_str(), sb.BuildSignatureDescriptor().c_str(), &ctor) != ANI_OK) {
HILOG_ERROR("find method BusinessError.constructor failed");
return;
}
ani_int errCode = static_cast<ani_int>(errMsg.errCode);
ani_string errMsgStr;
env->String_NewUTF8(errMsg.message.c_str(), errMsg.message.length(), &errMsgStr);
ani_object errorObject;
if (env->Object_New(cls, ctor, &errorObject) != ANI_OK) {
HILOG_ERROR("create BusinessError object failed");
return;
}
if (env->Object_SetPropertyByName_Int(errorObject, "code", errCode) != ANI_OK) {
HILOG_ERROR("set property BusinessError.code failed!");
return;
}
if (env->Object_SetPropertyByName_Ref(errorObject, "message", static_cast<ani_ref>(errMsgStr)) != ANI_OK) {
HILOG_ERROR("set property BusinessError.message failed!");
return;
}
if (env->ThrowError(static_cast<ani_error>(errorObject)) != ANI_OK) {
HILOG_ERROR("throw BusinessError failed!");
return;
}
HILOG_INFO("throw BusinessError success!");
return;
}
ani_string ANIUtils::CreateAniString(ani_env *env, const std::string &str)
{
ani_string aniString {};
if (env != nullptr) {
env->String_NewUTF8(str.c_str(), str.size(), &aniString);
}
return aniString;
}
ani_object ANIUtils::CreateBoolObject(ani_env *env, ani_boolean value)
{
Type boolClass = Builder::BuildClass("std.core.Boolean");
ani_class cls {};
if (env->FindClass(boolClass.Descriptor().c_str(), &cls) != ANI_OK) {
HILOG_ERROR("find class Boolean failed");
return nullptr;
}
ani_method ctor;
std::string ctorName = Builder::BuildConstructorName();
SignatureBuilder sb{};
sb.AddBoolean();
if (env->Class_FindMethod(cls, ctorName.c_str(), sb.BuildSignatureDescriptor().c_str(), &ctor) != ANI_OK) {
HILOG_ERROR("find method Boolean.constructor failed");
return nullptr;
}
ani_object boolObject;
if (env->Object_New(cls, ctor, &boolObject, value) != ANI_OK) {
HILOG_ERROR("create Boolean object failed");
return nullptr;
}
return boolObject;
}
bool ANIUtils::ConvertEventInfoMandatoryFields(ani_env *env, ani_object eventObject,
AccessibilityEventInfo &eventInfo)
{
std::string type;
if (!GetStringField(env, "type", eventObject, type)) {
HILOG_ERROR("get type Failed!");
return false;
}
OHOS::Accessibility::EventType eventType = ConvertStringToEventInfoTypes(type);
if (eventType == TYPE_VIEW_INVALID) {
HILOG_ERROR("event type is invalid!");
return false;
}
eventInfo.SetEventType(eventType);
std::string bundleName;
if (!GetStringField(env, "bundleName", eventObject, bundleName)) {
HILOG_ERROR("get bundleName Failed!");
return false;
}
if (bundleName == "") {
HILOG_ERROR("bundle name is invalid!");
return false;
}
eventInfo.SetBundleName(bundleName);
std::string triggerAction;
if (!GetStringField(env, "triggerAction", eventObject, triggerAction)) {
HILOG_ERROR("get triggerAction Failed!");
return false;
}
OHOS::Accessibility::ActionType action = ConvertStringToAccessibleOperationType(triggerAction);
if (action == ACCESSIBILITY_ACTION_INVALID) {
HILOG_ERROR("action is invalid!");
return false;
}
eventInfo.SetTriggerAction(action);
return true;
}
void ANIUtils::ConvertEventInfoStringFields(ani_env *env, ani_object eventObject,
OHOS::Accessibility::AccessibilityEventInfo &eventInfo)
{
std::string windowUpdateType;
if (GetStringField(env, "windowUpdateType", eventObject, windowUpdateType)) {
eventInfo.SetEventType(TYPE_WINDOW_UPDATE);
eventInfo.SetWindowChangeTypes(ConvertStringToWindowUpdateTypes(windowUpdateType));
}
std::string componentType;
if (GetStringField(env, "componentType", eventObject, componentType)) {
eventInfo.SetComponentType(componentType);
}
std::string description;
if (GetStringField(env, "description", eventObject, description)) {
eventInfo.SetDescription(description);
}
std::string textMoveUnit;
if (GetStringField(env, "textMoveUnit", eventObject, textMoveUnit)) {
eventInfo.SetTextMovementStep(ConvertStringToTextMoveUnit(textMoveUnit));
}
std::vector<std::string> contents;
if (GetArrayStringField(env, "contents", eventObject, contents)) {
for (auto str : contents) {
eventInfo.AddContent(str);
}
}
std::string lastContent;
if (GetStringField(env, "lastContent", eventObject, lastContent)) {
eventInfo.SetLatestContent(lastContent);
}
std::string textAnnouncedForAccessibility;
if (GetStringField(env, "textAnnouncedForAccessibility", eventObject, textAnnouncedForAccessibility)) {
eventInfo.SetTextAnnouncedForAccessibility(textAnnouncedForAccessibility);
}
std::string customId;
if (GetStringField(env, "customId", eventObject, customId)) {
eventInfo.SetInspectorKey(customId);
}
std::string triggerAction;
if (GetStringField(env, "triggerAction", eventObject, triggerAction)) {
eventInfo.SetTriggerAction(ConvertStringToAccessibleOperationType(triggerAction));
}
}
void ANIUtils::ConvertEventInfoIntFields(ani_env *env, ani_object eventObject,
OHOS::Accessibility::AccessibilityEventInfo &eventInfo)
{
int32_t pageId;
if (GetIntField(env, "pageId", eventObject, pageId)) {
eventInfo.SetPageId(pageId);
}
int32_t beginIndex;
if (GetIntField(env, "beginIndex", eventObject, beginIndex)) {
eventInfo.SetBeginIndex(beginIndex);
}
int32_t currentIndex;
if (GetIntField(env, "currentIndex", eventObject, currentIndex)) {
eventInfo.SetCurrentIndex(currentIndex);
}
int32_t endIndex;
if (GetIntField(env, "endIndex", eventObject, endIndex)) {
eventInfo.SetEndIndex(endIndex);
}
int32_t itemCount;
if (GetIntField(env, "itemCount", eventObject, itemCount)) {
eventInfo.SetItemCounts(itemCount);
}
int32_t elementId;
if (GetIntField(env, "elementId", eventObject, elementId)) {
eventInfo.SetRequestFocusElementId(elementId);
}
}
void ANIUtils::ConvertEventInfoRefFields(ani_env *env, ani_object eventObject,
OHOS::Accessibility::AccessibilityEventInfo &eventInfo)
{
ani_ref ref;
if (env->Object_GetFieldByName_Ref(eventObject, "textResourceAnnouncedForAccessibility", &ref) != ANI_OK) {
HILOG_ERROR("get field textResourceAnnouncedForAccessibility failed");
return;
}
ani_boolean isUndefined;
if (env->Reference_IsUndefined(ref, &isUndefined) != ANI_OK) {
HILOG_ERROR("get field textResourceAnnouncedForAccessibility undefined failed");
return;
}
if (isUndefined) {
return;
}
int64_t id;
if (!GetLongProperty(env, "id", static_cast<ani_object>(ref), id)) {
return;
}
std::string bundleName;
if (!GetStringField(env, "bundleName", static_cast<ani_object>(ref), bundleName, true)) {
return;
}
std::string moduleName;
if (!GetStringField(env, "moduleName", static_cast<ani_object>(ref), moduleName, true)) {
return;
}
eventInfo.SetResourceId(id);
eventInfo.SetResourceBundleName(bundleName);
eventInfo.SetResourceModuleName(moduleName);
HILOG_DEBUG("resourceId is %{public}" PRId64 ", bundleName is %{public}s, moduleName is %{public}s",
id, bundleName.c_str(), moduleName.c_str());
}
bool ANIUtils::SendEventToMainThread(const std::function<void()> func)
{
if (func == nullptr) {
HILOG_ERROR("func is nullptr!");
return false;
}
if (!mainHandler) {
std::shared_ptr<OHOS::AppExecFwk::EventRunner> runner = OHOS::AppExecFwk::EventRunner::GetMainEventRunner();
if (!runner) {
HILOG_ERROR("get main event runner failed!");
return false;
}
mainHandler = std::make_shared<OHOS::AppExecFwk::EventHandler>(runner);
}
mainHandler->PostTask(func, "", 0, OHOS::AppExecFwk::EventQueue::Priority::HIGH, {});
return true;
}
bool ANIUtils::ParseString(ani_env *env, ani_ref ref, std::string& outValue)
{
ani_string str = static_cast<ani_string>(ref);
ani_size strSize;
auto status = env->String_GetUTF8Size(str, &strSize);
if (status != ANI_OK) {
HILOG_ERROR("AniUtils_ParseString String_GetUTF8Size status: %{public}d", status);
return false;
}
std::vector<char> buffer(strSize + 1);
char* utfBuffer = buffer.data();
ani_size bytes_written = 0;
env->String_GetUTF8(str, utfBuffer, strSize + 1, &bytes_written);
utfBuffer[bytes_written] = '\0';
outValue = std::string(utfBuffer);
return true;
}
bool ANIUtils::ParseStringArray(ani_env *env, ani_object array, std::vector<std::string>& outValue)
{
ani_size length = 0;
if (env->Array_GetLength(static_cast<ani_array>(array), &length) != ANI_OK) {
HILOG_ERROR("Failed to get array length");
return false;
}
for (ani_size i = 0; i < length; i++) {
ani_ref elementRef;
if (env->Array_Get(static_cast<ani_array>(array), i, &elementRef) != ANI_OK) {
HILOG_ERROR("Failed to get element at index %{public}zu", i);
continue;
}
std::string strValue;
if (!ANIUtils::ParseString(env, elementRef, strValue)) {
HILOG_ERROR("Failed to parse string at index %{public}zu", i);
continue;
}
outValue.push_back(strValue);
}
return true;
}
ani_object ANIUtils::CreateArray(ani_env *env, const std::vector<std::string> strs)
{
ani_array array = ANIUtils::CreateEmptyAniArray(env, strs.size());
if (array == nullptr) {
HILOG_ERROR("Create array failed");
return nullptr;
}
ani_size index = 0;
for (auto &item : strs) {
auto aniString = ANIUtils::CreateAniString(env, item);
if (env->Array_Set(array, index, aniString) != ANI_OK) {
HILOG_ERROR("Set array failed, index=%{public}zu", index);
return nullptr;
}
index++;
}
return array;
}
std::string ANIUtils::AniStrToString(ani_env *env, ani_ref aniStr)
{
ani_string ani_str = static_cast<ani_string>(aniStr);
ani_size strSize;
if (env->String_GetUTF8Size(ani_str, &strSize) != ANI_OK) {
HILOG_ERROR("Get utf8 size failed");
return "";
}
std::vector<char> buffer(strSize + 1);
ani_size bytes_written = 0;
if (env->String_GetUTF8(ani_str, buffer.data(), buffer.size(), &bytes_written) != ANI_OK) {
HILOG_ERROR("Create string failed");
return "";
}
return std::string(buffer.data(), bytes_written);
}
bool ANIUtils::GetStringMember(ani_env *env, ani_object options, const std::string &name, std::string &value)
{
ani_ref ref;
if (env->Object_GetPropertyByName_Ref(options, name.c_str(), &ref) != ANI_OK) {
HILOG_ERROR("Get property '%{public}s' failed", name.c_str());
return false;
}
ani_boolean isUndefined;
if (env->Reference_IsUndefined(ref, &isUndefined) != ANI_OK) {
HILOG_ERROR("Reference IsUndefined failed");
return false;
}
if (isUndefined) {
HILOG_ERROR("GetStringMember isUndefined");
return false;
}
value = ANIUtils::AniStrToString(env, ref);
return true;
}
bool ANIUtils::GetColorMember(ani_env *env, ani_object object, const char* name, uint32_t &color)
{
color = 0;
ani_ref ref;
if (env->Object_GetPropertyByName_Ref(object, name, &ref) != ANI_OK) {
HILOG_ERROR("Get property '%{public}s' failed", name);
return false;
}
ani_boolean isUndefined;
if (env->Reference_IsUndefined(ref, &isUndefined) != ANI_OK) {
HILOG_ERROR("Reference IsUndefined failed");
return false;
}
if (isUndefined) {
return false;
}
ani_class stringClass;
env->FindClass("std.core.String", &stringClass);
ani_boolean isString;
env->Object_InstanceOf(static_cast<ani_object>(ref), stringClass, &isString);
if (isString) {
auto stringContent = ANIStringToStdString(env, static_cast<ani_string>(ref));
color = ConvertColorStringToNumber(stringContent);
HILOG_INFO("color stringContent = %{public}s, color = %{public}u", stringContent.c_str(), color);
} else {
ani_int valueInt;
if (env->Object_CallMethodByName_Int(static_cast<ani_object>(ref), "toInt", ":i", &valueInt) != ANI_OK) {
HILOG_ERROR("Unbox Int failed");
return false;
}
color = static_cast<uint32_t>(valueInt);
HILOG_INFO("color intContent = %{public}u", color);
}
return true;
}
bool ANIUtils::GetNumberMember(ani_env *env, ani_object options, const std::string &name, uint32_t& value)
{
ani_ref ref;
if (env->Object_GetPropertyByName_Ref(options, name.c_str(), &ref) != ANI_OK) {
HILOG_ERROR("Get property '%{public}s' failed", name.c_str());
return false;
}
ani_boolean isUndefined;
if (env->Reference_IsUndefined(ref, &isUndefined) != ANI_OK) {
HILOG_ERROR("Reference IsUndefined failed");
return false;
}
if (isUndefined) {
return false;
}
ani_double valueDouble;
if (env->Object_CallMethodByName_Double(static_cast<ani_object>(ref), "toDouble", ":d", &valueDouble) != ANI_OK) {
HILOG_ERROR("Unbox Double failed");
return false;
}
HILOG_INFO("valueDouble:%{public}f", valueDouble);
value = static_cast<uint32_t>(valueDouble);
return true;
}
bool ANIUtils::SetNumberMember(ani_env *env, ani_object obj, const std::string &name, const ani_int value)
{
static const char *className = "std.core.Int";
ani_class cls;
if (env->FindClass(className, &cls) != ANI_OK) {
HILOG_ERROR("Find class '%{public}s' failed", className);
return false;
}
ani_method ctor;
if (env->Class_FindMethod(cls, "<ctor>", "i:", &ctor) != ANI_OK) {
HILOG_ERROR("Find method '<ctor>' failed");
return false;
}
ani_object intObj;
if (env->Object_New(cls, ctor, &intObj, value) != ANI_OK) {
HILOG_ERROR("New object '%{public}s' failed", className);
return false;
}
if (env->Object_SetPropertyByName_Ref(obj, name.c_str(), intObj) != ANI_OK) {
HILOG_ERROR("Set property '%{public}s' failed", name.c_str());
return false;
}
return true;
}
ani_object ANIUtils::CreateDouble(ani_env *env, float value)
{
if (env == nullptr) {
HILOG_ERROR("CreateDouble fail, env is nullptr");
return nullptr;
}
ani_class doubleCls;
ani_status status = ANI_ERROR;
if ((status = env->FindClass(CLASSNAME_DOUBLE, &doubleCls)) != ANI_OK) {
HILOG_ERROR("status : %{public}d", status);
return nullptr;
}
ani_method doubleCtor;
if ((status = env->Class_FindMethod(doubleCls, "<ctor>", "d:", &doubleCtor)) != ANI_OK) {
HILOG_ERROR("status : %{public}d", status);
return nullptr;
}
ani_object doubleObj;
if ((status = env->Object_New(doubleCls, doubleCtor, &doubleObj, static_cast<ani_double>(value))) != ANI_OK) {
HILOG_ERROR("status : %{public}d", status);
return nullptr;
}
return doubleObj;
}
ani_status ANIUtils::CreateAniBoolean(ani_env* env, bool value, ani_object& result)
{
ani_status state;
ani_class booleanClass;
if ((state = env->FindClass("std.core.Boolean", &booleanClass)) != ANI_OK) {
HILOG_ERROR("FindClass std/core/Boolean failed, %{public}d", state);
return state;
}
ani_method booleanClassCtor;
if ((state = env->Class_FindMethod(booleanClass, "<ctor>", "z:", &booleanClassCtor)) != ANI_OK) {
HILOG_ERROR("Class_FindMethod Boolean ctor failed, %{public}d", state);
return state;
}
ani_boolean aniValue = value;
if ((state = env->Object_New(booleanClass, booleanClassCtor, &result, aniValue)) != ANI_OK) {
HILOG_ERROR("New Boolean object failed, %{public}d", state);
return state;
}
return state;
}
ani_status ANIUtils::CreateAniInt(ani_env* env, int32_t value, ani_object& result)
{
ani_status state;
ani_class intClass;
if ((state = env->FindClass("std.core.Int", &intClass)) != ANI_OK) {
HILOG_ERROR("FindClass std/core/Int failed, %{public}d", state);
return state;
}
ani_method intClassCtor;
if ((state = env->Class_FindMethod(intClass, "<ctor>", "i:", &intClassCtor)) != ANI_OK) {
HILOG_ERROR("Class_FindMethod Int ctor failed, %{public}d", state);
return state;
}
ani_int aniValue = value;
if ((state = env->Object_New(intClass, intClassCtor, &result, aniValue)) != ANI_OK) {
HILOG_ERROR("New Int object failed, %{public}d", state);
}
return state;
}
ani_status ANIUtils::CreateAniFloat(ani_env* env, float value, ani_object& result)
{
ani_status state;
ani_class floatClass;
if ((state = env->FindClass("std.core.Float", &floatClass)) != ANI_OK) {
HILOG_ERROR("FindClass std/core/Float failed, %{public}d", state);
return state;
}
ani_method floatClassCtor;
if ((state = env->Class_FindMethod(floatClass, "<ctor>", "f:", &floatClassCtor)) != ANI_OK) {
HILOG_ERROR("Class_FindMethod Float ctor failed, %{public}d", state);
return state;
}
ani_float aniValue = value;
if ((state = env->Object_New(floatClass, floatClassCtor, &result, aniValue)) != ANI_OK) {
HILOG_ERROR("New Float object failed, %{public}d", state);
}
return state;
}
ani_status ANIUtils::CreateAniLong(ani_env* env, int64_t value, ani_object& result)
{
ani_status state;
ani_class longClass;
if ((state = env->FindClass("std.core.Long", &longClass)) != ANI_OK) {
HILOG_ERROR("FindClass std/core/Long failed, %{public}d", state);
return state;
}
ani_method longClassCtor;
if ((state = env->Class_FindMethod(longClass, "<ctor>", "l:", &longClassCtor)) != ANI_OK) {
HILOG_ERROR("Class_FindMethod Long ctor failed, %{public}d", state);
return state;
}
ani_long aniValue = value;
if ((state = env->Object_New(longClass, longClassCtor, &result, aniValue)) != ANI_OK) {
HILOG_ERROR("New Long object failed, %{public}d", state);
}
return state;
}
bool ANIUtils::SetStringField(ani_env *env, ani_object &object, const std::string &fieldName,
const std::string &value, bool isProperty)
{
if (env == nullptr) {
HILOG_ERROR("SetStringField null env");
return false;
}
ani_string string = nullptr;
ani_status status;
if (value.empty()) {
ani_ref nullRef = nullptr;
if ((status = env->GetNull(&nullRef)) != ANI_OK) {
HILOG_ERROR("get null status : %{public}d", status);
return false;
}
if (isProperty) {
if ((status = env->Object_SetPropertyByName_Ref(object, fieldName.c_str(), nullRef)) != ANI_OK) {
HILOG_ERROR("set null property status : %{public}d", status);
return false;
}
return true;
} else {
if ((status = env->Object_SetFieldByName_Ref(object, fieldName.c_str(), nullRef)) != ANI_OK) {
HILOG_ERROR("set null status : %{public}d", status);
return false;
}
return true;
}
}
if ((status = env->String_NewUTF8(value.c_str(), value.size(), &string)) != ANI_OK) {
HILOG_ERROR("change to ani string status : %{public}d", status);
return false;
}
if (isProperty) {
if ((status = env->Object_SetPropertyByName_Ref(object, fieldName.c_str(), string)) != ANI_OK) {
HILOG_ERROR("set property status : %{public}d", status);
return false;
}
return true;
} else {
if ((status = env->Object_SetFieldByName_Ref(object, fieldName.c_str(), string)) != ANI_OK) {
HILOG_ERROR("set ref status : %{public}d", status);
return false;
}
return true;
}
}
bool ANIUtils::SetArrayStringField(ani_env *env, ani_object &object, const std::string &fieldName,
const std::vector<std::string> &values, bool isProperty)
{
if (env == nullptr) {
HILOG_ERROR("SetArrayStringField null env");
return false;
}
ani_array arrayObj = ANIUtils::CreateEmptyAniArray(env, values.size());
if (arrayObj == nullptr) {
HILOG_ERROR("SetArrayStringField array is null");
return false;
}
ani_size index = 0;
for (auto &str : values) {
if (env->Array_Set(arrayObj, index, StdStringToAniString(env, str)) != ANI_OK) {
HILOG_ERROR("Object_CallMethodByName_Void failed name=%{public}s index=%{public}zu str=%{public}s",
fieldName.c_str(), index, str.c_str());
return false;
}
index++;
}
if (isProperty) {
ani_status status = env->Object_SetPropertyByName_Ref(object, fieldName.c_str(), arrayObj);
if (status != ANI_OK) {
HILOG_ERROR("status : %{public}d", status);
return false;
}
return true;
} else {
ani_status status = env->Object_SetFieldByName_Ref(object, fieldName.c_str(), arrayObj);
if (status != ANI_OK) {
HILOG_ERROR("status : %{public}d", status);
return false;
}
return true;
}
}
bool ANIUtils::SetIntField(ani_env *env, ani_object &object, const std::string &fieldName,
int32_t fieldValue, bool isProperty)
{
if (env == nullptr) {
HILOG_ERROR("SetIntField null env");
return false;
}
ani_object value;
if (CreateAniInt(env, fieldValue, value) != ANI_OK) {
HILOG_ERROR("CreateAniInt failed");
return false;
}
if (isProperty) {
if (env->Object_SetPropertyByName_Ref(object, fieldName.c_str(), value) != ANI_OK) {
HILOG_ERROR("set int property failed %{public}s", fieldName.c_str());
return false;
}
return true;
} else {
if (env->Object_SetFieldByName_Ref(object, fieldName.c_str(), value) != ANI_OK) {
HILOG_ERROR("set int field failed %{public}s", fieldName.c_str());
return false;
}
return true;
}
}
bool ANIUtils::SetDoubleField(ani_env *env, ani_object &object, const std::string &fieldName,
double fieldValue, bool isProperty)
{
if (env == nullptr) {
HILOG_ERROR("SetDoubleField null env");
return false;
}
ani_status status;
ani_object value = CreateDouble(env, static_cast<int32_t>(fieldValue));
if (isProperty) {
if ((status = env->Object_SetPropertyByName_Ref(object, fieldName.c_str(), value)) != ANI_OK) {
HILOG_ERROR("set double property failed %{public}s %{public}d", fieldName.c_str(), status);
return false;
}
return true;
} else {
if ((status = env->Object_SetFieldByName_Ref(object, fieldName.c_str(), value)) != ANI_OK) {
HILOG_ERROR("set double field failed %{public}s %{public}d", fieldName.c_str(), status);
return false;
}
return true;
}
}
bool ANIUtils::SetBooleanField(ani_env *env, ani_object &object, const std::string &fieldName,
bool fieldValue, bool isProperty)
{
if (env == nullptr) {
HILOG_ERROR("SetBoolField null env");
return false;
}
ani_object value;
if (CreateAniBoolean(env, fieldValue, value) != ANI_OK) {
HILOG_ERROR("CreateAniBoolean failed");
return false;
}
if (isProperty) {
if ((env->Object_SetPropertyByName_Ref(object, fieldName.c_str(), value)) != ANI_OK) {
HILOG_ERROR("set bool property failed %{public}s", fieldName.c_str());
return false;
}
return true;
} else {
if ((env->Object_SetFieldByName_Ref(object, fieldName.c_str(), value)) != ANI_OK) {
HILOG_ERROR("set bool field failed %{public}s", fieldName.c_str());
return false;
}
return true;
}
}
bool ANIUtils::SetLongField(ani_env *env, ani_object &object, const std::string &fieldName,
int64_t fieldValue, bool isProperty)
{
if (env == nullptr) {
HILOG_ERROR("SetLongField null env");
return false;
}
ani_object value;
if (CreateAniLong(env, fieldValue, value) != ANI_OK) {
HILOG_ERROR("CreateAniLong failed");
return false;
}
ani_status status;
if (isProperty) {
if ((status = env->Object_SetPropertyByName_Ref(object, fieldName.c_str(), value)) != ANI_OK) {
HILOG_ERROR("set long property failed %{public}s %{public}d", fieldName.c_str(), status);
return false;
}
return true;
} else {
if ((status = env->Object_SetFieldByName_Ref(object, fieldName.c_str(), value)) != ANI_OK) {
HILOG_ERROR("set long field failed %{public}s %{public}d", fieldName.c_str(), status);
return false;
}
return true;
}
}
bool ANIUtils::SetArrayField(ani_env *env, ani_object &object, const std::string &fieldName,
const std::vector<ani_object> &fieldValue, bool isProperty)
{
if (env == nullptr) {
HILOG_ERROR("SetArrayField null env");
return false;
}
ani_array array = CreateEmptyAniArray(env, fieldValue.size());
if (array == nullptr) {
HILOG_ERROR("CreateArray failed");
return false;
}
ani_size index = 0;
for (auto &item : fieldValue) {
if (env->Array_Set(array, index, item) != ANI_OK) {
HILOG_ERROR("Object_CallMethodByName_Void failed name=%{public}s index=%{public}zu",
fieldName.c_str(), index);
return false;
}
index++;
}
if (isProperty) {
if (env->Object_SetPropertyByName_Ref(object, fieldName.c_str(), array) != ANI_OK) {
HILOG_ERROR("set array property failed %{public}s", fieldName.c_str());
return false;
}
return true;
} else {
if (env->Object_SetFieldByName_Ref(object, fieldName.c_str(), array) != ANI_OK) {
HILOG_ERROR("set array field failed %{public}s", fieldName.c_str());
return false;
}
return true;
}
}
ani_object ANIUtils::CreateObject(ani_env *env, ani_class cls, ...)
{
ani_object nullobj {};
ani_method ctor;
if (env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor) != ANI_OK) {
HILOG_ERROR("[ANI] Not found <ctor> for class");
return nullobj;
}
ani_object obj;
va_list args;
va_start(args, cls);
ani_status status = env->Object_New_V(cls, ctor, &obj, args);
va_end(args);
if (status != ANI_OK) {
HILOG_ERROR("[ANI] Failed to Object_New for class 1");
return nullobj;
}
return obj;
}
bool ANIUtils::ConvertStringToInt64(std::string &str, int64_t &value)
{
auto [ptr, errCode] = std::from_chars(str.data(), str.data() + str.size(), value);
return errCode == std::errc{} && ptr == str.data() + str.size();
}
void ANIUtils::CheckNumber(ani_env *env, std::string value)
{
int num;
std::stringstream streamStr;
streamStr << value;
if (!(streamStr >> num)) {
HILOG_ERROR("check number failed!");
ThrowBusinessError(env, QueryRetMsg(RetError::RET_ERR_INVALID_PARAM));
}
}
void ANIUtils::SetScrollTypeParam(ani_env *env, ani_object obj, std::map<std::string, std::string>& args)
{
ani_ref fiedNameValue;
std::string str = "";
std::map<std::string, std::string> scrollValueMap = { {"halfScreen", HALF_VALUE}, {"fullScreen", FULL_VALUE} };
std::string scrollValue = FULL_VALUE;
if (env->Object_GetFieldByName_Ref(obj, "scrollType", &fiedNameValue) == ANI_OK) {
str = ANIStringToStdString(env, static_cast<ani_string>(fiedNameValue));
if (scrollValueMap.find(str) != scrollValueMap.end()) {
scrollValue = scrollValueMap.find(str)->second;
HILOG_DEBUG("ScrollValue %{public}s", scrollValue.c_str());
} else {
HILOG_ERROR("Input is empty!");
ThrowBusinessError(env, QueryRetMsg(RetError::RET_ERR_INVALID_PARAM));
}
args.insert(std::pair<std::string, std::string>("scrolltype", scrollValue.c_str()));
}
}
void ANIUtils::SetSelectionParam(ani_env *env, ani_object obj, std::map<std::string, std::string>& args)
{
ani_ref fiedNameValue;
ani_boolean forWard;
std::string str = "";
if (env->Object_GetFieldByName_Ref(obj, "selectTextBegin", &fiedNameValue) == ANI_OK) {
str = ANIStringToStdString(env, static_cast<ani_string>(fiedNameValue));
CheckNumber(env, str);
args.insert(std::pair<std::string, std::string>("selectTextBegin", str.c_str()));
}
if (env->Object_GetFieldByName_Ref(obj, "selectTextEnd", &fiedNameValue) == ANI_OK) {
str = ANIStringToStdString(env, static_cast<ani_string>(fiedNameValue));
CheckNumber(env, str);
args.insert(std::pair<std::string, std::string>("selectTextEnd", str.c_str()));
}
if (env->Object_GetFieldByName_Boolean(obj, "selectTextInForWard", &forWard) == ANI_OK) {
std::string value = forWard ? "forWard" : "backWard";
args.insert(std::pair<std::string, std::string>("selectTextInForWard", value.c_str()));
}
}
void ANIUtils::SetAccessibilityFocusSceneParam(ani_env *env, ani_object obj, std::map<std::string, std::string>& args)
{
ani_ref fiedNameValue;
ani_boolean isUndefined;
if (env->Object_GetFieldByName_Ref(obj, "accessibilityFocusScene", &fiedNameValue) == ANI_OK &&
env->Reference_IsUndefined(fiedNameValue, &isUndefined) == ANI_OK) {
if (isUndefined) {
HILOG_WARN("accessibilityFocusScene isUndefined");
return;
}
ani_enum_item enumItem = static_cast<ani_enum_item>(fiedNameValue);
ani_int intValue = 0;
if (env->EnumItem_GetValue_Int(enumItem, &intValue) == ANI_OK) {
if (intValue >= AccessibilityFocusScene::HOVER_FOCUS && intValue <= AccessibilityFocusScene::SCROLL_FOCUS) {
args.insert(std::pair<std::string, std::string>("accessibilityFocusScene", std::to_string(intValue)));
} else {
HILOG_ERROR("Invalid AccessibilityFocusScene value: %{public}d", intValue);
ThrowBusinessError(env, QueryRetMsg(RetError::RET_ERR_INVALID_PARAM));
}
}
}
}
void ANIUtils::ConvertActionArgsJSToANI(ani_env *env, ani_object obj,
std::map<std::string, std::string>& args, OHOS::Accessibility::ActionType action)
{
ani_ref fiedNameValue;
std::string str = "";
switch (action) {
case ActionType::ACCESSIBILITY_ACTION_NEXT_HTML_ITEM:
case ActionType::ACCESSIBILITY_ACTION_PREVIOUS_HTML_ITEM:
if (env->Object_GetFieldByName_Ref(obj, "htmlItem", &fiedNameValue) == ANI_OK) {
str = ANIStringToStdString(env, static_cast<ani_string>(fiedNameValue));
args.insert(std::pair<std::string, std::string>("htmlItem", str.c_str()));
}
break;
case ActionType::ACCESSIBILITY_ACTION_NEXT_TEXT:
case ActionType::ACCESSIBILITY_ACTION_PREVIOUS_TEXT:
if (env->Object_GetFieldByName_Ref(obj, "textMoveUnit", &fiedNameValue) == ANI_OK) {
str = ANIStringToStdString(env, static_cast<ani_string>(fiedNameValue));
args.insert(std::pair<std::string, std::string>("textMoveUnit", str.c_str()));
}
break;
case ActionType::ACCESSIBILITY_ACTION_SET_SELECTION:
SetSelectionParam(env, obj, args);
break;
case ActionType::ACCESSIBILITY_ACTION_SET_CURSOR_POSITION:
if (env->Object_GetFieldByName_Ref(obj, "offset", &fiedNameValue) == ANI_OK) {
str = ANIStringToStdString(env, static_cast<ani_string>(fiedNameValue));
CheckNumber(env, str);
args.insert(std::pair<std::string, std::string>("offset", str.c_str()));
}
break;
case ActionType::ACCESSIBILITY_ACTION_SET_TEXT:
if (env->Object_GetFieldByName_Ref(obj, "setText", &fiedNameValue) == ANI_OK) {
str = ANIStringToStdString(env, static_cast<ani_string>(fiedNameValue));
args.insert(std::pair<std::string, std::string>("setText", str.c_str()));
}
break;
case ActionType::ACCESSIBILITY_ACTION_SPAN_CLICK:
if (env->Object_GetFieldByName_Ref(obj, "spanId", &fiedNameValue) == ANI_OK) {
str = ANIStringToStdString(env, static_cast<ani_string>(fiedNameValue));
CheckNumber(env, str);
args.insert(std::pair<std::string, std::string>("spanId", str.c_str()));
}
break;
case ActionType::ACCESSIBILITY_ACTION_INJECT_ACTION: {
if (env->Object_GetFieldByName_Ref(obj, "injectActionType", &fiedNameValue) == ANI_OK) {
int32_t injectActionType = 0;
if (env->EnumItem_GetValue_Int(static_cast<ani_enum_item>(fiedNameValue),
&injectActionType) != ANI_OK) {
HILOG_ERROR("Failed to get injectActionType enum value");
break;
}
args.insert(std::pair<std::string, std::string>("injectActionType", std::to_string(injectActionType)));
}
break;
}
case ActionType::ACCESSIBILITY_ACTION_CUSTOM:
if (env->Object_GetFieldByName_Ref(obj, "customAction", &fiedNameValue) == ANI_OK) {
str = ANIStringToStdString(env, static_cast<ani_string>(fiedNameValue));
args.insert(std::pair<std::string, std::string>("customAction", str.c_str()));
} else {
HILOG_ERROR("customAction is required for CUSTOM action");
ThrowBusinessError(env, QueryRetMsg(RetError::RET_ERR_INVALID_PARAM));
}
break;
case ActionType::ACCESSIBILITY_ACTION_SCROLL_FORWARD:
case ActionType::ACCESSIBILITY_ACTION_SCROLL_BACKWARD:
SetScrollTypeParam(env, obj, args);
break;
case ActionType::ACCESSIBILITY_ACTION_ACCESSIBILITY_FOCUS:
SetAccessibilityFocusSceneParam(env, obj, args);
break;
default:
break;
}
}