* Copyright (C) 2022 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 "accessibility_element_operator_callback_stub.h"
#include "accessibility_element_info_parcel.h"
#include "accessibility_ipc_interface_code.h"
#include "hilog_wrapper.h"
#include "parcel_util.h"
#include <securec.h>
#define SWITCH_BEGIN(code) switch (code) {
#define SWITCH_CASE(case_code, func) \
case case_code: { \
result_code = func(data, reply); \
break; \
}
#define SWITCH_END() \
default: { \
result_code = ERR_CODE_DEFAULT; \
HILOG_WARN("AccessibilityElementOperatorCallbackStub::OnRemoteRequest, default case, need check."); \
break; \
} \
}
#define ACCESSIBILITY_ELEMENT_OPERATOR_CALLBACK_STUB_CASES() \
SWITCH_CASE(AccessibilityInterfaceCode::SET_RESULT_BY_ACCESSIBILITY_ID, \
HandleSetSearchElementInfoByAccessibilityIdResult) \
SWITCH_CASE(AccessibilityInterfaceCode::SET_RESULT_BY_TEXT, HandleSetSearchElementInfoByTextResult) \
SWITCH_CASE(AccessibilityInterfaceCode::SET_RESULT_FOCUSED_INFO, HandleSetFindFocusedElementInfoResult) \
SWITCH_CASE(AccessibilityInterfaceCode::SET_RESULT_FOCUS_MOVE, HandleSetFocusMoveSearchResult) \
SWITCH_CASE(AccessibilityInterfaceCode::SET_RESULT_PERFORM_ACTION, HandleSetExecuteActionResult) \
SWITCH_CASE(AccessibilityInterfaceCode::SET_RESULT_CURSOR_RESULT, HandleSetCursorPositionResult) \
SWITCH_CASE(AccessibilityInterfaceCode::SET_RESULT_BY_WINDOW_ID, \
HandleSetSearchDefaultFocusByWindowIdResult) \
SWITCH_CASE(AccessibilityInterfaceCode::SET_RESULT_BY_SPECIFIC_PROPERTY, \
HandleSetSearchElementInfoBySpecificPropertyResult) \
SWITCH_CASE(AccessibilityInterfaceCode::SET_RESULT_FOCUS_MOVE_SEARCH_WITH_CONDITION, \
HandleSetFocusMoveSearchWithConditionResult) \
SWITCH_CASE(AccessibilityInterfaceCode::SET_RESULT_UPDATE_ACCESSIBILITY_ELEMENT_INFO, \
HandleSetUpdateCustomAccessibilityPropertyResult) \
SWITCH_CASE(AccessibilityInterfaceCode::SET_RESULT_ADD_ACCESSIBILITY_VIRTUAL_NODE, \
HandleSetAddAccessibilityVirtualNodeResult) \
SWITCH_CASE(AccessibilityInterfaceCode::SET_RESULT_REMOVE_ACCESSIBILITY_VIRTUAL_NODE, \
HandleSetRemoveAccessibilityVirtualNodeResult)
namespace OHOS {
namespace Accessibility {
constexpr int32_t ERR_CODE_DEFAULT = -1000;
constexpr int32_t MAX_RAWDATA_SIZE = 128 * 1024 * 1024;
static bool GetData(size_t size, const void *data, void *&buffer)
{
if (data == nullptr || size == 0) {
return false;
}
if (size > MAX_RAWDATA_SIZE) {
return false;
}
size_t bufferSize = size;
buffer = malloc(bufferSize);
if (buffer == nullptr) {
return false;
}
if (memcpy_s(buffer, bufferSize, data, size) != EOK) {
free(buffer);
return false;
}
return true;
}
AccessibilityElementOperatorCallbackStub::AccessibilityElementOperatorCallbackStub()
{
}
AccessibilityElementOperatorCallbackStub::~AccessibilityElementOperatorCallbackStub()
{
}
int AccessibilityElementOperatorCallbackStub::OnRemoteRequest(uint32_t code, MessageParcel &data,
MessageParcel &reply, MessageOption &option)
{
HILOG_DEBUG("cmd = %{public}u, flags= %{public}d", code, option.GetFlags());
std::u16string descriptor = AccessibilityElementOperatorCallbackStub::GetDescriptor();
std::u16string remoteDescriptor = data.ReadInterfaceToken();
if (descriptor != remoteDescriptor) {
HILOG_ERROR("AccessibilityElementOperatorCallbackStub::OnRemoteRequest"
"local descriptor is not equal to remote");
return ERR_INVALID_STATE;
}
ErrCode result_code = ERR_NONE;
SWITCH_BEGIN(code)
ACCESSIBILITY_ELEMENT_OPERATOR_CALLBACK_STUB_CASES()
SWITCH_END()
if (result_code != ERR_CODE_DEFAULT) {
return result_code;
}
return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
}
ErrCode AccessibilityElementOperatorCallbackStub::HandleSetSearchElementInfoByAccessibilityIdResult(
MessageParcel &data, MessageParcel &reply)
{
HILOG_DEBUG();
std::vector<AccessibilityElementInfo> storeData;
int32_t requestId = data.ReadInt32();
uint32_t infoSize = data.ReadUint32();
if (infoSize != 0) {
size_t rawDataSize = data.ReadUint32();
MessageParcel tmpParcel;
void *buffer = nullptr;
if (!GetData(rawDataSize, data.ReadRawData(rawDataSize), buffer)) {
reply.WriteInt32(RET_ERR_FAILED);
return TRANSACTION_ERR;
}
if (!tmpParcel.ParseFrom(reinterpret_cast<uintptr_t>(buffer), rawDataSize)) {
free(buffer);
buffer = nullptr;
reply.WriteInt32(RET_ERR_FAILED);
return TRANSACTION_ERR;
}
if (infoSize > static_cast<uint32_t>(MAX_ALLOW_SIZE)) {
reply.WriteInt32(RET_ERR_FAILED);
return TRANSACTION_ERR;
}
for (size_t i = 0; i < infoSize; i++) {
sptr<AccessibilityElementInfoParcel> info =
tmpParcel.ReadStrongParcelable<AccessibilityElementInfoParcel>();
if (info == nullptr) {
reply.WriteInt32(RET_ERR_FAILED);
return TRANSACTION_ERR;
}
storeData.emplace_back(*info);
}
}
reply.WriteInt32(RET_OK);
SetSearchElementInfoByAccessibilityIdResult(storeData, requestId);
return NO_ERROR;
}
ErrCode AccessibilityElementOperatorCallbackStub::HandleSetSearchDefaultFocusByWindowIdResult(
MessageParcel &data, MessageParcel &reply)
{
HILOG_DEBUG();
std::vector<AccessibilityElementInfo> storeData;
int32_t requestId = data.ReadInt32();
uint32_t infoSize = data.ReadUint32();
if (infoSize != 0) {
size_t rawDataSize = data.ReadUint32();
MessageParcel tmpParcel;
void *buffer = nullptr;
if (!GetData(rawDataSize, data.ReadRawData(rawDataSize), buffer)) {
HILOG_ERROR("get data failed!");
reply.WriteInt32(RET_ERR_FAILED);
return TRANSACTION_ERR;
}
if (!tmpParcel.ParseFrom(reinterpret_cast<uintptr_t>(buffer), rawDataSize)) {
HILOG_ERROR("parse data from buffer failed!");
free(buffer);
buffer = nullptr;
reply.WriteInt32(RET_ERR_FAILED);
return TRANSACTION_ERR;
}
if (infoSize > static_cast<uint32_t>(MAX_ALLOW_SIZE)) {
HILOG_ERROR("The infoSize is abnormal");
reply.WriteInt32(RET_ERR_FAILED);
return TRANSACTION_ERR;
}
for (size_t i = 0; i < infoSize; i++) {
sptr<AccessibilityElementInfoParcel> info =
tmpParcel.ReadStrongParcelable<AccessibilityElementInfoParcel>();
if (info == nullptr) {
HILOG_ERROR("info is nullptr!");
reply.WriteInt32(RET_ERR_FAILED);
return TRANSACTION_ERR;
}
storeData.emplace_back(*info);
}
}
reply.WriteInt32(RET_OK);
SetSearchDefaultFocusByWindowIdResult(storeData, requestId);
return NO_ERROR;
}
ErrCode AccessibilityElementOperatorCallbackStub::HandleSetSearchElementInfoByTextResult(
MessageParcel &data, MessageParcel &reply)
{
HILOG_DEBUG();
std::vector<AccessibilityElementInfo> infos {};
int32_t accessibilityInfosize = data.ReadInt32();
bool verifyResult = ContainerSecurityVerify(data, accessibilityInfosize, infos.max_size());
if (!verifyResult) {
return TRANSACTION_ERR;
}
if (accessibilityInfosize < 0 || accessibilityInfosize > MAX_ALLOW_SIZE) {
return TRANSACTION_ERR;
}
for (int32_t i = 0; i < accessibilityInfosize; i++) {
sptr<AccessibilityElementInfoParcel> accessibilityInfo =
data.ReadStrongParcelable<AccessibilityElementInfoParcel>();
if (accessibilityInfo == nullptr) {
HILOG_ERROR("ReadStrongParcelable<accessibilityInfo> failed");
return TRANSACTION_ERR;
}
infos.emplace_back(*accessibilityInfo);
}
int32_t requestId = data.ReadInt32();
SetSearchElementInfoByTextResult(infos, requestId);
return NO_ERROR;
}
ErrCode AccessibilityElementOperatorCallbackStub::HandleSetFindFocusedElementInfoResult(MessageParcel &data,
MessageParcel &reply)
{
HILOG_DEBUG();
sptr<AccessibilityElementInfoParcel> info = data.ReadStrongParcelable<AccessibilityElementInfoParcel>();
if (info == nullptr) {
HILOG_ERROR("ReadStrongParcelable<AccessibilityElementInfo> failed");
return TRANSACTION_ERR;
}
int32_t requestId = data.ReadInt32();
SetFindFocusedElementInfoResult(*info, requestId);
return NO_ERROR;
}
ErrCode AccessibilityElementOperatorCallbackStub::HandleSetFocusMoveSearchResult(MessageParcel &data,
MessageParcel &reply)
{
HILOG_DEBUG();
sptr<AccessibilityElementInfoParcel> info = data.ReadStrongParcelable<AccessibilityElementInfoParcel>();
if (info == nullptr) {
HILOG_ERROR("ReadStrongParcelable<AccessibilityElementInfo> failed");
return TRANSACTION_ERR;
}
int32_t requestId = data.ReadInt32();
SetFocusMoveSearchResult(*info, requestId);
return NO_ERROR;
}
ErrCode AccessibilityElementOperatorCallbackStub::HandleSetExecuteActionResult(MessageParcel &data,
MessageParcel &reply)
{
HILOG_DEBUG();
bool succeeded = data.ReadBool();
int32_t requestId = data.ReadInt32();
SetExecuteActionResult(succeeded, requestId);
return NO_ERROR;
}
ErrCode AccessibilityElementOperatorCallbackStub::HandleSetCursorPositionResult(MessageParcel &data,
MessageParcel &reply)
{
HILOG_DEBUG();
int32_t cursorPosition = data.ReadInt32();
int32_t requestId = data.ReadInt32();
HILOG_INFO("[cursorPosition:%{public}d]", cursorPosition);
SetCursorPositionResult(cursorPosition, requestId);
return NO_ERROR;
}
ErrCode AccessibilityElementOperatorCallbackStub::ReadAccessibilityElementInfoList(
MessageParcel &data, MessageParcel &reply, int32_t infoSize, std::list<AccessibilityElementInfo> &infos)
{
if (infoSize == 0) {
HILOG_INFO("infoSize is 0, no element info to read");
return NO_ERROR;
}
size_t rawDataSize = data.ReadUint32();
MessageParcel tmpParcel;
void *buffer = nullptr;
if (!GetData(rawDataSize, data.ReadRawData(rawDataSize), buffer)) {
reply.WriteInt32(RET_ERR_FAILED);
return TRANSACTION_ERR;
}
if (!tmpParcel.ParseFrom(reinterpret_cast<uintptr_t>(buffer), rawDataSize)) {
free(buffer);
buffer = nullptr;
reply.WriteInt32(RET_ERR_FAILED);
return TRANSACTION_ERR;
}
if (infoSize < 0 || infoSize > MAX_ALLOW_SIZE) {
reply.WriteInt32(RET_ERR_FAILED);
return TRANSACTION_ERR;
}
for (int32_t i = 0; i < infoSize; i++) {
sptr<AccessibilityElementInfoParcel> info =
tmpParcel.ReadStrongParcelable<AccessibilityElementInfoParcel>();
if (info == nullptr) {
reply.WriteInt32(RET_ERR_FAILED);
return TRANSACTION_ERR;
}
infos.emplace_back(*info);
}
return NO_ERROR;
}
ErrCode AccessibilityElementOperatorCallbackStub::HandleSetSearchElementInfoBySpecificPropertyResult(
MessageParcel &data, MessageParcel &reply)
{
HILOG_DEBUG();
int32_t requestId = data.ReadInt32();
int32_t infoSize = data.ReadInt32();
std::list<AccessibilityElementInfo> infos;
ErrCode result = ReadAccessibilityElementInfoList(data, reply, infoSize, infos);
if (result != NO_ERROR) {
return result;
}
int32_t treeInfoSize = data.ReadInt32();
std::list<AccessibilityElementInfo> treeInfos;
result = ReadAccessibilityElementInfoList(data, reply, treeInfoSize, treeInfos);
if (result != NO_ERROR) {
return result;
}
reply.WriteInt32(RET_OK);
SetSearchElementInfoBySpecificPropertyResult(infos, treeInfos, requestId);
return NO_ERROR;
}
ErrCode AccessibilityElementOperatorCallbackStub::HandleSetFocusMoveSearchWithConditionResult(
MessageParcel &data, MessageParcel &reply)
{
HILOG_DEBUG();
std::list<AccessibilityElementInfo> infos;
int32_t infoSize = data.ReadInt32();
ErrCode rtn = ReadAccessibilityElementInfoList(data, reply, infoSize, infos);
if (rtn != NO_ERROR) {
return rtn;
}
FocusMoveResult result;
result.resultType = static_cast<FocusMoveResultType>(data.ReadInt32());
result.nowLevelBelongTreeId = data.ReadInt32();
result.parentWindowId = data.ReadInt32();
result.changeToNewInfo = data.ReadBool();
result.needTerminate = data.ReadBool();
int32_t requestId = data.ReadInt32();
reply.WriteInt32(RET_OK);
SetFocusMoveSearchWithConditionResult(infos, result, requestId);
return NO_ERROR;
}
ErrCode AccessibilityElementOperatorCallbackStub::HandleSetUpdateCustomAccessibilityPropertyResult(
MessageParcel &data, MessageParcel &reply)
{
HILOG_DEBUG();
OperateVirtualNodeResult result = static_cast<OperateVirtualNodeResult>(data.ReadInt32());
int32_t requestId = data.ReadInt32();
HILOG_DEBUG("requestId[%{public}d], result[%{public}d]", requestId, result);
SetUpdateCustomAccessibilityPropertyResult(result, requestId);
return NO_ERROR;
}
ErrCode AccessibilityElementOperatorCallbackStub::HandleSetAddAccessibilityVirtualNodeResult(
MessageParcel &data, MessageParcel &reply)
{
HILOG_DEBUG();
OperateVirtualNodeResult result = static_cast<OperateVirtualNodeResult>(data.ReadInt32());
int32_t requestId = data.ReadInt32();
HILOG_DEBUG("requestId[%{public}d], result[%{public}d]", requestId, result);
SetAddAccessibilityVirtualNodeResult(result, requestId);
return NO_ERROR;
}
ErrCode AccessibilityElementOperatorCallbackStub::HandleSetRemoveAccessibilityVirtualNodeResult(
MessageParcel &data, MessageParcel &reply)
{
HILOG_DEBUG();
OperateVirtualNodeResult result = static_cast<OperateVirtualNodeResult>(data.ReadInt32());
int32_t requestId = data.ReadInt32();
HILOG_DEBUG("requestId[%{public}d], result[%{public}d]", requestId, result);
SetRemoveAccessibilityVirtualNodeResult(result, requestId);
return NO_ERROR;
}
}
}