1 /*
2 * Copyright (C) 2022-2023 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_client_impl.h"
17
18 #include <chrono>
19 #include <cinttypes>
20 #include <thread>
21
22 #include "accessible_ability_client.h"
23 #include "hilog_wrapper.h"
24 #include "if_system_ability_manager.h"
25 #include "iservice_registry.h"
26 #include "parameter.h"
27 #include "system_ability_definition.h"
28
29 namespace OHOS {
30 namespace Accessibility {
31 // tmp: wait for window registing when client connect done
32 constexpr int WAIT_WINDOW_REGIST = 500;
33 namespace {
34 const std::string SYSTEM_PARAMETER_AAMS_NAME = "accessibility.config.ready";
35 constexpr int32_t CONFIG_PARAMETER_VALUE_SIZE = 10;
36 constexpr int64_t ROOT_NONE_ID = -1;
37 constexpr int64_t NODE_ID_MAX = 0x7FFFFFFE;
38 std::mutex g_Mutex;
39 sptr<AccessibleAbilityClientImpl> g_Instance = nullptr;
40 } // namespace
41
GetInstance()42 sptr<AccessibleAbilityClient> AccessibleAbilityClient::GetInstance()
43 {
44 HILOG_DEBUG();
45 std::lock_guard<std::mutex> lock(g_Mutex);
46 if (!g_Instance) {
47 g_Instance = new(std::nothrow) AccessibleAbilityClientImpl();
48 }
49 return g_Instance;
50 }
51
GetAbilityClientImplement()52 sptr<AccessibleAbilityClientImpl> AccessibleAbilityClientImpl::GetAbilityClientImplement()
53 {
54 HILOG_DEBUG();
55 std::lock_guard<std::mutex> lock(g_Mutex);
56 if (!g_Instance) {
57 g_Instance = new(std::nothrow) AccessibleAbilityClientImpl();
58 }
59 return g_Instance;
60 }
61
AccessibleAbilityClientImpl()62 AccessibleAbilityClientImpl::AccessibleAbilityClientImpl()
63 {
64 HILOG_DEBUG();
65 char value[CONFIG_PARAMETER_VALUE_SIZE] = "default";
66 int retSysParam = GetParameter(SYSTEM_PARAMETER_AAMS_NAME.c_str(), "false", value, CONFIG_PARAMETER_VALUE_SIZE);
67 if (retSysParam >= 0 && !std::strcmp(value, "true")) {
68 // Accessibility service is ready
69 if (!InitAccessibilityServiceProxy()) {
70 HILOG_ERROR("Init accessibility service proxy failed");
71 }
72 }
73
74 HILOG_DEBUG("Start watching accessibility service.");
75 retSysParam = WatchParameter(SYSTEM_PARAMETER_AAMS_NAME.c_str(),
76 &AccessibleAbilityClientImpl::OnParameterChanged, this);
77 if (retSysParam) {
78 HILOG_ERROR("Watch parameter failed, error = %{public}d", retSysParam);
79 }
80 }
81
~AccessibleAbilityClientImpl()82 AccessibleAbilityClientImpl::~AccessibleAbilityClientImpl()
83 {
84 HILOG_DEBUG();
85 std::lock_guard<std::mutex> lock(mutex_);
86 if (serviceProxy_ && serviceProxy_->AsObject()) {
87 HILOG_DEBUG("Remove service death recipient");
88 serviceProxy_->AsObject()->RemoveDeathRecipient(accessibilityServiceDeathRecipient_);
89 }
90 }
91
InitAccessibilityServiceProxy()92 bool AccessibleAbilityClientImpl::InitAccessibilityServiceProxy()
93 {
94 if (serviceProxy_) {
95 HILOG_DEBUG("Accessibility Service is connected");
96 return true;
97 }
98
99 sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
100 if (!samgr) {
101 HILOG_ERROR("Failed to get ISystemAbilityManager");
102 return false;
103 }
104 HILOG_DEBUG("ISystemAbilityManager obtained");
105
106 sptr<IRemoteObject> object = samgr->GetSystemAbility(ACCESSIBILITY_MANAGER_SERVICE_ID);
107 if (!object) {
108 HILOG_ERROR("Get IAccessibleAbilityManagerService object from samgr failed");
109 return false;
110 }
111 HILOG_DEBUG("Get remote object ok");
112
113 serviceProxy_ = iface_cast<IAccessibleAbilityManagerService>(object);
114 if (!serviceProxy_) {
115 HILOG_ERROR("Get aams proxy failed");
116 return false;
117 }
118
119 // Add death recipient
120 if (!accessibilityServiceDeathRecipient_) {
121 accessibilityServiceDeathRecipient_ = new(std::nothrow) AccessibilityServiceDeathRecipient(*this);
122 if (!accessibilityServiceDeathRecipient_) {
123 HILOG_ERROR("Failed to create service deathRecipient.");
124 return false;
125 }
126 }
127
128 if (serviceProxy_->AsObject()) {
129 HILOG_DEBUG("Add death recipient");
130 serviceProxy_->AsObject()->AddDeathRecipient(accessibilityServiceDeathRecipient_);
131 }
132 return true;
133 }
134
OnParameterChanged(const char * key,const char * value,void * context)135 void AccessibleAbilityClientImpl::OnParameterChanged(const char *key, const char *value, void *context)
136 {
137 HILOG_DEBUG("Parameter key = [%{public}s] value = [%{public}s]", key, value);
138
139 if (!key || std::strcmp(key, SYSTEM_PARAMETER_AAMS_NAME.c_str())) {
140 HILOG_WARN("not accessibility.config.ready callback");
141 return;
142 }
143
144 if (!value || std::strcmp(value, "true")) {
145 HILOG_WARN("accessibility.config.ready value not true");
146 return;
147 }
148
149 if (!context) {
150 HILOG_ERROR("accessibility.config.ready context NULL");
151 return;
152 }
153
154 AccessibleAbilityClientImpl* implPtr = static_cast<AccessibleAbilityClientImpl*>(context);
155 {
156 HILOG_DEBUG("ConnectToService start.");
157 std::lock_guard<std::mutex> lock(implPtr->mutex_);
158 if (implPtr->InitAccessibilityServiceProxy()) {
159 HILOG_DEBUG("ConnectToService Success");
160 }
161 }
162 }
163
GetRemoteObject()164 sptr<IRemoteObject> AccessibleAbilityClientImpl::GetRemoteObject()
165 {
166 HILOG_DEBUG();
167 return this->AsObject();
168 }
169
RegisterAbilityListener(const std::shared_ptr<AccessibleAbilityListener> & listener)170 RetError AccessibleAbilityClientImpl::RegisterAbilityListener(
171 const std::shared_ptr<AccessibleAbilityListener> &listener)
172 {
173 HILOG_DEBUG();
174 std::lock_guard<std::mutex> lock(mutex_);
175 if (listener_) {
176 HILOG_DEBUG("listener already exists.");
177 return RET_ERR_REGISTER_EXIST;
178 }
179
180 listener_ = listener;
181 return RET_OK;
182 }
183
Init(const sptr<IAccessibleAbilityChannel> & channel,const int32_t channelId)184 void AccessibleAbilityClientImpl::Init(const sptr<IAccessibleAbilityChannel> &channel, const int32_t channelId)
185 {
186 HILOG_DEBUG("channelId[%{public}d]", channelId);
187 if (!channel || channelId == INVALID_CHANNEL_ID) {
188 HILOG_ERROR("channel is nullptr, or channelId is invalid");
189 return;
190 }
191
192 std::shared_ptr<AccessibleAbilityListener> listener = nullptr;
193 {
194 std::lock_guard<std::mutex> lock(mutex_);
195 if (!listener_) {
196 HILOG_ERROR("listener_ is nullptr.");
197 return;
198 }
199 listener = listener_;
200 channelClient_ = std::make_shared<AccessibleAbilityChannelClient>(channelId, channel);
201
202 // Add death recipient
203 if (!deathRecipient_) {
204 deathRecipient_ = new(std::nothrow) AccessibleAbilityDeathRecipient(*this);
205 if (!deathRecipient_) {
206 HILOG_ERROR("Failed to create deathRecipient.");
207 return;
208 }
209 }
210
211 if (channel->AsObject()) {
212 HILOG_DEBUG("Add death recipient");
213 channel->AsObject()->AddDeathRecipient(deathRecipient_);
214 }
215 }
216
217 isConnected_ = true;
218 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_WINDOW_REGIST));
219 if (listener) {
220 listener->OnAbilityConnected();
221 }
222 }
223
Disconnect(const int32_t channelId)224 void AccessibleAbilityClientImpl::Disconnect(const int32_t channelId)
225 {
226 HILOG_DEBUG("channelId[%{public}d]", channelId);
227
228 std::shared_ptr<AccessibleAbilityListener> listener = nullptr;
229 {
230 isConnected_ = false;
231 std::lock_guard<std::mutex> lock(mutex_);
232 // Delete death recipient
233 if (channelClient_ && channelClient_->GetRemote()) {
234 HILOG_ERROR("Remove death recipient");
235 channelClient_->GetRemote()->RemoveDeathRecipient(deathRecipient_);
236 }
237
238 // Remove channel
239 channelClient_ = nullptr;
240 listener = listener_;
241 listener_ = nullptr;
242 }
243
244 if (listener) {
245 listener->OnAbilityDisconnected();
246 }
247 }
248
OnAccessibilityEvent(const AccessibilityEventInfo & eventInfo)249 void AccessibleAbilityClientImpl::OnAccessibilityEvent(const AccessibilityEventInfo &eventInfo)
250 {
251 HILOG_DEBUG();
252 std::shared_ptr<AccessibleAbilityListener> listener = nullptr;
253 {
254 std::lock_guard<std::mutex> lock(mutex_);
255 if (!channelClient_) {
256 HILOG_ERROR("The channel is invalid.");
257 return;
258 }
259 listener = listener_;
260 }
261 if (listener) {
262 listener->OnAccessibilityEvent(eventInfo);
263 }
264 }
265
OnKeyPressEvent(const MMI::KeyEvent & keyEvent,const int32_t sequence)266 void AccessibleAbilityClientImpl::OnKeyPressEvent(const MMI::KeyEvent &keyEvent, const int32_t sequence)
267 {
268 HILOG_DEBUG("sequence[%{public}d]", sequence);
269 std::shared_ptr<AccessibleAbilityListener> listener = nullptr;
270 std::shared_ptr<AccessibleAbilityChannelClient> channel = nullptr;
271 {
272 std::lock_guard<std::mutex> lock(mutex_);
273 listener = listener_;
274 channel = channelClient_;
275 }
276
277 if (!channel) {
278 HILOG_ERROR("The channel is invalid.");
279 return;
280 }
281 bool handled = false;
282 if (listener) {
283 std::shared_ptr<MMI::KeyEvent> tmp = std::make_shared<MMI::KeyEvent>(keyEvent);
284 handled = listener->OnKeyPressEvent(tmp);
285 }
286 channel->SetOnKeyPressEventResult(handled, sequence);
287 }
288
GetFocus(const int32_t focusType,AccessibilityElementInfo & elementInfo)289 RetError AccessibleAbilityClientImpl::GetFocus(const int32_t focusType, AccessibilityElementInfo &elementInfo)
290 {
291 HILOG_DEBUG("focusType[%{public}d]", focusType);
292 if (!isConnected_) {
293 HILOG_ERROR("connection is broken");
294 return RET_ERR_NO_CONNECTION;
295 }
296
297 std::lock_guard<std::mutex> lock(mutex_);
298 if ((focusType != FOCUS_TYPE_INPUT) && (focusType != FOCUS_TYPE_ACCESSIBILITY)) {
299 HILOG_ERROR("focusType is not allowed.");
300 return RET_ERR_INVALID_PARAM;
301 }
302
303 if (!channelClient_) {
304 HILOG_ERROR("The channel is invalid.");
305 return RET_ERR_NO_CONNECTION;
306 }
307
308 return channelClient_->FindFocusedElementInfo(ANY_WINDOW_ID, ROOT_NODE_ID, focusType, elementInfo);
309 }
310
GetFocusByElementInfo(const AccessibilityElementInfo & sourceInfo,const int32_t focusType,AccessibilityElementInfo & elementInfo)311 RetError AccessibleAbilityClientImpl::GetFocusByElementInfo(const AccessibilityElementInfo &sourceInfo,
312 const int32_t focusType, AccessibilityElementInfo &elementInfo)
313 {
314 HILOG_DEBUG("focusType[%{public}d]", focusType);
315 if (!isConnected_) {
316 HILOG_ERROR("connection is broken");
317 return RET_ERR_NO_CONNECTION;
318 }
319
320 std::lock_guard<std::mutex> lock(mutex_);
321 if ((focusType != FOCUS_TYPE_INPUT) && (focusType != FOCUS_TYPE_ACCESSIBILITY)) {
322 HILOG_ERROR("focusType is not allowed.");
323 return RET_ERR_INVALID_PARAM;
324 }
325
326 if (!channelClient_) {
327 HILOG_ERROR("The channel is invalid.");
328 return RET_ERR_NO_CONNECTION;
329 }
330
331 int32_t windowId = sourceInfo.GetWindowId();
332 int64_t elementId = sourceInfo.GetAccessibilityId();
333 HILOG_DEBUG("windowId[%{public}d], elementId[%{public}" PRId64 "], focusType[%{public}d]",
334 windowId, elementId, focusType);
335
336 return channelClient_->FindFocusedElementInfo(windowId, elementId, focusType, elementInfo);
337 }
338
InjectGesture(const std::shared_ptr<AccessibilityGestureInjectPath> & gesturePath)339 RetError AccessibleAbilityClientImpl::InjectGesture(const std::shared_ptr<AccessibilityGestureInjectPath> &gesturePath)
340 {
341 HILOG_DEBUG();
342 if (!isConnected_) {
343 HILOG_ERROR("connection is broken");
344 return RET_ERR_NO_CONNECTION;
345 }
346
347 std::lock_guard<std::mutex> lock(mutex_);
348 if (!gesturePath) {
349 HILOG_ERROR("The gesturePath is null.");
350 return RET_ERR_INVALID_PARAM;
351 }
352
353 std::vector<AccessibilityGesturePosition> positions = gesturePath->GetPositions();
354
355 if (positions.size() == 0) {
356 HILOG_ERROR("The number of gesture path position is not allowed.");
357 return RET_ERR_INVALID_PARAM;
358 }
359
360 if (!channelClient_) {
361 HILOG_ERROR("The channel is invalid.");
362 return RET_ERR_NO_CONNECTION;
363 }
364
365 return channelClient_->SendSimulateGesture(gesturePath);
366 }
367
GetRoot(AccessibilityElementInfo & elementInfo)368 RetError AccessibleAbilityClientImpl::GetRoot(AccessibilityElementInfo &elementInfo)
369 {
370 HILOG_DEBUG();
371 if (!isConnected_) {
372 HILOG_ERROR("connection is broken");
373 return RET_ERR_NO_CONNECTION;
374 }
375
376 std::lock_guard<std::mutex> lock(mutex_);
377 if (!serviceProxy_) {
378 HILOG_ERROR("Failed to connect to aams");
379 return RET_ERR_SAMGR;
380 }
381
382 if (!channelClient_) {
383 HILOG_ERROR("The channel is invalid.");
384 return RET_ERR_NO_CONNECTION;
385 }
386
387 int32_t activeWindow = serviceProxy_->GetActiveWindow();
388 HILOG_DEBUG("activeWindow[%{public}d]", activeWindow);
389 if (GetCacheElementInfo(activeWindow, ROOT_NONE_ID, elementInfo)) {
390 HILOG_DEBUG("get element info from cache");
391 return RET_OK;
392 }
393
394 return SearchElementInfoFromAce(activeWindow, ROOT_NONE_ID, cacheMode_, elementInfo);
395 }
396
GetRootByWindow(const AccessibilityWindowInfo & windowInfo,AccessibilityElementInfo & elementInfo)397 RetError AccessibleAbilityClientImpl::GetRootByWindow(const AccessibilityWindowInfo &windowInfo,
398 AccessibilityElementInfo &elementInfo)
399 {
400 HILOG_DEBUG();
401 if (!isConnected_) {
402 HILOG_ERROR("connection is broken");
403 return RET_ERR_NO_CONNECTION;
404 }
405
406 std::lock_guard<std::mutex> lock(mutex_);
407 if (!channelClient_) {
408 HILOG_ERROR("The channel is invalid.");
409 return RET_ERR_NO_CONNECTION;
410 }
411
412 int32_t windowId = windowInfo.GetWindowId();
413 HILOG_DEBUG("windowId[%{public}d]", windowId);
414 if (GetCacheElementInfo(windowId, ROOT_NONE_ID, elementInfo)) {
415 HILOG_DEBUG("get element info from cache");
416 return RET_OK;
417 }
418
419 return SearchElementInfoFromAce(windowId, ROOT_NONE_ID, cacheMode_, elementInfo);
420 }
421
GetWindow(const int32_t windowId,AccessibilityWindowInfo & windowInfo)422 RetError AccessibleAbilityClientImpl::GetWindow(const int32_t windowId, AccessibilityWindowInfo &windowInfo)
423 {
424 HILOG_DEBUG("windowId[%{public}d]", windowId);
425 if (!isConnected_) {
426 HILOG_ERROR("connection is broken");
427 return RET_ERR_NO_CONNECTION;
428 }
429
430 std::lock_guard<std::mutex> lock(mutex_);
431 if (!channelClient_) {
432 HILOG_ERROR("The channel is invalid.");
433 return RET_ERR_NO_CONNECTION;
434 }
435 return channelClient_->GetWindow(windowId, windowInfo);
436 }
437
GetRootBatch(std::vector<AccessibilityElementInfo> & elementInfos)438 RetError AccessibleAbilityClientImpl::GetRootBatch(std::vector<AccessibilityElementInfo>& elementInfos)
439 {
440 HILOG_DEBUG();
441 if (!isConnected_) {
442 HILOG_ERROR("connection is broken");
443 return RET_ERR_NO_CONNECTION;
444 }
445
446 std::lock_guard<std::mutex> lock(mutex_);
447 if (!channelClient_) {
448 HILOG_ERROR("channel is invalid.");
449 return RET_ERR_NO_CONNECTION;
450 }
451
452 if (!serviceProxy_) {
453 HILOG_ERROR("failed to connect to aams");
454 return RET_ERR_SAMGR;
455 }
456
457 int32_t windowId = serviceProxy_->GetActiveWindow();
458 int64_t elementId = ROOT_NONE_ID;
459 RetError ret = SearchElementInfoRecursive(windowId, elementId, PREFETCH_RECURSIVE_CHILDREN, elementInfos);
460 if (ret != RET_OK) {
461 HILOG_ERROR("get window element failed.");
462 return ret;
463 }
464 SortElementInfosIfNecessary(elementInfos);
465 return RET_OK;
466 }
467
SortElementInfosIfNecessary(std::vector<AccessibilityElementInfo> & elementInfos)468 void AccessibleAbilityClientImpl::SortElementInfosIfNecessary(std::vector<AccessibilityElementInfo> &elementInfos)
469 {
470 HILOG_DEBUG();
471 std::map<int64_t, std::shared_ptr<AccessibilityElementInfo>> elementInfosMap;
472 std::vector<AccessibilityElementInfo> sortedElementInfos;
473 int64_t nodeId = NODE_ID_MAX;
474 int32_t count = 1;
475 AccessibilityElementInfo virtualRoot = elementInfos.front();
476 if (virtualRoot.GetAccessibilityId() != NODE_ID_MAX) {
477 return;
478 }
479 elementInfos.erase(elementInfos.begin());
480 for (auto &element : elementInfos) {
481 if (element.GetAccessibilityId() == NODE_ID_MAX) {
482 nodeId = NODE_ID_MAX - count;
483 element.SetAccessibilityId(nodeId);
484 element.SetParent(NODE_ID_MAX);
485 virtualRoot.AddChild(nodeId);
486 count += 1;
487 }
488 nodeId = element.GetAccessibilityId();
489 elementInfosMap[nodeId] = std::make_shared<AccessibilityElementInfo>(element);
490 }
491 elementInfosMap[NODE_ID_MAX] = std::make_shared<AccessibilityElementInfo>(virtualRoot);
492
493 std::vector<int64_t> elementList;
494 elementList.push_back(NODE_ID_MAX);
495 uint32_t index = 0;
496 while (index < elementList.size()) {
497 auto iter = elementInfosMap.find(elementList[index]);
498 if (iter == elementInfosMap.end()) {
499 sortedElementInfos.clear();
500 elementInfos.insert(elementInfos.begin(), virtualRoot);
501 return;
502 }
503 sortedElementInfos.push_back(*(iter->second));
504 std::vector<int64_t> childNodeIds = iter->second->GetChildIds();
505 for (auto &id : childNodeIds) {
506 if (std::find(elementList.begin(), elementList.end(), id) == elementList.end()) {
507 elementList.push_back(id);
508 }
509 }
510 index++;
511 }
512
513 if (static_cast<int32_t>(sortedElementInfos.size()) > 0) {
514 elementInfos = sortedElementInfos;
515 }
516 elementInfosMap.clear();
517 }
518
GetRootByWindowBatch(const AccessibilityWindowInfo & windowInfo,std::vector<AccessibilityElementInfo> & elementInfos)519 RetError AccessibleAbilityClientImpl::GetRootByWindowBatch(const AccessibilityWindowInfo &windowInfo,
520 std::vector<AccessibilityElementInfo>& elementInfos)
521 {
522 HILOG_DEBUG("GetRootByWindowBatch %{public}d", windowInfo.GetWindowId());
523 if (!isConnected_) {
524 HILOG_ERROR("connection is broken");
525 return RET_ERR_NO_CONNECTION;
526 }
527
528 std::lock_guard<std::mutex> lock(mutex_);
529 if (!serviceProxy_) {
530 HILOG_ERROR("failed to connect to aams");
531 return RET_ERR_SAMGR;
532 }
533
534 if (!channelClient_) {
535 HILOG_ERROR("channel is invalid.");
536 return RET_ERR_NO_CONNECTION;
537 }
538
539 int32_t windowId = windowInfo.GetWindowId();
540 int64_t elementId = ROOT_NONE_ID;
541 RetError ret = SearchElementInfoRecursive(windowId, elementId, PREFETCH_RECURSIVE_CHILDREN, elementInfos);
542 if (ret != RET_OK) {
543 HILOG_ERROR("get window element failed");
544 return ret;
545 }
546 return RET_OK;
547 }
548
GetWindows(std::vector<AccessibilityWindowInfo> & windows)549 RetError AccessibleAbilityClientImpl::GetWindows(std::vector<AccessibilityWindowInfo> &windows)
550 {
551 HILOG_DEBUG();
552 if (!isConnected_) {
553 HILOG_ERROR("connection is broken");
554 return RET_ERR_NO_CONNECTION;
555 }
556
557 std::lock_guard<std::mutex> lock(mutex_);
558 if (!channelClient_) {
559 HILOG_ERROR("The channel is invalid.");
560 return RET_ERR_NO_CONNECTION;
561 }
562 return channelClient_->GetWindows(windows);
563 }
564
GetWindows(const uint64_t displayId,std::vector<AccessibilityWindowInfo> & windows)565 RetError AccessibleAbilityClientImpl::GetWindows(const uint64_t displayId,
566 std::vector<AccessibilityWindowInfo> &windows)
567 {
568 HILOG_DEBUG("displayId[%{public}" PRIu64 "]", displayId);
569 if (!isConnected_) {
570 HILOG_ERROR("connection is broken");
571 return RET_ERR_NO_CONNECTION;
572 }
573
574 std::lock_guard<std::mutex> lock(mutex_);
575 if (!channelClient_) {
576 HILOG_ERROR("The channel is invalid.");
577 return RET_ERR_NO_CONNECTION;
578 }
579 return channelClient_->GetWindows(displayId, windows);
580 }
581
GetNext(const AccessibilityElementInfo & elementInfo,const FocusMoveDirection direction,AccessibilityElementInfo & nextElementInfo)582 RetError AccessibleAbilityClientImpl::GetNext(const AccessibilityElementInfo &elementInfo,
583 const FocusMoveDirection direction, AccessibilityElementInfo &nextElementInfo)
584 {
585 HILOG_DEBUG("windowId[%{public}d], elementId[%{public}" PRId64 "], direction[%{public}d]",
586 elementInfo.GetWindowId(), elementInfo.GetAccessibilityId(), direction);
587 if (!isConnected_) {
588 HILOG_ERROR("connection is broken");
589 return RET_ERR_NO_CONNECTION;
590 }
591
592 std::lock_guard<std::mutex> lock(mutex_);
593 if (!channelClient_) {
594 HILOG_ERROR("The channel is invalid.");
595 return RET_ERR_NO_CONNECTION;
596 }
597 if (direction == DIRECTION_INVALID) {
598 HILOG_ERROR("direction is invalid.");
599 return RET_ERR_INVALID_PARAM;
600 }
601 return channelClient_->FocusMoveSearch(elementInfo.GetWindowId(),
602 elementInfo.GetAccessibilityId(), direction, nextElementInfo);
603 }
604
GetChildElementInfo(const int32_t index,const AccessibilityElementInfo & parent,AccessibilityElementInfo & child)605 RetError AccessibleAbilityClientImpl::GetChildElementInfo(const int32_t index, const AccessibilityElementInfo &parent,
606 AccessibilityElementInfo &child)
607 {
608 HILOG_DEBUG();
609 if (!isConnected_) {
610 HILOG_ERROR("connection is broken");
611 return RET_ERR_NO_CONNECTION;
612 }
613
614 std::lock_guard<std::mutex> lock(mutex_);
615 if (!channelClient_) {
616 HILOG_ERROR("The channel is invalid.");
617 return RET_ERR_NO_CONNECTION;
618 }
619
620 int32_t windowId = parent.GetWindowId();
621 int64_t childId = parent.GetChildId(index);
622 HILOG_DEBUG("windowId[%{public}d], childId[%{public}" PRId64 "]", windowId, childId);
623 if (childId == -1) {
624 HILOG_ERROR("childId[%{public}" PRId64 "] is invalid", childId);
625 return RET_ERR_INVALID_PARAM;
626 }
627 if (GetCacheElementInfo(windowId, childId, child)) {
628 HILOG_DEBUG("get element info from cache");
629 return RET_OK;
630 }
631
632 return SearchElementInfoFromAce(windowId, childId, cacheMode_, child);
633 }
634
GetChildren(const AccessibilityElementInfo & parent,std::vector<AccessibilityElementInfo> & children)635 RetError AccessibleAbilityClientImpl::GetChildren(const AccessibilityElementInfo &parent,
636 std::vector<AccessibilityElementInfo> &children)
637 {
638 HILOG_DEBUG();
639 if (!isConnected_) {
640 HILOG_ERROR("connection is broken");
641 return RET_ERR_NO_CONNECTION;
642 }
643
644 std::lock_guard<std::mutex> lock(mutex_);
645 if (!channelClient_) {
646 HILOG_ERROR("The channel is invalid.");
647 return RET_ERR_NO_CONNECTION;
648 }
649
650 int32_t windowId = parent.GetWindowId();
651 std::vector<int64_t> childIds = parent.GetChildIds();
652 HILOG_DEBUG("windowId[%{public}d], childIds.size[%{public}zu]", windowId, childIds.size());
653 for (auto &childId : childIds) {
654 HILOG_DEBUG("childId[%{public}" PRId64 "]", childId);
655 if (childId == -1) {
656 HILOG_ERROR("childId is invalid");
657 return RET_ERR_INVALID_PARAM;
658 }
659
660 AccessibilityElementInfo child;
661 if (GetCacheElementInfo(windowId, childId, child)) {
662 HILOG_DEBUG("get element info from cache");
663 children.emplace_back(child);
664 continue;
665 }
666
667 RetError ret = SearchElementInfoFromAce(windowId, childId, cacheMode_, child);
668 if (ret != RET_OK) {
669 HILOG_ERROR("Get element info from ace failed");
670 return ret;
671 }
672 children.emplace_back(child);
673 }
674 return RET_OK;
675 }
676
GetByContent(const AccessibilityElementInfo & elementInfo,const std::string & text,std::vector<AccessibilityElementInfo> & elementInfos)677 RetError AccessibleAbilityClientImpl::GetByContent(const AccessibilityElementInfo &elementInfo,
678 const std::string &text, std::vector<AccessibilityElementInfo> &elementInfos)
679 {
680 HILOG_DEBUG();
681 if (!isConnected_) {
682 HILOG_ERROR("connection is broken");
683 return RET_ERR_NO_CONNECTION;
684 }
685
686 std::lock_guard<std::mutex> lock(mutex_);
687 if (!channelClient_) {
688 HILOG_ERROR("The channel is invalid.");
689 return RET_ERR_NO_CONNECTION;
690 }
691
692 int32_t windowId = elementInfo.GetWindowId();
693 int64_t elementId = elementInfo.GetAccessibilityId();
694 HILOG_DEBUG("windowId %{public}d, elementId %{public}" PRId64 ", text %{public}s",
695 windowId, elementId, text.c_str());
696 if (text != "") { // find element condition is null, so we will search all element info
697 return channelClient_->SearchElementInfosByText(windowId, elementId, text, elementInfos);
698 }
699
700 RetError ret = SearchElementInfoRecursive(windowId, elementId, GET_SOURCE_MODE, elementInfos);
701 if (ret != RET_OK) {
702 HILOG_ERROR("get window element info failed");
703 return ret;
704 }
705 return RET_OK;
706 }
707
GetSource(const AccessibilityEventInfo & eventInfo,AccessibilityElementInfo & elementInfo)708 RetError AccessibleAbilityClientImpl::GetSource(const AccessibilityEventInfo &eventInfo,
709 AccessibilityElementInfo &elementInfo)
710 {
711 HILOG_DEBUG();
712 if (!isConnected_) {
713 HILOG_ERROR("connection is broken");
714 return RET_ERR_NO_CONNECTION;
715 }
716
717 std::lock_guard<std::mutex> lock(mutex_);
718 if (!channelClient_) {
719 HILOG_ERROR("The channel is invalid.");
720 return RET_ERR_NO_CONNECTION;
721 }
722 int32_t windowId = eventInfo.GetWindowId();
723 int64_t elementId = eventInfo.GetAccessibilityId();
724 HILOG_DEBUG("windowId[%{public}d], elementId[%{public}" PRId64 "]", windowId, elementId);
725 if (GetCacheElementInfo(windowId, elementId, elementInfo)) {
726 HILOG_DEBUG("get element info from cache");
727 return RET_OK;
728 }
729 return SearchElementInfoFromAce(windowId, elementId, cacheMode_, elementInfo);
730 }
731
GetParentElementInfo(const AccessibilityElementInfo & child,AccessibilityElementInfo & parent)732 RetError AccessibleAbilityClientImpl::GetParentElementInfo(const AccessibilityElementInfo &child,
733 AccessibilityElementInfo &parent)
734 {
735 HILOG_DEBUG();
736 if (!isConnected_) {
737 HILOG_ERROR("connection is broken");
738 return RET_ERR_NO_CONNECTION;
739 }
740
741 std::lock_guard<std::mutex> lock(mutex_);
742 if (!channelClient_) {
743 HILOG_ERROR("The channel is invalid.");
744 return RET_ERR_NO_CONNECTION;
745 }
746 int32_t windowId = child.GetWindowId();
747 int64_t elementId = child.GetParentNodeId();
748 HILOG_DEBUG("windowId[%{public}d], parentId[%{public}" PRId64 "]", windowId, elementId);
749 if (GetCacheElementInfo(windowId, elementId, parent)) {
750 HILOG_DEBUG("get element info from cache");
751 return RET_OK;
752 }
753
754 return SearchElementInfoFromAce(windowId, elementId, cacheMode_, parent);
755 }
756
ExecuteAction(const AccessibilityElementInfo & elementInfo,const ActionType action,const std::map<std::string,std::string> & actionArguments)757 RetError AccessibleAbilityClientImpl::ExecuteAction(const AccessibilityElementInfo &elementInfo,
758 const ActionType action, const std::map<std::string, std::string> &actionArguments)
759 {
760 HILOG_DEBUG();
761 if (!isConnected_) {
762 HILOG_ERROR("connection is broken");
763 return RET_ERR_NO_CONNECTION;
764 }
765
766 std::lock_guard<std::mutex> lock(mutex_);
767 if (!channelClient_) {
768 HILOG_ERROR("The channel is invalid.");
769 return RET_ERR_NO_CONNECTION;
770 }
771 if (action == ACCESSIBILITY_ACTION_INVALID) {
772 HILOG_ERROR("action is invalid.");
773 return RET_ERR_INVALID_PARAM;
774 }
775 int32_t windowId = elementInfo.GetWindowId();
776 int64_t elementId = elementInfo.GetAccessibilityId();
777 HILOG_DEBUG("windowId[%{public}d], elementId[%{public}" PRId64 "], action[%{public}d", windowId, elementId, action);
778 return channelClient_->ExecuteAction(windowId, elementId, action,
779 const_cast<std::map<std::string, std::string> &>(actionArguments));
780 }
781
SetTargetBundleName(const std::vector<std::string> & targetBundleNames)782 RetError AccessibleAbilityClientImpl::SetTargetBundleName(const std::vector<std::string> &targetBundleNames)
783 {
784 HILOG_DEBUG("targetBundleNames size[%{public}zu]", targetBundleNames.size());
785 if (!isConnected_) {
786 HILOG_ERROR("connection is broken");
787 return RET_ERR_NO_CONNECTION;
788 }
789
790 std::lock_guard<std::mutex> lock(mutex_);
791 if (!channelClient_) {
792 HILOG_ERROR("The channel is invalid.");
793 return RET_ERR_NO_CONNECTION;
794 }
795 return channelClient_->SetTargetBundleName(targetBundleNames);
796 }
797
OnRemoteDied(const wptr<IRemoteObject> & remote)798 void AccessibleAbilityClientImpl::AccessibleAbilityDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& remote)
799 {
800 HILOG_ERROR();
801 client_.ResetAAClient(remote);
802 }
803
OnRemoteDied(const wptr<IRemoteObject> & remote)804 void AccessibleAbilityClientImpl::AccessibilityServiceDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& remote)
805 {
806 HILOG_ERROR();
807 client_.NotifyServiceDied(remote);
808 }
809
NotifyServiceDied(const wptr<IRemoteObject> & remote)810 void AccessibleAbilityClientImpl::NotifyServiceDied(const wptr<IRemoteObject> &remote)
811 {
812 std::shared_ptr<AccessibleAbilityListener> listener = nullptr;
813 {
814 std::lock_guard<std::mutex> lock(mutex_);
815 if (!serviceProxy_) {
816 HILOG_ERROR("serviceProxy_ is nullptr");
817 return;
818 }
819 sptr<IRemoteObject> object = serviceProxy_->AsObject();
820 if (object && (remote == object)) {
821 listener = listener_;
822 listener_ = nullptr;
823
824 object->RemoveDeathRecipient(accessibilityServiceDeathRecipient_);
825 serviceProxy_ = nullptr;
826 channelClient_ = nullptr;
827 HILOG_DEBUG("ResetAAClient OK");
828 }
829 }
830
831 isConnected_ = false;
832 if (listener) {
833 listener->OnAbilityDisconnected();
834 }
835 }
836
ResetAAClient(const wptr<IRemoteObject> & remote)837 void AccessibleAbilityClientImpl::ResetAAClient(const wptr<IRemoteObject> &remote)
838 {
839 HILOG_DEBUG();
840 std::lock_guard<std::mutex> lock(mutex_);
841 if (channelClient_) {
842 sptr<IRemoteObject> object = channelClient_->GetRemote();
843 if (object && (remote == object)) {
844 object->RemoveDeathRecipient(deathRecipient_);
845 channelClient_ = nullptr;
846 HILOG_DEBUG("ResetAAClient OK");
847 }
848 }
849
850 isConnected_ = false;
851 }
852
SetCacheMode(const int32_t cacheMode)853 RetError AccessibleAbilityClientImpl::SetCacheMode(const int32_t cacheMode)
854 {
855 HILOG_DEBUG("set cache mode: [%{public}d]", cacheMode);
856 std::lock_guard<std::mutex> lock(mutex_);
857 cacheWindowId_ = -1;
858 cacheElementInfos_.clear();
859 if (cacheMode < 0) {
860 cacheMode_ = 0;
861 } else {
862 uint32_t mode = static_cast<uint32_t>(cacheMode);
863 cacheMode_ = mode & static_cast<uint32_t>(GET_SOURCE_PREFETCH_MODE);
864 }
865 return RET_OK;
866 }
867
GetCacheElementInfo(const int32_t windowId,const int64_t elementId,AccessibilityElementInfo & elementInfo) const868 bool AccessibleAbilityClientImpl::GetCacheElementInfo(const int32_t windowId,
869 const int64_t elementId, AccessibilityElementInfo &elementInfo) const
870 {
871 HILOG_DEBUG();
872 if (cacheWindowId_ == -1 || cacheWindowId_ != windowId) {
873 HILOG_DEBUG("cacheWindowId[%{public}d], windowId[%{public}d]", cacheWindowId_, windowId);
874 return false;
875 }
876
877 auto iter = cacheElementInfos_.find(elementId);
878 if (iter == cacheElementInfos_.end()) {
879 HILOG_DEBUG("the element id[%{public}" PRId64 "] is not in cache", elementId);
880 return false;
881 }
882
883 elementInfo = iter->second;
884 return true;
885 }
886
SetCacheElementInfo(const int32_t windowId,const std::vector<OHOS::Accessibility::AccessibilityElementInfo> & elementInfos)887 void AccessibleAbilityClientImpl::SetCacheElementInfo(const int32_t windowId,
888 const std::vector<OHOS::Accessibility::AccessibilityElementInfo> &elementInfos)
889 {
890 HILOG_DEBUG("windowId[%{public}d], elementInfos size[%{public}zu]", windowId, elementInfos.size());
891 cacheElementInfos_.clear();
892 cacheWindowId_ = windowId;
893 for (auto &elementInfo : elementInfos) {
894 cacheElementInfos_.insert(std::make_pair(elementInfo.GetAccessibilityId(), elementInfo));
895 }
896 }
897
SearchElementInfoFromAce(const int32_t windowId,const int64_t elementId,const uint32_t mode,AccessibilityElementInfo & info)898 RetError AccessibleAbilityClientImpl::SearchElementInfoFromAce(const int32_t windowId, const int64_t elementId,
899 const uint32_t mode, AccessibilityElementInfo &info)
900 {
901 if (!channelClient_) {
902 HILOG_ERROR("The channel is invalid.");
903 return RET_ERR_NO_CONNECTION;
904 }
905
906 std::vector<AccessibilityElementInfo> elementInfos {};
907
908 RetError ret = channelClient_->SearchElementInfosByAccessibilityId(
909 windowId, elementId, static_cast<int32_t>(mode), elementInfos);
910 if (ret != RET_OK) {
911 HILOG_ERROR("search element info failed. windowId[%{public}d] elementId[%{public}" PRId64 "] mode[%{public}d]",
912 windowId, elementId, mode);
913 return ret;
914 }
915 if (elementInfos.empty()) {
916 HILOG_ERROR("elementInfos from ace is empty");
917 return RET_ERR_INVALID_ELEMENT_INFO_FROM_ACE;
918 }
919
920 HILOG_DEBUG("element [elementSize:%{public}zu]", elementInfos.size());
921 SetCacheElementInfo(windowId, elementInfos);
922 info = elementInfos.front();
923 return RET_OK;
924 }
925
Connect()926 RetError AccessibleAbilityClientImpl::Connect()
927 {
928 HILOG_DEBUG();
929 std::lock_guard<std::mutex> lock(mutex_);
930 if (!serviceProxy_) {
931 HILOG_ERROR("Failed to get aams service");
932 return RET_ERR_SAMGR;
933 }
934
935 return serviceProxy_->EnableUITestAbility(this->AsObject());
936 }
937
Disconnect()938 RetError AccessibleAbilityClientImpl::Disconnect()
939 {
940 HILOG_DEBUG();
941 std::lock_guard<std::mutex> lock(mutex_);
942 if (!serviceProxy_) {
943 HILOG_ERROR("Failed to get aams service");
944 return RET_ERR_SAMGR;
945 }
946 return serviceProxy_->DisableUITestAbility();
947 }
948
SetConnectionState(bool state)949 void AccessibleAbilityClientImpl::SetConnectionState(bool state)
950 {
951 isConnected_ = state;
952 }
953
AddWindowElementMapByWMS(int32_t windowId,int64_t elementId)954 void AccessibleAbilityClientImpl::AddWindowElementMapByWMS(int32_t windowId, int64_t elementId)
955 {
956 // only used for scene board window, non scene board window not need window element map
957 int32_t realWindowId = windowId;
958 int64_t realElementId = elementId;
959 serviceProxy_->GetRealWindowAndElementId(realWindowId, realElementId);
960 HILOG_DEBUG("windowId %{public}d, real windowId %{public}d, real elementId %{public}" PRId64 "",
961 windowId, realWindowId, realElementId);
962 if (windowId != realElementId) {
963 windowElementMap_.AddWindowElementIdPair(windowId, realElementId);
964 }
965 }
966
AddWindowElementMapByAce(int32_t windowId,int64_t elementId)967 void AccessibleAbilityClientImpl::AddWindowElementMapByAce(int32_t windowId, int64_t elementId)
968 {
969 // only used for scene board window, non scene board window not need window element map
970 if (windowId == SCENE_BOARD_WINDOW_ID) {
971 int32_t innerWid = INVALID_SCENE_BOARD_INNER_WINDOW_ID;
972 serviceProxy_->GetSceneBoardInnerWinId(windowId, elementId, innerWid);
973 HILOG_DEBUG("windowId %{public}d, elementId %{public}" PRId64 ", innerWid %{public}d",
974 windowId, elementId, innerWid);
975 if (innerWid != INVALID_SCENE_BOARD_INNER_WINDOW_ID) {
976 windowElementMap_.AddWindowElementIdPair(innerWid, elementId);
977 }
978 }
979 }
980
GetElementInfoFromCache(int32_t windowId,int64_t elementId,std::vector<AccessibilityElementInfo> & elementInfos)981 RetError AccessibleAbilityClientImpl::GetElementInfoFromCache(int32_t windowId, int64_t elementId,
982 std::vector<AccessibilityElementInfo> &elementInfos)
983 {
984 if (windowId == SCENE_BOARD_WINDOW_ID) { // sceneboard window id
985 if (elementCacheInfo_.GetElementByWindowId(windowId, elementId, elementInfos)) {
986 HILOG_DEBUG("get element info from cache");
987 return RET_OK;
988 }
989
990 std::vector<int32_t> windowsList = windowElementMap_.GetWindowIdList();
991 for (auto tmpWindowId : windowsList) {
992 if (elementCacheInfo_.GetElementByWindowId(tmpWindowId, elementId, elementInfos)) {
993 HILOG_DEBUG("get element info from cache");
994 return RET_OK;
995 }
996 }
997 } else {
998 if (elementCacheInfo_.GetElementByWindowId(windowId, elementId, elementInfos)) {
999 HILOG_DEBUG("get element info from cache");
1000 return RET_OK;
1001 }
1002 }
1003
1004 return RET_ERR_FAILED;
1005 }
1006
SearchElementInfoRecursive(int32_t windowId,int64_t elementId,int mode,std::vector<AccessibilityElementInfo> & elementInfos)1007 RetError AccessibleAbilityClientImpl::SearchElementInfoRecursive(int32_t windowId, int64_t elementId, int mode,
1008 std::vector<AccessibilityElementInfo> &elementInfos)
1009 {
1010 RetError ret = channelClient_->SearchElementInfosByAccessibilityId(windowId, elementId,
1011 mode, elementInfos);
1012 if (ret != RET_OK) {
1013 HILOG_ERROR("search element info failed. windowId %{public}d elementId %{public}" PRId64 "",
1014 windowId, elementId);
1015 return ret;
1016 }
1017
1018 if (elementInfos.empty()) {
1019 HILOG_ERROR("elementInfos from ace is empty");
1020 return RET_ERR_INVALID_ELEMENT_INFO_FROM_ACE;
1021 }
1022
1023 return RET_OK;
1024 }
1025
RemoveCacheData(const AccessibilityEventInfo & eventInfo)1026 void AccessibleAbilityClientImpl::RemoveCacheData(const AccessibilityEventInfo& eventInfo)
1027 {
1028 EventType type = eventInfo.GetEventType();
1029 if (type == TYPE_VIEW_TEXT_UPDATE_EVENT || type == TYPE_PAGE_STATE_UPDATE ||
1030 type == TYPE_NOTIFICATION_UPDATE_EVENT || type == TYPE_PAGE_CONTENT_UPDATE ||
1031 type == TYPE_VIEW_TEXT_SELECTION_UPDATE_EVENT || type == TYPE_WINDOW_UPDATE) {
1032 int32_t windowId = eventInfo.GetWindowId();
1033 HILOG_DEBUG("RemoveCacheData windowId %{public}d", windowId);
1034 if (windowId == SCENE_BOARD_WINDOW_ID) {
1035 elementCacheInfo_.RemoveElementByWindowId(windowId);
1036 windowElementMap_.RemovePairByWindowId(windowId);
1037
1038 auto windowList = windowElementMap_.GetWindowIdList();
1039 windowElementMap_.RemovePairByWindowIdList(windowList);
1040 for (auto window: windowList) {
1041 elementCacheInfo_.RemoveElementByWindowId(window);
1042 }
1043 } else {
1044 elementCacheInfo_.RemoveElementByWindowId(windowId);
1045 windowElementMap_.RemovePairByWindowId(windowId);
1046 }
1047 }
1048 }
1049
AddCacheByWMS(int32_t windowId,int64_t elementId,std::vector<AccessibilityElementInfo> & elementInfos)1050 void AccessibleAbilityClientImpl::AddCacheByWMS(int32_t windowId, int64_t elementId,
1051 std::vector<AccessibilityElementInfo>& elementInfos)
1052 {
1053 HILOG_DEBUG("elementSize %{public}zu", elementInfos.size());
1054 AddWindowElementMapByWMS(windowId, elementId);
1055 elementCacheInfo_.AddElementCache(windowId, elementInfos);
1056 }
1057
AddCacheByAce(int32_t windowId,int64_t elementId,std::vector<AccessibilityElementInfo> & elementInfos)1058 void AccessibleAbilityClientImpl::AddCacheByAce(int32_t windowId, int64_t elementId,
1059 std::vector<AccessibilityElementInfo>& elementInfos)
1060 {
1061 AddWindowElementMapByAce(windowId, elementId);
1062 HILOG_DEBUG("elementSize %{public}zu", elementInfos.size());
1063 if (windowId == SCENE_BOARD_WINDOW_ID) {
1064 windowId = windowElementMap_.GetWindowIdByElementId(elementId);
1065 HILOG_DEBUG("windowId convert to %{public}d", windowId);
1066 if (windowId == INVALID_SCENE_BOARD_INNER_WINDOW_ID) {
1067 elementCacheInfo_.AddElementCache(SCENE_BOARD_WINDOW_ID, elementInfos);
1068 } else {
1069 elementCacheInfo_.AddElementCache(windowId, elementInfos);
1070 }
1071 } else {
1072 elementCacheInfo_.AddElementCache(windowId, elementInfos);
1073 }
1074 }
1075
AddElementCache(const int32_t windowId,const std::vector<AccessibilityElementInfo> & elementInfos)1076 void AccessibleAbilityClientImpl::ElementCacheInfo::AddElementCache(const int32_t windowId,
1077 const std::vector<AccessibilityElementInfo>& elementInfos)
1078 {
1079 std::lock_guard<std::mutex> lock(elementCacheMutex_);
1080 if (windowIdSet_.size() >= MAX_CACHE_WINDOW_SIZE) {
1081 auto winId = windowIdSet_.front();
1082 windowIdSet_.pop_front();
1083 elementCache_.erase(winId);
1084 }
1085
1086 elementCache_.erase(windowId);
1087
1088 std::map<int32_t, std::shared_ptr<AccessibilityElementInfo>> cache;
1089 for (auto& elementInfo : elementInfos) {
1090 int64_t elementId = elementInfo.GetAccessibilityId();
1091 cache[elementId] = std::make_shared<AccessibilityElementInfo>(elementInfo);
1092 }
1093
1094 elementCache_[windowId] = std::move(cache);
1095 windowIdSet_.push_back(windowId);
1096 }
1097
GetElementByWindowIdBFS(const int64_t realElementId,std::vector<AccessibilityElementInfo> & elementInfos,std::map<int32_t,std::shared_ptr<AccessibilityElementInfo>> & cache)1098 bool AccessibleAbilityClientImpl::ElementCacheInfo::GetElementByWindowIdBFS(const int64_t realElementId,
1099 std::vector<AccessibilityElementInfo>& elementInfos,
1100 std::map<int32_t, std::shared_ptr<AccessibilityElementInfo>>& cache)
1101 {
1102 std::vector<int64_t> elementList;
1103 elementList.push_back(realElementId);
1104 uint32_t index = 0;
1105 while (index < elementList.size()) {
1106 auto iter = cache.find(elementList[index]);
1107 if (iter == cache.end()) {
1108 elementInfos.clear();
1109 HILOG_DEBUG("element data abnormal, clear elementInfos");
1110 return false;
1111 }
1112
1113 elementInfos.push_back(*(iter->second));
1114 std::vector<int64_t> childrenNode = iter->second->GetChildIds();
1115 for (auto& node : childrenNode) {
1116 elementList.push_back(node);
1117 }
1118 index++;
1119 }
1120 return true;
1121 }
1122
1123 // window id is true, element id is true
GetElementByWindowId(const int32_t windowId,const int64_t elementId,std::vector<AccessibilityElementInfo> & elementInfos)1124 bool AccessibleAbilityClientImpl::ElementCacheInfo::GetElementByWindowId(const int32_t windowId,
1125 const int64_t elementId, std::vector<AccessibilityElementInfo>& elementInfos)
1126 {
1127 elementInfos.clear(); // clear
1128 std::lock_guard<std::mutex> lock(elementCacheMutex_);
1129 if (elementCache_.find(windowId) == elementCache_.end()) {
1130 HILOG_DEBUG("windowId %{public}d is not existed", windowId);
1131 return false;
1132 }
1133
1134 auto& cache = elementCache_.find(windowId)->second;
1135 if (cache.size() == 0) {
1136 HILOG_DEBUG("windowId %{public}d element is null", windowId);
1137 return false;
1138 }
1139
1140 if (cache.find(elementId) == cache.end() && elementId != ROOT_NONE_ID) {
1141 HILOG_DEBUG("elementId %{public}" PRId64 " is not existed", elementId);
1142 return false;
1143 }
1144
1145 int64_t realElementId = elementId;
1146 if (realElementId == ROOT_NONE_ID) {
1147 for (auto iter = cache.begin(); iter != cache.end(); iter++) {
1148 if (iter->second->GetComponentType() == "root") {
1149 realElementId = iter->first;
1150 HILOG_DEBUG("find realElementId %{public}" PRId64 "", realElementId);
1151 break;
1152 }
1153 }
1154 }
1155
1156 if (realElementId == ROOT_NONE_ID) {
1157 HILOG_ERROR("elementId %{public}" PRId64 " is not existed", realElementId);
1158 return false;
1159 }
1160
1161 if (!GetElementByWindowIdBFS(realElementId, elementInfos, cache)) {
1162 HILOG_DEBUG("get window element fail");
1163 return false;
1164 }
1165
1166 HILOG_DEBUG("get element info success, element size %{public}zu", elementInfos.size());
1167 return true;
1168 }
1169
RemoveElementByWindowId(const int32_t windowId)1170 void AccessibleAbilityClientImpl::ElementCacheInfo::RemoveElementByWindowId(const int32_t windowId)
1171 {
1172 std::lock_guard<std::mutex> lock(elementCacheMutex_);
1173 HILOG_DEBUG("erase windowId %{public}d cache", windowId);
1174 for (auto iter = windowIdSet_.begin(); iter != windowIdSet_.end(); iter++) {
1175 if (*iter == windowId) {
1176 windowIdSet_.erase(iter);
1177 break;
1178 }
1179 }
1180
1181 elementCache_.erase(windowId);
1182 }
1183
IsExistWindowId(int32_t windowId)1184 bool AccessibleAbilityClientImpl::ElementCacheInfo::IsExistWindowId(int32_t windowId)
1185 {
1186 std::lock_guard<std::mutex> lock(elementCacheMutex_);
1187 for (auto iter = windowIdSet_.begin(); iter != windowIdSet_.end(); iter++) {
1188 if (*iter == windowId) {
1189 return true;
1190 }
1191 }
1192
1193 return false;
1194 }
1195
IsExistWindowId(int32_t windowId)1196 bool AccessibleAbilityClientImpl::SceneBoardWindowElementMap::IsExistWindowId(int32_t windowId)
1197 {
1198 std::lock_guard<std::mutex> lock(mapMutex_);
1199 if (windowElementMap_.find(windowId) != windowElementMap_.end()) {
1200 return true;
1201 }
1202
1203 return false;
1204 }
1205
AddWindowElementIdPair(int32_t windowId,int64_t elementId)1206 void AccessibleAbilityClientImpl::SceneBoardWindowElementMap::AddWindowElementIdPair(int32_t windowId,
1207 int64_t elementId)
1208 {
1209 std::lock_guard<std::mutex> lock(mapMutex_);
1210 windowElementMap_[windowId] = elementId;
1211 }
1212
GetWindowIdList()1213 std::vector<int32_t> AccessibleAbilityClientImpl::SceneBoardWindowElementMap::GetWindowIdList()
1214 {
1215 std::lock_guard<std::mutex> lock(mapMutex_);
1216 std::vector<int32_t> windowList;
1217 for (auto iter = windowElementMap_.begin(); iter != windowElementMap_.end(); iter++) {
1218 windowList.push_back(iter->first);
1219 }
1220
1221 return windowList;
1222 }
1223
GetWindowIdByElementId(int64_t elementId)1224 int32_t AccessibleAbilityClientImpl::SceneBoardWindowElementMap::GetWindowIdByElementId(int64_t elementId)
1225 {
1226 std::lock_guard<std::mutex> lock(mapMutex_);
1227 for (auto iter = windowElementMap_.begin(); iter != windowElementMap_.end(); iter++) {
1228 if (iter->second == elementId) {
1229 return iter->first;
1230 }
1231 }
1232
1233 return INVALID_SCENE_BOARD_INNER_WINDOW_ID;
1234 }
1235
RemovePairByWindowIdList(std::vector<int32_t> & windowIdList)1236 void AccessibleAbilityClientImpl::SceneBoardWindowElementMap::RemovePairByWindowIdList(
1237 std::vector<int32_t>& windowIdList)
1238 {
1239 std::lock_guard<std::mutex> lock(mapMutex_);
1240 for (auto windowId : windowIdList) {
1241 windowElementMap_.erase(windowId);
1242 }
1243 }
1244
RemovePairByWindowId(int32_t windowId)1245 void AccessibleAbilityClientImpl::SceneBoardWindowElementMap::RemovePairByWindowId(int32_t windowId)
1246 {
1247 std::lock_guard<std::mutex> lock(mapMutex_);
1248 windowElementMap_.erase(windowId);
1249 }
1250 } // namespace Accessibility
1251 } // namespace OHOS