• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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