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_proxy.h"
17 #include "accessibility_element_info_parcel.h"
18 #include "hilog_wrapper.h"
19
20 namespace OHOS {
21 namespace Accessibility {
22
23 constexpr int32_t IPC_MEMORY_SIZE = 500 * 1024; // default size is 200 * 1024B, batch query need more memory
24 constexpr int32_t SINGLE_TRANSMIT = -2;
25 constexpr int32_t MULTI_TRANSMIT_FINISH = -1;
26 constexpr int32_t DATA_NUMBER_ONE_TIME = 400;
27
AccessibilityElementOperatorCallbackProxy(const sptr<IRemoteObject> & impl)28 AccessibilityElementOperatorCallbackProxy::AccessibilityElementOperatorCallbackProxy(
29 const sptr<IRemoteObject> &impl) : IRemoteProxy<IAccessibilityElementOperatorCallback>(impl)
30 {}
31
~AccessibilityElementOperatorCallbackProxy()32 AccessibilityElementOperatorCallbackProxy::~AccessibilityElementOperatorCallbackProxy()
33 {}
34
WriteInterfaceToken(MessageParcel & data)35 bool AccessibilityElementOperatorCallbackProxy::WriteInterfaceToken(MessageParcel &data)
36 {
37 HILOG_DEBUG();
38 if (!data.WriteInterfaceToken(AccessibilityElementOperatorCallbackProxy::GetDescriptor())) {
39 HILOG_ERROR("write interface token failed");
40 return false;
41 }
42 return true;
43 }
44
SendTransactCmd(AccessibilityInterfaceCode code,MessageParcel & data,MessageParcel & reply,MessageOption & option)45 bool AccessibilityElementOperatorCallbackProxy::SendTransactCmd(AccessibilityInterfaceCode code,
46 MessageParcel &data, MessageParcel &reply, MessageOption &option)
47 {
48 HILOG_DEBUG();
49
50 sptr<IRemoteObject> remoteObj = Remote();
51 if (remoteObj == nullptr) {
52 HILOG_ERROR("fail to send transact cmd %{public}d due to remote object", code);
53 return false;
54 }
55 int32_t ret = remoteObj->SendRequest(static_cast<uint32_t>(code), data, reply, option);
56 if (ret != NO_ERROR) {
57 HILOG_ERROR("receive error transact code %{public}d in transact cmd %{public}d", ret, code);
58 return false;
59 }
60 return true;
61 }
62
GetTransmitFlag(int32_t time,int32_t leftSize)63 int32_t AccessibilityElementOperatorCallbackProxy::GetTransmitFlag(int32_t time, int32_t leftSize)
64 {
65 int32_t flag = time;
66 if (time == 0 && leftSize <= DATA_NUMBER_ONE_TIME) {
67 flag = SINGLE_TRANSMIT;
68 } else if (leftSize <= DATA_NUMBER_ONE_TIME) {
69 flag = MULTI_TRANSMIT_FINISH;
70 }
71
72 return flag;
73 }
74
SetSearchElementInfoByAccessibilityIdResult(const std::vector<AccessibilityElementInfo> & infos,const int32_t requestId)75 void AccessibilityElementOperatorCallbackProxy::SetSearchElementInfoByAccessibilityIdResult(
76 const std::vector<AccessibilityElementInfo> &infos, const int32_t requestId)
77 {
78 HILOG_DEBUG("infos size %{public}zu, resquestId %{public}d", infos.size(), requestId);
79 int32_t leftSize = static_cast<int32_t>(infos.size());
80 int32_t time = 0;
81 int32_t index = 0;
82 while (leftSize >= 0) {
83 MessageParcel data;
84 MessageParcel reply;
85 MessageOption type = MessageOption::TF_SYNC;
86 if (leftSize <= DATA_NUMBER_ONE_TIME) {
87 type = MessageOption::TF_ASYNC;
88 }
89 MessageOption option(type);
90 data.SetMaxCapacity(IPC_MEMORY_SIZE);
91
92 // when infos size is a multi of 800, do not send the last empty reply
93 if (leftSize == 0 && time > 0) {
94 return;
95 }
96 if (!WriteInterfaceToken(data)) {
97 return;
98 }
99
100 int32_t flag = GetTransmitFlag(time, leftSize);
101 if (!data.WriteInt32(flag)) {
102 return;
103 }
104
105 int32_t writeSize = (leftSize <= DATA_NUMBER_ONE_TIME) ? leftSize : DATA_NUMBER_ONE_TIME;
106 if (!data.WriteInt32(writeSize)) {
107 return;
108 }
109
110 for (int32_t i = 0; i < writeSize; ++i) {
111 AccessibilityElementInfoParcel infoParcel(infos[index]);
112 index++;
113 if (!data.WriteParcelable(&infoParcel)) {
114 HILOG_ERROR("accessibility element info failed index %{public}d", index);
115 return;
116 }
117 }
118
119 if (!data.WriteInt32(requestId)) {
120 return;
121 }
122
123 if (!SendTransactCmd(AccessibilityInterfaceCode::SET_RESULT_BY_ACCESSIBILITY_ID, data, reply, option)) {
124 HILOG_ERROR("set search element info by accessibility id result failed");
125 return;
126 }
127
128 leftSize -= DATA_NUMBER_ONE_TIME;
129 time++;
130 if (static_cast<RetError>(reply.ReadInt32()) != RET_OK) {
131 return;
132 }
133 }
134 }
135
SetSearchElementInfoByTextResult(const std::vector<AccessibilityElementInfo> & infos,const int32_t requestId)136 void AccessibilityElementOperatorCallbackProxy::SetSearchElementInfoByTextResult(
137 const std::vector<AccessibilityElementInfo> &infos, const int32_t requestId)
138 {
139 HILOG_DEBUG();
140 MessageParcel data;
141 MessageParcel reply;
142 MessageOption option(MessageOption::TF_ASYNC);
143
144 if (!WriteInterfaceToken(data)) {
145 HILOG_ERROR("connection write token failed");
146 return;
147 }
148
149 if (!data.WriteInt32(infos.size())) {
150 HILOG_ERROR("write infos's size failed");
151 return;
152 }
153
154 for (auto &info : infos) {
155 AccessibilityElementInfoParcel infoParcel(info);
156 if (!data.WriteParcelable(&infoParcel)) {
157 HILOG_ERROR("write accessibility element info failed");
158 return;
159 }
160 }
161
162 if (!data.WriteInt32(requestId)) {
163 HILOG_ERROR("connection write request id failed");
164 return;
165 }
166
167 if (!SendTransactCmd(AccessibilityInterfaceCode::SET_RESULT_BY_TEXT,
168 data, reply, option)) {
169 HILOG_ERROR("set search element info by text result failed");
170 return;
171 }
172 }
173
SetFindFocusedElementInfoResult(const AccessibilityElementInfo & info,const int32_t requestId)174 void AccessibilityElementOperatorCallbackProxy::SetFindFocusedElementInfoResult(
175 const AccessibilityElementInfo &info, const int32_t requestId)
176 {
177 HILOG_DEBUG();
178 MessageParcel data;
179 MessageParcel reply;
180 MessageOption option(MessageOption::TF_ASYNC);
181 AccessibilityElementInfoParcel infoParcel(info);
182
183 if (!WriteInterfaceToken(data)) {
184 HILOG_ERROR("connection write token failed");
185 return;
186 }
187
188 if (!data.WriteParcelable(&infoParcel)) {
189 HILOG_ERROR("connection write info failed");
190 return;
191 }
192 if (!data.WriteInt32(requestId)) {
193 HILOG_ERROR("connection write request id failed");
194 return;
195 }
196
197 if (!SendTransactCmd(AccessibilityInterfaceCode::SET_RESULT_FOCUSED_INFO,
198 data, reply, option)) {
199 HILOG_ERROR("set find focused element info result failed");
200 return;
201 }
202 }
203
SetFocusMoveSearchResult(const AccessibilityElementInfo & info,const int32_t requestId)204 void AccessibilityElementOperatorCallbackProxy::SetFocusMoveSearchResult(const AccessibilityElementInfo &info,
205 const int32_t requestId)
206 {
207 HILOG_DEBUG();
208 MessageParcel data;
209 MessageParcel reply;
210 MessageOption option(MessageOption::TF_ASYNC);
211 AccessibilityElementInfoParcel infoParcel(info);
212
213 if (!WriteInterfaceToken(data)) {
214 HILOG_ERROR("connection write token failed");
215 return;
216 }
217
218 if (!data.WriteParcelable(&infoParcel)) {
219 HILOG_ERROR("connection write info failed");
220 return;
221 }
222
223 if (!data.WriteInt32(requestId)) {
224 HILOG_ERROR("connection write requestId failed");
225 return;
226 }
227
228 if (!SendTransactCmd(AccessibilityInterfaceCode::SET_RESULT_FOCUS_MOVE,
229 data, reply, option)) {
230 HILOG_ERROR("set focus move search result failed");
231 return;
232 }
233 }
234
SetExecuteActionResult(const bool succeeded,const int32_t requestId)235 void AccessibilityElementOperatorCallbackProxy::SetExecuteActionResult(const bool succeeded, const int32_t requestId)
236 {
237 HILOG_DEBUG();
238 MessageParcel data;
239 MessageParcel reply;
240 MessageOption option(MessageOption::TF_ASYNC);
241
242 if (!WriteInterfaceToken(data)) {
243 HILOG_ERROR("connection write token failed");
244 return;
245 }
246
247 if (!data.WriteBool(succeeded)) {
248 HILOG_ERROR("connection write failed");
249 return;
250 }
251
252 if (!data.WriteInt32(requestId)) {
253 HILOG_ERROR("connection write request id failed");
254 return;
255 }
256
257 if (!SendTransactCmd(AccessibilityInterfaceCode::SET_RESULT_PERFORM_ACTION,
258 data, reply, option)) {
259 HILOG_ERROR("set execute action result failed");
260 return;
261 }
262 }
263
SetCursorPositionResult(const int32_t cursorPosition,const int32_t requestId)264 void AccessibilityElementOperatorCallbackProxy::SetCursorPositionResult(const int32_t cursorPosition,
265 const int32_t requestId)
266 {
267 HILOG_DEBUG();
268 MessageParcel data;
269 MessageParcel reply;
270 MessageOption option(MessageOption::TF_ASYNC);
271
272 if (!WriteInterfaceToken(data)) {
273 HILOG_ERROR("connection write token failed");
274 return;
275 }
276 HILOG_INFO(" [cursorPosition:%{public}d]", cursorPosition);
277 if (!data.WriteInt32(cursorPosition)) {
278 HILOG_ERROR("connection write failed");
279 return;
280 }
281
282 if (!data.WriteInt32(requestId)) {
283 HILOG_ERROR("connection write request id failed");
284 return;
285 }
286
287 if (!SendTransactCmd(AccessibilityInterfaceCode::SET_RESULT_CURSOR_RESULT,
288 data, reply, option)) {
289 HILOG_ERROR("set cursor position result failed");
290 return;
291 }
292 }
293
294 } // namespace Accessibility
295 } // namespace OHOS
296