1 /*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "accessibility_element_operator_callback_stub.h"
17 #include "accessibility_element_info_parcel.h"
18 #include "accessibility_ipc_interface_code.h"
19 #include "hilog_wrapper.h"
20 #include "parcel_util.h"
21 #include <securec.h>
22
23 #define SWITCH_BEGIN(code) switch (code) {
24 #define SWITCH_CASE(case_code, func) \
25 case case_code: { \
26 result_code = func(data, reply); \
27 break; \
28 }
29
30 #define SWITCH_END() \
31 default: { \
32 result_code = ERR_CODE_DEFAULT; \
33 HILOG_WARN("AccessibilityElementOperatorCallbackStub::OnRemoteRequest, default case, need check."); \
34 break; \
35 } \
36 }
37
38 #define ACCESSIBILITY_ELEMENT_OPERATOR_CALLBACK_STUB_CASES() \
39 SWITCH_CASE(AccessibilityInterfaceCode::SET_RESULT_BY_ACCESSIBILITY_ID, \
40 HandleSetSearchElementInfoByAccessibilityIdResult) \
41 SWITCH_CASE(AccessibilityInterfaceCode::SET_RESULT_BY_TEXT, HandleSetSearchElementInfoByTextResult) \
42 SWITCH_CASE(AccessibilityInterfaceCode::SET_RESULT_FOCUSED_INFO, HandleSetFindFocusedElementInfoResult) \
43 SWITCH_CASE(AccessibilityInterfaceCode::SET_RESULT_FOCUS_MOVE, HandleSetFocusMoveSearchResult) \
44 SWITCH_CASE(AccessibilityInterfaceCode::SET_RESULT_PERFORM_ACTION, HandleSetExecuteActionResult) \
45 SWITCH_CASE(AccessibilityInterfaceCode::SET_RESULT_CURSOR_RESULT, HandleSetCursorPositionResult) \
46 SWITCH_CASE(AccessibilityInterfaceCode::SET_RESULT_BY_WINDOW_ID, \
47 HandleSetSearchDefaultFocusByWindowIdResult) \
48 SWITCH_CASE(AccessibilityInterfaceCode::SET_RESULT_BY_SPECIFIC_PROPERTY, \
49 HandleSetSearchElementInfoBySpecificPropertyResult)
50
51 namespace OHOS {
52 namespace Accessibility {
53
54 constexpr int32_t SINGLE_TRANSMIT = -2;
55 constexpr int32_t MULTI_TRANSMIT_FINISH = -1;
56 constexpr int32_t ERR_CODE_DEFAULT = -1000;
57 constexpr int32_t MAX_RAWDATA_SIZE = 128 * 1024 * 1024; // RawData limit is 128M, limited by IPC
58
GetData(size_t size,const void * data,void * & buffer)59 static bool GetData(size_t size, const void *data, void *&buffer)
60 {
61 if (data == nullptr || size == 0) {
62 return false;
63 }
64 if (size > MAX_RAWDATA_SIZE) {
65 return false;
66 }
67 buffer = malloc(size);
68 if (buffer == nullptr) {
69 return false;
70 }
71 if (memcpy_s(buffer, sizeof(char) * size, data, size) != EOK) {
72 free(buffer);
73 return false;
74 }
75 return true;
76 }
77
AccessibilityElementOperatorCallbackStub()78 AccessibilityElementOperatorCallbackStub::AccessibilityElementOperatorCallbackStub()
79 {
80 }
81
~AccessibilityElementOperatorCallbackStub()82 AccessibilityElementOperatorCallbackStub::~AccessibilityElementOperatorCallbackStub()
83 {
84 }
85
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)86 int AccessibilityElementOperatorCallbackStub::OnRemoteRequest(uint32_t code, MessageParcel &data,
87 MessageParcel &reply, MessageOption &option)
88 {
89 HILOG_DEBUG("cmd = %{public}u, flags= %{public}d", code, option.GetFlags());
90 std::u16string descriptor = AccessibilityElementOperatorCallbackStub::GetDescriptor();
91 std::u16string remoteDescriptor = data.ReadInterfaceToken();
92 if (descriptor != remoteDescriptor) {
93 HILOG_ERROR("AccessibilityElementOperatorCallbackStub::OnRemoteRequest"
94 "local descriptor is not equal to remote");
95 return ERR_INVALID_STATE;
96 }
97
98 ErrCode result_code = ERR_NONE;
99 SWITCH_BEGIN(code)
100 ACCESSIBILITY_ELEMENT_OPERATOR_CALLBACK_STUB_CASES()
101 SWITCH_END()
102
103 if (result_code != ERR_CODE_DEFAULT) {
104 return result_code;
105 }
106
107 return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
108 }
109
HandleSetSearchElementInfoByAccessibilityIdResult(MessageParcel & data,MessageParcel & reply)110 ErrCode AccessibilityElementOperatorCallbackStub::HandleSetSearchElementInfoByAccessibilityIdResult(
111 MessageParcel &data, MessageParcel &reply)
112 {
113 HILOG_DEBUG();
114 std::vector<AccessibilityElementInfo> storeData;
115 int32_t requestId = data.ReadInt32();
116 size_t infoSize = data.ReadUint32();
117 if (infoSize != 0) {
118 size_t rawDataSize = data.ReadUint32();
119 MessageParcel tmpParcel;
120 void *buffer = nullptr;
121 // memory alloced in GetData will be released when tmpParcel destruct
122 if (!GetData(rawDataSize, data.ReadRawData(rawDataSize), buffer)) {
123 reply.WriteInt32(RET_ERR_FAILED);
124 return TRANSACTION_ERR;
125 }
126
127 if (!tmpParcel.ParseFrom(reinterpret_cast<uintptr_t>(buffer), rawDataSize)) {
128 reply.WriteInt32(RET_ERR_FAILED);
129 return TRANSACTION_ERR;
130 }
131
132 if (infoSize < 0 || infoSize > MAX_ALLOW_SIZE) {
133 reply.WriteInt32(RET_ERR_FAILED);
134 return TRANSACTION_ERR;
135 }
136
137 for (size_t i = 0; i < infoSize; i++) {
138 sptr<AccessibilityElementInfoParcel> info =
139 tmpParcel.ReadStrongParcelable<AccessibilityElementInfoParcel>();
140 if (info == nullptr) {
141 reply.WriteInt32(RET_ERR_FAILED);
142 return TRANSACTION_ERR;
143 }
144 storeData.emplace_back(*info);
145 }
146 }
147 reply.WriteInt32(RET_OK);
148 SetSearchElementInfoByAccessibilityIdResult(storeData, requestId);
149 return NO_ERROR;
150 }
151
HandleSetSearchDefaultFocusByWindowIdResult(MessageParcel & data,MessageParcel & reply)152 ErrCode AccessibilityElementOperatorCallbackStub::HandleSetSearchDefaultFocusByWindowIdResult(
153 MessageParcel &data, MessageParcel &reply)
154 {
155 HILOG_DEBUG();
156 std::vector<AccessibilityElementInfo> storeData;
157 int32_t requestId = data.ReadInt32();
158 uint32_t infoSize = data.ReadUint32();
159 if (infoSize != 0) {
160 size_t rawDataSize = data.ReadUint32();
161 MessageParcel tmpParcel;
162 void *buffer = nullptr;
163 // memory alloced in GetData will be released when tmpParcel destruct
164 if (!GetData(rawDataSize, data.ReadRawData(rawDataSize), buffer)) {
165 reply.WriteInt32(RET_ERR_FAILED);
166 return TRANSACTION_ERR;
167 }
168
169 if (!tmpParcel.ParseFrom(reinterpret_cast<uintptr_t>(buffer), rawDataSize)) {
170 free(buffer);
171 buffer = nullptr;
172 reply.WriteInt32(RET_ERR_FAILED);
173 return TRANSACTION_ERR;
174 }
175
176 if (infoSize < 0 || infoSize > static_cast<uint32_t>(MAX_ALLOW_SIZE)) {
177 reply.WriteInt32(RET_ERR_FAILED);
178 return TRANSACTION_ERR;
179 }
180
181 for (size_t i = 0; i < infoSize; i++) {
182 sptr<AccessibilityElementInfoParcel> info =
183 tmpParcel.ReadStrongParcelable<AccessibilityElementInfoParcel>();
184 if (info == nullptr) {
185 reply.WriteInt32(RET_ERR_FAILED);
186 return TRANSACTION_ERR;
187 }
188 storeData.emplace_back(*info);
189 }
190 }
191 reply.WriteInt32(RET_OK);
192 SetSearchDefaultFocusByWindowIdResult(storeData, requestId);
193 return NO_ERROR;
194 }
195
HandleSetSearchElementInfoByTextResult(MessageParcel & data,MessageParcel & reply)196 ErrCode AccessibilityElementOperatorCallbackStub::HandleSetSearchElementInfoByTextResult(
197 MessageParcel &data, MessageParcel &reply)
198 {
199 HILOG_DEBUG();
200 std::vector<AccessibilityElementInfo> infos {};
201 int32_t accessibilityInfosize = data.ReadInt32();
202 bool verifyResult = ContainerSecurityVerify(data, accessibilityInfosize, infos.max_size());
203 if (!verifyResult) {
204 return TRANSACTION_ERR;
205 }
206 if (accessibilityInfosize < 0 || accessibilityInfosize > MAX_ALLOW_SIZE) {
207 return TRANSACTION_ERR;
208 }
209 for (int32_t i = 0; i < accessibilityInfosize; i++) {
210 sptr<AccessibilityElementInfoParcel> accessibilityInfo =
211 data.ReadStrongParcelable<AccessibilityElementInfoParcel>();
212 if (accessibilityInfo == nullptr) {
213 HILOG_ERROR("ReadStrongParcelable<accessibilityInfo> failed");
214 return TRANSACTION_ERR;
215 }
216 infos.emplace_back(*accessibilityInfo);
217 }
218 int32_t requestId = data.ReadInt32();
219
220 SetSearchElementInfoByTextResult(infos, requestId);
221
222 return NO_ERROR;
223 }
224
HandleSetFindFocusedElementInfoResult(MessageParcel & data,MessageParcel & reply)225 ErrCode AccessibilityElementOperatorCallbackStub::HandleSetFindFocusedElementInfoResult(MessageParcel &data,
226 MessageParcel &reply)
227 {
228 HILOG_DEBUG();
229 sptr<AccessibilityElementInfoParcel> info = data.ReadStrongParcelable<AccessibilityElementInfoParcel>();
230 if (info == nullptr) {
231 HILOG_ERROR("ReadStrongParcelable<AccessibilityElementInfo> failed");
232 return TRANSACTION_ERR;
233 }
234
235 int32_t requestId = data.ReadInt32();
236
237 SetFindFocusedElementInfoResult(*info, requestId);
238
239 return NO_ERROR;
240 }
241
HandleSetFocusMoveSearchResult(MessageParcel & data,MessageParcel & reply)242 ErrCode AccessibilityElementOperatorCallbackStub::HandleSetFocusMoveSearchResult(MessageParcel &data,
243 MessageParcel &reply)
244 {
245 HILOG_DEBUG();
246 sptr<AccessibilityElementInfoParcel> info = data.ReadStrongParcelable<AccessibilityElementInfoParcel>();
247 if (info == nullptr) {
248 HILOG_ERROR("ReadStrongParcelable<AccessibilityElementInfo> failed");
249 return TRANSACTION_ERR;
250 }
251
252 int32_t requestId = data.ReadInt32();
253
254 SetFocusMoveSearchResult(*info, requestId);
255
256 return NO_ERROR;
257 }
258
HandleSetExecuteActionResult(MessageParcel & data,MessageParcel & reply)259 ErrCode AccessibilityElementOperatorCallbackStub::HandleSetExecuteActionResult(MessageParcel &data,
260 MessageParcel &reply)
261 {
262 HILOG_DEBUG();
263
264 bool succeeded = data.ReadBool();
265 int32_t requestId = data.ReadInt32();
266
267 SetExecuteActionResult(succeeded, requestId);
268
269 return NO_ERROR;
270 }
271
HandleSetCursorPositionResult(MessageParcel & data,MessageParcel & reply)272 ErrCode AccessibilityElementOperatorCallbackStub::HandleSetCursorPositionResult(MessageParcel &data,
273 MessageParcel &reply)
274 {
275 HILOG_DEBUG();
276 int32_t cursorPosition = data.ReadInt32();
277 int32_t requestId = data.ReadInt32();
278 HILOG_INFO("[cursorPosition:%{public}d]", cursorPosition);
279 SetCursorPositionResult(cursorPosition, requestId);
280
281 return NO_ERROR;
282 }
283
ReadAccessibilityElementInfoList(MessageParcel & data,MessageParcel & reply,int32_t infoSize,std::list<AccessibilityElementInfo> & infos)284 ErrCode AccessibilityElementOperatorCallbackStub::ReadAccessibilityElementInfoList(
285 MessageParcel &data, MessageParcel &reply, int32_t infoSize, std::list<AccessibilityElementInfo> &infos)
286 {
287 if (infoSize == 0) {
288 HILOG_INFO("infoSize is 0, no element info to read");
289 return NO_ERROR;
290 }
291 size_t rawDataSize = data.ReadUint32();
292 MessageParcel tmpParcel;
293 void *buffer = nullptr;
294 // memory alloced in GetData will be released when tmpParcel destruct
295 if (!GetData(rawDataSize, data.ReadRawData(rawDataSize), buffer)) {
296 reply.WriteInt32(RET_ERR_FAILED);
297 return TRANSACTION_ERR;
298 }
299 if (!tmpParcel.ParseFrom(reinterpret_cast<uintptr_t>(buffer), rawDataSize)) {
300 reply.WriteInt32(RET_ERR_FAILED);
301 return TRANSACTION_ERR;
302 }
303 if (infoSize < 0 || infoSize > MAX_ALLOW_SIZE) {
304 reply.WriteInt32(RET_ERR_FAILED);
305 return TRANSACTION_ERR;
306 }
307 for (size_t i = 0; i < static_cast<uint32_t>(infoSize); i++) {
308 sptr<AccessibilityElementInfoParcel> info =
309 tmpParcel.ReadStrongParcelable<AccessibilityElementInfoParcel>();
310 if (info == nullptr) {
311 reply.WriteInt32(RET_ERR_FAILED);
312 return TRANSACTION_ERR;
313 }
314 infos.emplace_back(*info);
315 }
316 return NO_ERROR;
317 }
318
HandleSetSearchElementInfoBySpecificPropertyResult(MessageParcel & data,MessageParcel & reply)319 ErrCode AccessibilityElementOperatorCallbackStub::HandleSetSearchElementInfoBySpecificPropertyResult(
320 MessageParcel &data, MessageParcel &reply)
321 {
322 HILOG_DEBUG();
323 int32_t requestId = data.ReadInt32();
324 int32_t infoSize = data.ReadInt32();
325
326 std::list<AccessibilityElementInfo> infos;
327 ErrCode result = ReadAccessibilityElementInfoList(data, reply, infoSize, infos);
328 if (result != NO_ERROR) {
329 return result;
330 }
331 int32_t treeInfoSize = data.ReadInt32();
332 std::list<AccessibilityElementInfo> treeInfos;
333 result = ReadAccessibilityElementInfoList(data, reply, treeInfoSize, treeInfos);
334 if (result != NO_ERROR) {
335 return result;
336 }
337 reply.WriteInt32(RET_OK);
338 SetSearchElementInfoBySpecificPropertyResult(infos, treeInfos, requestId);
339 return NO_ERROR;
340 }
341 } // namespace Accessibility
342 } // namespace OHOS