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 
22 #define SWITCH_BEGIN(code) switch (code) {
23 #define SWITCH_CASE(case_code, func) case case_code:\
24     {\
25         result_code = func(data, reply);\
26         break;\
27     }
28 
29 #define SWITCH_END() default:\
30     {\
31         result_code = ERR_CODE_DEFAULT;\
32         HILOG_WARN("AccessibilityElementOperatorCallbackStub::OnRemoteRequest, default case, need check."); \
33         break;\
34     }\
35 }
36 
37 #define ACCESSIBILITY_ELEMENT_OPERATOR_CALLBACK_STUB_CASES() \
38     SWITCH_CASE( \
39         AccessibilityInterfaceCode::SET_RESULT_BY_ACCESSIBILITY_ID, HandleSetSearchElementInfoByAccessibilityIdResult)\
40     SWITCH_CASE(AccessibilityInterfaceCode::SET_RESULT_BY_TEXT, HandleSetSearchElementInfoByTextResult)\
41     SWITCH_CASE(AccessibilityInterfaceCode::SET_RESULT_FOCUSED_INFO, HandleSetFindFocusedElementInfoResult)\
42     SWITCH_CASE(AccessibilityInterfaceCode::SET_RESULT_FOCUS_MOVE, HandleSetFocusMoveSearchResult)\
43     SWITCH_CASE(AccessibilityInterfaceCode::SET_RESULT_PERFORM_ACTION, HandleSetExecuteActionResult)\
44     SWITCH_CASE(AccessibilityInterfaceCode::SET_RESULT_CURSOR_RESULT, HandleSetCursorPositionResult)\
45 
46 namespace OHOS {
47 namespace Accessibility {
48 
49 constexpr int32_t SINGLE_TRANSMIT = -2;
50 constexpr int32_t MULTI_TRANSMIT_FINISH = -1;
51 constexpr int32_t ERR_CODE_DEFAULT = -1000;
52 
WriteData(std::vector<AccessibilityElementInfo> & infos)53 void StoreElementData::WriteData(std::vector<AccessibilityElementInfo> &infos)
54 {
55     HILOG_DEBUG();
56     std::lock_guard<ffrt::mutex> lock(mutex_);
57     storeData_.insert(storeData_.end(), infos.begin(), infos.end());
58 }
59 
Clear()60 void StoreElementData::Clear()
61 {
62     HILOG_DEBUG();
63     std::lock_guard<ffrt::mutex> lock(mutex_);
64     storeData_.clear();
65 }
66 
ReadData()67 std::vector<AccessibilityElementInfo> StoreElementData::ReadData()
68 {
69     HILOG_DEBUG();
70     std::lock_guard<ffrt::mutex> lock(mutex_);
71     return storeData_;
72 }
73 
Size()74 size_t StoreElementData::Size()
75 {
76     HILOG_DEBUG();
77     std::lock_guard<ffrt::mutex> lock(mutex_);
78     return storeData_.size();
79 }
80 
AccessibilityElementOperatorCallbackStub()81 AccessibilityElementOperatorCallbackStub::AccessibilityElementOperatorCallbackStub()
82 {
83 }
84 
85 StoreElementData AccessibilityElementOperatorCallbackStub::storeElementData;
86 
~AccessibilityElementOperatorCallbackStub()87 AccessibilityElementOperatorCallbackStub::~AccessibilityElementOperatorCallbackStub()
88 {
89 }
90 
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)91 int AccessibilityElementOperatorCallbackStub::OnRemoteRequest(uint32_t code, MessageParcel &data,
92     MessageParcel &reply, MessageOption &option)
93 {
94     HILOG_DEBUG("cmd = %{public}u, flags= %{public}d", code, option.GetFlags());
95     std::u16string descriptor = AccessibilityElementOperatorCallbackStub::GetDescriptor();
96     std::u16string remoteDescriptor = data.ReadInterfaceToken();
97     if (descriptor != remoteDescriptor) {
98         HILOG_ERROR("AccessibilityElementOperatorCallbackStub::OnRemoteRequest"
99             "local descriptor is not equal to remote");
100         return ERR_INVALID_STATE;
101     }
102 
103     ErrCode result_code = ERR_NONE;
104     SWITCH_BEGIN(code)
105     ACCESSIBILITY_ELEMENT_OPERATOR_CALLBACK_STUB_CASES()
106     SWITCH_END()
107 
108     if (result_code != ERR_CODE_DEFAULT) {
109         return result_code;
110     }
111 
112     return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
113 }
114 
HandleSetSearchElementInfoByAccessibilityIdResult(MessageParcel & data,MessageParcel & reply)115 ErrCode AccessibilityElementOperatorCallbackStub::HandleSetSearchElementInfoByAccessibilityIdResult(
116     MessageParcel &data, MessageParcel &reply)
117 {
118     HILOG_DEBUG();
119     int32_t flag = data.ReadInt32();
120     if (flag == SINGLE_TRANSMIT || flag == 0) {
121         storeElementData.Clear();
122     }
123 
124     int32_t accessibilityInfosize = data.ReadInt32();
125     std::vector<AccessibilityElementInfo> tmpData;
126     bool verifyResult = ContainerSecurityVerify(data, accessibilityInfosize, tmpData.max_size());
127     if (!verifyResult || accessibilityInfosize < 0 || accessibilityInfosize > INT32_MAX) {
128         return TRANSACTION_ERR;
129     }
130     for (int32_t i = 0; i < accessibilityInfosize; i++) {
131         sptr<AccessibilityElementInfoParcel> accessibilityInfo =
132             data.ReadStrongParcelable<AccessibilityElementInfoParcel>();
133         if (accessibilityInfo == nullptr) {
134             HILOG_ERROR("ReadStrongParcelable<accessibilityInfo> failed");
135             storeElementData.Clear();
136             reply.WriteInt32(RET_ERR_FAILED);
137             return TRANSACTION_ERR;
138         }
139         tmpData.push_back(*accessibilityInfo);
140     }
141 
142     storeElementData.WriteData(tmpData); // get all data and push once
143     int32_t requestId = data.ReadInt32();
144     if (flag == SINGLE_TRANSMIT || flag == MULTI_TRANSMIT_FINISH) {
145         reply.WriteInt32(0);
146         HILOG_DEBUG("infos size %{public}zu, requestId %{public}d", storeElementData.Size(), requestId);
147         SetSearchElementInfoByAccessibilityIdResult(storeElementData.ReadData(), requestId);
148         return NO_ERROR;
149     }
150 
151     reply.WriteInt32(0);
152     return NO_ERROR;
153 }
154 
HandleSetSearchElementInfoByTextResult(MessageParcel & data,MessageParcel & reply)155 ErrCode AccessibilityElementOperatorCallbackStub::HandleSetSearchElementInfoByTextResult(
156     MessageParcel &data, MessageParcel &reply)
157 {
158     HILOG_DEBUG();
159     std::vector<AccessibilityElementInfo> infos {};
160     int32_t accessibilityInfosize = data.ReadInt32();
161     bool verifyResult = ContainerSecurityVerify(data, accessibilityInfosize, infos.max_size());
162     if (!verifyResult || accessibilityInfosize < 0 || accessibilityInfosize > INT32_MAX) {
163         return TRANSACTION_ERR;
164     }
165     for (int32_t i = 0; i < accessibilityInfosize; i++) {
166         sptr<AccessibilityElementInfoParcel> accessibilityInfo =
167             data.ReadStrongParcelable<AccessibilityElementInfoParcel>();
168         if (accessibilityInfo == nullptr) {
169             HILOG_ERROR("ReadStrongParcelable<accessibilityInfo> failed");
170             return TRANSACTION_ERR;
171         }
172         infos.emplace_back(*accessibilityInfo);
173     }
174     int32_t requestId = data.ReadInt32();
175 
176     SetSearchElementInfoByTextResult(infos, requestId);
177 
178     return NO_ERROR;
179 }
180 
HandleSetFindFocusedElementInfoResult(MessageParcel & data,MessageParcel & reply)181 ErrCode AccessibilityElementOperatorCallbackStub::HandleSetFindFocusedElementInfoResult(MessageParcel &data,
182     MessageParcel &reply)
183 {
184     HILOG_DEBUG();
185     sptr<AccessibilityElementInfoParcel> info = data.ReadStrongParcelable<AccessibilityElementInfoParcel>();
186     if (info == nullptr) {
187         HILOG_ERROR("ReadStrongParcelable<AccessibilityElementInfo> failed");
188         return TRANSACTION_ERR;
189     }
190 
191     int32_t requestId = data.ReadInt32();
192 
193     SetFindFocusedElementInfoResult(*info, requestId);
194 
195     return NO_ERROR;
196 }
197 
HandleSetFocusMoveSearchResult(MessageParcel & data,MessageParcel & reply)198 ErrCode AccessibilityElementOperatorCallbackStub::HandleSetFocusMoveSearchResult(MessageParcel &data,
199     MessageParcel &reply)
200 {
201     HILOG_DEBUG();
202     sptr<AccessibilityElementInfoParcel> info = data.ReadStrongParcelable<AccessibilityElementInfoParcel>();
203     if (info == nullptr) {
204         HILOG_ERROR("ReadStrongParcelable<AccessibilityElementInfo> failed");
205         return TRANSACTION_ERR;
206     }
207 
208     int32_t requestId = data.ReadInt32();
209 
210     SetFocusMoveSearchResult(*info, requestId);
211 
212     return NO_ERROR;
213 }
214 
HandleSetExecuteActionResult(MessageParcel & data,MessageParcel & reply)215 ErrCode AccessibilityElementOperatorCallbackStub::HandleSetExecuteActionResult(MessageParcel &data,
216     MessageParcel &reply)
217 {
218     HILOG_DEBUG();
219 
220     bool succeeded = data.ReadBool();
221     int32_t requestId = data.ReadInt32();
222 
223     SetExecuteActionResult(succeeded, requestId);
224 
225     return NO_ERROR;
226 }
227 
HandleSetCursorPositionResult(MessageParcel & data,MessageParcel & reply)228 ErrCode AccessibilityElementOperatorCallbackStub::HandleSetCursorPositionResult(MessageParcel &data,
229     MessageParcel &reply)
230 {
231     HILOG_DEBUG();
232     int32_t cursorPosition = data.ReadInt32();
233     int32_t requestId = data.ReadInt32();
234     HILOG_INFO("[cursorPosition:%{public}d]", cursorPosition);
235     SetCursorPositionResult(cursorPosition, requestId);
236 
237     return NO_ERROR;
238 }
239 
240 } // namespace Accessibility
241 } // namespace OHOS