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 "accessible_ability_channel_proxy.h"
17
18#include <cinttypes>
19
20#include "accessibility_element_info_parcel.h"
21#include "accessibility_gesture_inject_path_parcel.h"
22#include "accessibility_ipc_interface_code.h"
23#include "accessibility_window_info_parcel.h"
24#include "hilog_wrapper.h"
25
26namespace OHOS {
27namespace Accessibility {
28AccessibleAbilityChannelProxy::AccessibleAbilityChannelProxy(
29    const sptr<IRemoteObject> &object): IRemoteProxy<IAccessibleAbilityChannel>(object)
30{
31}
32
33bool AccessibleAbilityChannelProxy::WriteInterfaceToken(MessageParcel &data)
34{
35    HILOG_DEBUG();
36
37    if (!data.WriteInterfaceToken(AccessibleAbilityChannelProxy::GetDescriptor())) {
38        HILOG_ERROR("write interface token failed");
39        return false;
40    }
41    return true;
42}
43
44bool AccessibleAbilityChannelProxy::SendTransactCmd(AccessibilityInterfaceCode code,
45    MessageParcel &data, MessageParcel &reply, MessageOption &option)
46{
47    HILOG_DEBUG();
48
49    sptr<IRemoteObject> remoteChannelProxy = Remote();
50    if (remoteChannelProxy == nullptr) {
51        HILOG_ERROR("fail to send transact cmd %{public}d due to remote object", code);
52        return false;
53    }
54    int32_t resultChannelProxy = remoteChannelProxy->SendRequest(static_cast<uint32_t>(code), data, reply, option);
55    if (resultChannelProxy != NO_ERROR) {
56        HILOG_ERROR("receive error transact code %{public}d in transact cmd %{public}d", resultChannelProxy, code);
57        return false;
58    }
59    return true;
60}
61
62RetError AccessibleAbilityChannelProxy::SearchElementInfoByAccessibilityId(const ElementBasicInfo elementBasicInfo,
63    const int32_t requestId, const sptr<IAccessibilityElementOperatorCallback> &callback,
64    const int32_t mode, bool isFilter)
65{
66    HILOG_DEBUG();
67    if (callback == nullptr) {
68        HILOG_ERROR("callback is nullptr.");
69        return RET_ERR_INVALID_PARAM;
70    }
71
72    MessageParcel data;
73    MessageParcel reply;
74    MessageOption option;
75
76    if (!WriteInterfaceToken(data)) {
77        return RET_ERR_IPC_FAILED;
78    }
79    if (!data.WriteInt32(elementBasicInfo.windowId)) {
80        HILOG_ERROR("windowId write error: %{public}d, ", elementBasicInfo.windowId);
81        return RET_ERR_IPC_FAILED;
82    }
83    if (!data.WriteInt32(elementBasicInfo.treeId)) {
84        HILOG_ERROR("treeId write error: %{public}d", elementBasicInfo.treeId);
85        return RET_ERR_IPC_FAILED;
86    }
87    if (!data.WriteInt64(elementBasicInfo.elementId)) {
88        HILOG_ERROR("elementId write error: %{public}" PRId64 "", elementBasicInfo.elementId);
89        return RET_ERR_IPC_FAILED;
90    }
91    if (!data.WriteInt32(requestId)) {
92        HILOG_ERROR("requestId write error: %{public}d, ", requestId);
93        return RET_ERR_IPC_FAILED;
94    }
95    if (!data.WriteRemoteObject(callback->AsObject())) {
96        HILOG_ERROR("callback write error");
97        return RET_ERR_IPC_FAILED;
98    }
99    if (!data.WriteInt32(mode)) {
100        HILOG_ERROR("mode write error: %{public}d, ", mode);
101        return RET_ERR_IPC_FAILED;
102    }
103    if (!data.WriteBool(isFilter)) {
104        HILOG_ERROR("isFilter write error: %{public}d, ", isFilter);
105        return RET_ERR_IPC_FAILED;
106    }
107    if (!SendTransactCmd(AccessibilityInterfaceCode::SEARCH_ELEMENTINFO_BY_ACCESSIBILITY_ID,
108        data, reply, option)) {
109        HILOG_ERROR("fail to find elementInfo by elementId");
110        return RET_ERR_IPC_FAILED;
111    }
112    return static_cast<RetError>(reply.ReadInt32());
113}
114
115RetError AccessibleAbilityChannelProxy::SearchElementInfosByText(const int32_t accessibilityWindowId,
116    const int64_t elementId, const std::string &text, const int32_t requestId,
117    const sptr<IAccessibilityElementOperatorCallback> &callback)
118{
119    HILOG_DEBUG();
120
121    if (callback == nullptr) {
122        HILOG_ERROR("callback is nullptr.");
123        return RET_ERR_INVALID_PARAM;
124    }
125
126    MessageParcel data;
127    MessageParcel reply;
128    MessageOption option;
129
130    if (!WriteInterfaceToken(data)) {
131        return RET_ERR_IPC_FAILED;
132    }
133    if (!data.WriteInt32(accessibilityWindowId)) {
134        HILOG_ERROR("accessibilityWindowId write error: %{public}d, ", accessibilityWindowId);
135        return RET_ERR_IPC_FAILED;
136    }
137    if (!data.WriteInt64(elementId)) {
138        HILOG_ERROR("elementId write error: %{public}" PRId64 "", elementId);
139        return RET_ERR_IPC_FAILED;
140    }
141    if (!data.WriteString(text)) {
142        HILOG_ERROR("text write error: %{public}s, ", text.c_str());
143        return RET_ERR_IPC_FAILED;
144    }
145    if (!data.WriteInt32(requestId)) {
146        HILOG_ERROR("requestId write error: %{public}d, ", requestId);
147        return RET_ERR_IPC_FAILED;
148    }
149    if (!data.WriteRemoteObject(callback->AsObject())) {
150        HILOG_ERROR("callback write error");
151        return RET_ERR_IPC_FAILED;
152    }
153
154    if (!SendTransactCmd(AccessibilityInterfaceCode::SEARCH_ELEMENTINFOS_BY_TEXT,
155        data, reply, option)) {
156        HILOG_ERROR("fail to find elementInfo by text");
157        return RET_ERR_IPC_FAILED;
158    }
159    return static_cast<RetError>(reply.ReadInt32());
160}
161
162RetError AccessibleAbilityChannelProxy::FindFocusedElementInfo(const int32_t accessibilityWindowId,
163    const int64_t elementId, const int32_t focusType, const int32_t requestId,
164    const sptr<IAccessibilityElementOperatorCallback> &callback)
165{
166    HILOG_DEBUG();
167    if (callback == nullptr) {
168        HILOG_ERROR("callback is nullptr.");
169        return RET_ERR_INVALID_PARAM;
170    }
171
172    MessageParcel data;
173    MessageParcel reply;
174    MessageOption option;
175
176    if (!WriteInterfaceToken(data)) {
177        return RET_ERR_IPC_FAILED;
178    }
179    if (!data.WriteInt32(accessibilityWindowId)) {
180        HILOG_ERROR("accessibilityWindowId write error: %{public}d, ", accessibilityWindowId);
181        return RET_ERR_IPC_FAILED;
182    }
183    if (!data.WriteInt64(elementId)) {
184        HILOG_ERROR("elementId write error: %{public}" PRId64 "", elementId);
185        return RET_ERR_IPC_FAILED;
186    }
187    if (!data.WriteInt32(focusType)) {
188        HILOG_ERROR("focusType write error: %{public}d, ", focusType);
189        return RET_ERR_IPC_FAILED;
190    }
191    if (!data.WriteInt32(requestId)) {
192        HILOG_ERROR("requestId write error: %{public}d, ", requestId);
193        return RET_ERR_IPC_FAILED;
194    }
195    if (!data.WriteRemoteObject(callback->AsObject())) {
196        HILOG_ERROR("callback write error");
197        return RET_ERR_IPC_FAILED;
198    }
199
200    if (!SendTransactCmd(AccessibilityInterfaceCode::FIND_FOCUSED_ELEMENTINFO, data, reply, option)) {
201        HILOG_ERROR("fail to gain focus");
202        return RET_ERR_IPC_FAILED;
203    }
204    return static_cast<RetError>(reply.ReadInt32());
205}
206
207RetError AccessibleAbilityChannelProxy::FocusMoveSearch(const int32_t accessibilityWindowId, const int64_t elementId,
208    const int32_t direction, const int32_t requestId, const sptr<IAccessibilityElementOperatorCallback> &callback)
209{
210    HILOG_DEBUG();
211    if (callback == nullptr) {
212        HILOG_ERROR("callback is nullptr.");
213        return RET_ERR_INVALID_PARAM;
214    }
215
216    MessageParcel data;
217    MessageParcel reply;
218    MessageOption option;
219
220    if (!WriteInterfaceToken(data)) {
221        return RET_ERR_IPC_FAILED;
222    }
223    if (!data.WriteInt32(accessibilityWindowId)) {
224        HILOG_ERROR("accessibilityWindowId write error: %{public}d, ", accessibilityWindowId);
225        return RET_ERR_IPC_FAILED;
226    }
227    if (!data.WriteInt64(elementId)) {
228        HILOG_ERROR("elementId write error: %{public}" PRId64 "", elementId);
229        return RET_ERR_IPC_FAILED;
230    }
231    if (!data.WriteInt32(direction)) {
232        HILOG_ERROR("direction write error: %{public}d, ", direction);
233        return RET_ERR_IPC_FAILED;
234    }
235    if (!data.WriteInt32(requestId)) {
236        HILOG_ERROR("requestId write error: %{public}d, ", requestId);
237        return RET_ERR_IPC_FAILED;
238    }
239    if (!data.WriteRemoteObject(callback->AsObject())) {
240        HILOG_ERROR("callback write error");
241        return RET_ERR_IPC_FAILED;
242    }
243
244    if (!SendTransactCmd(AccessibilityInterfaceCode::FOCUS_MOVE_SEARCH, data, reply, option)) {
245        HILOG_ERROR("fail to search focus");
246        return RET_ERR_IPC_FAILED;
247    }
248    return static_cast<RetError>(reply.ReadInt32());
249}
250
251RetError AccessibleAbilityChannelProxy::EnableScreenCurtain(bool isEnable)
252{
253    HILOG_DEBUG();
254
255    MessageParcel data;
256    MessageParcel reply;
257    MessageOption option;
258
259    if (!WriteInterfaceToken(data)) {
260        return RET_ERR_IPC_FAILED;
261    }
262    if (!data.WriteBool(isEnable)) {
263        HILOG_ERROR("isEnable write error: %{public}d, ", isEnable);
264        return RET_ERR_IPC_FAILED;
265    }
266    if (!SendTransactCmd(AccessibilityInterfaceCode::SET_CURTAIN_SCREEN,
267        data, reply, option)) {
268        HILOG_ERROR("fail to enable screen curtain");
269        return RET_ERR_IPC_FAILED;
270    }
271
272    return static_cast<RetError>(reply.ReadInt32());
273}
274
275RetError AccessibleAbilityChannelProxy::ExecuteAction(const int32_t accessibilityWindowId, const int64_t elementId,
276    const int32_t action, const std::map<std::string, std::string> &actionArguments, const int32_t requestId,
277    const sptr<IAccessibilityElementOperatorCallback> &callback)
278{
279    HILOG_DEBUG();
280
281    MessageParcel data;
282    MessageParcel reply;
283    MessageOption option;
284
285    if (!WriteInterfaceToken(data)) {
286        return RET_ERR_IPC_FAILED;
287    }
288    if (!data.WriteInt32(accessibilityWindowId)) {
289        HILOG_ERROR("accessibilityWindowId write error: %{public}d, ", accessibilityWindowId);
290        return RET_ERR_IPC_FAILED;
291    }
292    if (!data.WriteInt64(elementId)) {
293        HILOG_ERROR("elementId write error: %{public}" PRId64 "", elementId);
294        return RET_ERR_IPC_FAILED;
295    }
296    if (!data.WriteInt32(action)) {
297        HILOG_ERROR("action write error: %{public}d, ", action);
298        return RET_ERR_IPC_FAILED;
299    }
300
301    std::vector<std::string> actionArgumentsKey {};
302    std::vector<std::string> actionArgumentsValue {};
303    for (auto iter = actionArguments.begin(); iter != actionArguments.end(); iter++) {
304        actionArgumentsKey.push_back(iter->first);
305        actionArgumentsValue.push_back(iter->second);
306    }
307    if (!data.WriteStringVector(actionArgumentsKey)) {
308        HILOG_ERROR("actionArgumentsKey write error");
309        return RET_ERR_IPC_FAILED;
310    }
311    if (!data.WriteStringVector(actionArgumentsValue)) {
312        HILOG_ERROR("actionArgumentsValue write error");
313        return RET_ERR_IPC_FAILED;
314    }
315
316    if (!data.WriteInt32(requestId)) {
317        HILOG_ERROR("requestId write error: %{public}d, ", requestId);
318        return RET_ERR_IPC_FAILED;
319    }
320    if (callback == nullptr || !data.WriteRemoteObject(callback->AsObject())) {
321        HILOG_ERROR("callback write error");
322        return RET_ERR_IPC_FAILED;
323    }
324
325    if (!SendTransactCmd(AccessibilityInterfaceCode::PERFORM_ACTION,
326        data, reply, option)) {
327        HILOG_ERROR("fail to perform accessibility action");
328        return RET_ERR_IPC_FAILED;
329    }
330    return static_cast<RetError>(reply.ReadInt32());
331}
332
333RetError AccessibleAbilityChannelProxy::GetWindow(const int32_t windowId, AccessibilityWindowInfo &windowInfo)
334{
335    HILOG_DEBUG();
336
337    MessageParcel data;
338    MessageParcel reply;
339    MessageOption option;
340
341    if (!WriteInterfaceToken(data)) {
342        return RET_ERR_IPC_FAILED;
343    }
344
345    if (!data.WriteInt32(windowId)) {
346        HILOG_ERROR("windowId write error: %{public}d, ", windowId);
347        return RET_ERR_IPC_FAILED;
348    }
349
350    if (!SendTransactCmd(AccessibilityInterfaceCode::GET_WINDOW, data, reply, option)) {
351        HILOG_ERROR("fail to get window");
352        return RET_ERR_IPC_FAILED;
353    }
354
355    sptr<AccessibilityWindowInfoParcel> windowInfoParcel = reply.ReadStrongParcelable<AccessibilityWindowInfoParcel>();
356    if (windowInfoParcel == nullptr) {
357        HILOG_ERROR("ReadStrongParcelable<AccessibilityWindowInfoParcel> failed");
358        return RET_ERR_IPC_FAILED;
359    }
360    windowInfo = *windowInfoParcel;
361
362    return static_cast<RetError>(reply.ReadInt32());
363}
364
365RetError AccessibleAbilityChannelProxy::GetWindows(std::vector<AccessibilityWindowInfo> &windows)
366{
367    HILOG_DEBUG();
368    MessageParcel data;
369    MessageParcel reply;
370    MessageOption option;
371
372    if (!WriteInterfaceToken(data)) {
373        return RET_ERR_IPC_FAILED;
374    }
375
376    if (!SendTransactCmd(AccessibilityInterfaceCode::GET_WINDOWS, data, reply, option)) {
377        HILOG_ERROR("fail to get windows");
378        return RET_ERR_IPC_FAILED;
379    }
380
381    int32_t windowsSize = reply.ReadInt32();
382    if (windowsSize < 0 || windowsSize > INT32_MAX) {
383        HILOG_ERROR("windowsSize is invalid");
384        return RET_ERR_INVALID_PARAM;
385    }
386
387    for (int32_t i = 0; i < windowsSize; i++) {
388        sptr<AccessibilityWindowInfoParcel> window = reply.ReadStrongParcelable<AccessibilityWindowInfoParcel>();
389        if (window == nullptr) {
390            HILOG_ERROR("ReadStrongParcelable<AccessibilityWindowInfoParcel> failed");
391            return RET_ERR_IPC_FAILED;
392        }
393        windows.emplace_back(*window);
394    }
395
396    return static_cast<RetError>(reply.ReadInt32());
397}
398
399RetError AccessibleAbilityChannelProxy::GetWindowsByDisplayId(const uint64_t displayId,
400    std::vector<AccessibilityWindowInfo> &windows)
401{
402    HILOG_DEBUG();
403
404    MessageParcel data;
405    MessageParcel reply;
406    MessageOption option;
407
408    if (!WriteInterfaceToken(data)) {
409        return RET_ERR_IPC_FAILED;
410    }
411
412    if (!data.WriteUint64(displayId)) {
413        HILOG_ERROR("displayId write error: %{public}" PRIu64 ", ", displayId);
414        return RET_ERR_IPC_FAILED;
415    }
416
417    if (!SendTransactCmd(AccessibilityInterfaceCode::GET_WINDOWS_BY_DISPLAY_ID, data, reply, option)) {
418        HILOG_ERROR("fail to get windows");
419        return RET_ERR_IPC_FAILED;
420    }
421
422    int32_t windowsSize = reply.ReadInt32();
423    if (windowsSize < 0 || windowsSize > INT32_MAX) {
424        HILOG_ERROR("windowsSize is invalid");
425        return RET_ERR_INVALID_PARAM;
426    }
427
428    for (int32_t i = 0; i < windowsSize; i++) {
429        sptr<AccessibilityWindowInfoParcel> window = reply.ReadStrongParcelable<AccessibilityWindowInfoParcel>();
430        if (window == nullptr) {
431            HILOG_ERROR("ReadStrongParcelable<AccessibilityWindowInfoParcel> failed");
432            return RET_ERR_IPC_FAILED;
433        }
434        windows.emplace_back(*window);
435    }
436
437    return static_cast<RetError>(reply.ReadInt32());
438}
439
440void AccessibleAbilityChannelProxy::SetOnKeyPressEventResult(const bool handled, const int32_t sequence)
441{
442    HILOG_DEBUG();
443
444    MessageParcel data;
445    MessageParcel reply;
446    MessageOption option(MessageOption::TF_ASYNC);
447
448    if (!WriteInterfaceToken(data)) {
449        return;
450    }
451    if (!data.WriteBool(handled)) {
452        HILOG_ERROR("handled write error: %{public}d, ", handled);
453        return;
454    }
455    if (!data.WriteInt32(sequence)) {
456        HILOG_ERROR("sequence write error: %{public}d, ", sequence);
457        return;
458    }
459    if (!SendTransactCmd(AccessibilityInterfaceCode::SET_ON_KEY_PRESS_EVENT_RESULT,
460        data, reply, option)) {
461        HILOG_ERROR("fail to set onKeyPressEvent result");
462    }
463}
464
465RetError AccessibleAbilityChannelProxy::GetCursorPosition(const int32_t accessibilityWindowId, const int64_t elementId,
466    const int32_t requestId, const sptr<IAccessibilityElementOperatorCallback> &callback)
467{
468    HILOG_DEBUG();
469
470    MessageParcel data;
471    MessageParcel reply;
472    MessageOption option(MessageOption::TF_ASYNC);
473    if (!WriteInterfaceToken(data)) {
474        return RET_ERR_FAILED;
475    }
476    if (!data.WriteInt32(accessibilityWindowId)) {
477        HILOG_ERROR("accessibilityWindowId write error: %{public}d, ", accessibilityWindowId);
478        return RET_ERR_FAILED;
479    }
480    if (!data.WriteInt64(elementId)) {
481        HILOG_ERROR("elementId write error");
482        return RET_ERR_FAILED;
483    }
484    if (!data.WriteInt32(requestId)) {
485        HILOG_ERROR("requestId write error: %{public}d, ", requestId);
486        return RET_ERR_IPC_FAILED;
487    }
488    if (callback == nullptr) {
489        HILOG_ERROR("callback is null");
490        return RET_ERR_FAILED;
491    }
492    if (callback->AsObject() == nullptr) {
493        HILOG_ERROR("callback->AsObject() is null");
494        return RET_ERR_FAILED;
495    }
496    if (!data.WriteRemoteObject(callback->AsObject())) {
497        HILOG_ERROR("callback write error");
498        return RET_ERR_IPC_FAILED;
499    }
500    if (!SendTransactCmd(AccessibilityInterfaceCode::GET_CURSOR_POSITION,
501        data, reply, option)) {
502        HILOG_ERROR("fail to set onKeyPressEvent result");
503        return RET_ERR_FAILED;
504    }
505
506    return static_cast<RetError>(reply.ReadInt32());
507}
508
509RetError AccessibleAbilityChannelProxy::SendSimulateGesture(
510    const std::shared_ptr<AccessibilityGestureInjectPath>& gesturePath)
511{
512    HILOG_DEBUG();
513    sptr<AccessibilityGestureInjectPathParcel> path =
514        new(std::nothrow) AccessibilityGestureInjectPathParcel(*gesturePath);
515    if (path == nullptr) {
516        HILOG_ERROR("Failed to create path.");
517        return RET_ERR_NULLPTR;
518    }
519
520    MessageParcel data;
521    MessageParcel reply;
522    MessageOption option(MessageOption::TF_SYNC);
523
524    if (!WriteInterfaceToken(data)) {
525        return RET_ERR_IPC_FAILED;
526    }
527
528    if (!data.WriteStrongParcelable(path)) {
529        HILOG_ERROR("WriteStrongParcelable<AccessibilityGestureInjectPathParcel> failed");
530        return RET_ERR_IPC_FAILED;
531    }
532
533    if (!SendTransactCmd(AccessibilityInterfaceCode::SEND_SIMULATE_GESTURE_PATH, data, reply, option)) {
534        HILOG_ERROR("fail to send simulation gesture path");
535        return RET_ERR_IPC_FAILED;
536    }
537    return static_cast<RetError>(reply.ReadInt32());
538}
539
540RetError AccessibleAbilityChannelProxy::SetTargetBundleName(const std::vector<std::string> &targetBundleNames)
541{
542    HILOG_DEBUG();
543
544    MessageParcel data;
545    MessageParcel reply;
546    MessageOption option(MessageOption::TF_SYNC);
547
548    if (!WriteInterfaceToken(data)) {
549        return RET_ERR_IPC_FAILED;
550    }
551    if (!data.WriteInt32(targetBundleNames.size())) {
552        HILOG_ERROR("targetBundleNames.size() write error: %{public}zu, ", targetBundleNames.size());
553        return RET_ERR_IPC_FAILED;
554    }
555    for (auto &targetBundleName : targetBundleNames) {
556        if (!data.WriteString(targetBundleName)) {
557            HILOG_ERROR("targetBundleName write error: %{public}s, ", targetBundleName.c_str());
558            return RET_ERR_IPC_FAILED;
559        }
560    }
561    if (!SendTransactCmd(AccessibilityInterfaceCode::SET_TARGET_BUNDLE_NAME, data, reply, option)) {
562        HILOG_ERROR("fail to set target bundle name filter");
563        return RET_ERR_IPC_FAILED;
564    }
565    return static_cast<RetError>(reply.ReadInt32());
566}
567} // namespace Accessibility
568} // namespace OHOS