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 
30 namespace OHOS {
31 namespace Accessibility {
32 // tmp: wait for window registing when client connect done
33 constexpr int WAIT_WINDOW_REGIST = 500;
34 constexpr int64_t ROOT_PARENT_ELEMENT_ID = -2100000;
35 const int32_t ROOT_TREE_ID = 0;
36 constexpr uint64_t ELEMENT_MOVE_BIT = 40;
37 namespace {
38     const std::string SYSTEM_PARAMETER_AAMS_SERVICE = "accessibility.config.ready";
39     constexpr int32_t CONFIG_PARAMETER_VALUE_SIZE = 10;
40     constexpr int64_t ROOT_NONE_ID = -1;
41     constexpr int64_t NODE_ID_MAX = 0x7FFFFFFE;
42     ffrt::mutex g_Mutex;
43     sptr<AccessibleAbilityClientImpl> g_Instance = nullptr;
44     constexpr int32_t SA_CONNECT_TIMEOUT = 500; // ms
45 } // namespace
46 
GetInstance()47 sptr<AccessibleAbilityClient> AccessibleAbilityClient::GetInstance()
48 {
49     HILOG_DEBUG();
50     std::lock_guard<ffrt::mutex> lock(g_Mutex);
51     if (g_Instance == nullptr) {
52         g_Instance = new(std::nothrow) AccessibleAbilityClientImpl();
53     }
54     return g_Instance;
55 }
56 
GetAbilityClientImplement()57 sptr<AccessibleAbilityClientImpl> AccessibleAbilityClientImpl::GetAbilityClientImplement()
58 {
59     HILOG_DEBUG();
60     std::lock_guard<ffrt::mutex> lock(g_Mutex);
61     if (g_Instance == nullptr) {
62         g_Instance = new(std::nothrow) AccessibleAbilityClientImpl();
63     }
64     return g_Instance;
65 }
66 
AccessibleAbilityClientImpl()67 AccessibleAbilityClientImpl::AccessibleAbilityClientImpl()
68 {
69     HILOG_DEBUG();
70     if (!InitAccessibilityServiceProxy()) {
71         HILOG_ERROR("Init accessibility service proxy failed");
72     }
73 #ifndef ACCESSIBILITY_WATCH_FEATURE
74     int retSysParam = WatchParameter(SYSTEM_PARAMETER_AAMS_SERVICE.c_str(),
75         &AccessibleAbilityClientImpl::OnParameterChanged, this);
76     if (retSysParam) {
77         HILOG_ERROR("Watch parameter failed, error = %{public}d", retSysParam);
78     }
79 #endif // ACCESSIBILITY_WATCH_FEATURE
80 }
81 
~AccessibleAbilityClientImpl()82 AccessibleAbilityClientImpl::~AccessibleAbilityClientImpl()
83 {
84     HILOG_DEBUG();
85     std::lock_guard<ffrt::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_ != nullptr) {
95         HILOG_DEBUG("Accessibility Service is connected");
96         return true;
97     }
98 
99     sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
100     if (samgr == nullptr) {
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 != nullptr) {
108         if (accessibilityServiceDeathRecipient_ == nullptr) {
109             accessibilityServiceDeathRecipient_ = new(std::nothrow) AccessibilityServiceDeathRecipient(*this);
110             if (accessibilityServiceDeathRecipient_ == nullptr) {
111                 HILOG_ERROR("Failed to create service deathRecipient.");
112                 return false;
113             }
114         }
115         serviceProxy_ = iface_cast<IAccessibleAbilityManagerService>(object);
116         if (serviceProxy_ == nullptr) {
117             HILOG_ERROR("InitAccessibilityServiceProxy failed.");
118             return false;
119         }
120         if (serviceProxy_->AsObject() &&
121             serviceProxy_->AsObject()->AddDeathRecipient(accessibilityServiceDeathRecipient_)) {
122             return true;
123         }
124     } else {
125 #ifdef ACCESSIBILITY_WATCH_FEATURE
126         if (LoadAccessibilityService() == false) {
127             HILOG_ERROR("LoadSystemAbilityService failed.");
128             return false;
129         } else {
130             return true;
131         }
132 #endif // ACCESSIBILITY_WATCH_FEATURE
133     }
134     return false;
135 }
136 
OnParameterChanged(const char * key,const char * value,void * context)137 void AccessibleAbilityClientImpl::OnParameterChanged(const char *key, const char *value, void *context)
138 {
139     if (key == nullptr || std::strcmp(key, SYSTEM_PARAMETER_AAMS_SERVICE.c_str())) {
140         return;
141     }
142     if (value == nullptr || std::strcmp(value, "true")) {
143         return;
144     }
145     if (context == nullptr) {
146         return;
147     }
148 
149     AccessibleAbilityClientImpl *implPtr = static_cast<AccessibleAbilityClientImpl *>(context);
150     std::lock_guard<ffrt::mutex> lock(implPtr->mutex_);
151     if (implPtr->InitAccessibilityServiceProxy()) {
152         HILOG_INFO("InitAccessibilityServiceProxy success");
153     }
154 }
155 
CheckServiceProxy()156 bool AccessibleAbilityClientImpl::CheckServiceProxy()
157 {
158 #ifndef ACCESSIBILITY_WATCH_FEATURE
159     return serviceProxy_ != nullptr;
160 #else
161     if (serviceProxy_ != nullptr || LoadAccessibilityService() == true) {
162         return true;
163     }
164     return false;
165 #endif // ACCESSIBILITY_WATCH_FEATURE
166 }
167 
CheckConnection()168 RetError AccessibleAbilityClientImpl::CheckConnection()
169 {
170     if (!isConnected_) {
171         HILOG_ERROR("connection is broken");
172         return RET_ERR_NO_CONNECTION;
173     }
174     if (!channelClient_) {
175         HILOG_ERROR("connection is broken");
176         return RET_ERR_NO_CONNECTION;
177     }
178     return RET_OK;
179 }
180 
LoadAccessibilityService()181 bool AccessibleAbilityClientImpl::LoadAccessibilityService()
182 {
183     std::unique_lock<ffrt::mutex> lock(conVarMutex_);
184     sptr<AccessibilityLoadCallback> loadCallback = new AccessibilityLoadCallback();
185     if (loadCallback == nullptr) {
186         return false;
187     }
188     auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
189     if (samgr == nullptr) {
190         return false;
191     }
192     int32_t ret = samgr->LoadSystemAbility(ACCESSIBILITY_MANAGER_SERVICE_ID, loadCallback);
193     if (ret != 0) {
194         return false;
195     }
196     auto waitStatus = proxyConVar_.wait_for(lock, std::chrono::milliseconds(SA_CONNECT_TIMEOUT),
197         [this]() { return serviceProxy_ != nullptr; });
198     if (!waitStatus) {
199         return false;
200     }
201     return true;
202 }
203 
LoadSystemAbilitySuccess(const sptr<IRemoteObject> & remoteObject)204 void AccessibleAbilityClientImpl::LoadSystemAbilitySuccess(const sptr<IRemoteObject> &remoteObject)
205 {
206     std::lock_guard<ffrt::mutex> lock(conVarMutex_);
207     char value[CONFIG_PARAMETER_VALUE_SIZE] = "default";
208     int retSysParam = GetParameter(SYSTEM_PARAMETER_AAMS_SERVICE.c_str(), "false", value, CONFIG_PARAMETER_VALUE_SIZE);
209     do {
210         if (serviceProxy_ != nullptr) {
211             break;
212         }
213         if (retSysParam >= 0 && !std::strcmp(value, "true")) {
214             break;
215         }
216         sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
217         if (samgr == nullptr) {
218             break;
219         }
220         sptr<IRemoteObject> object = samgr->GetSystemAbility(ACCESSIBILITY_MANAGER_SERVICE_ID);
221         if (object == nullptr) {
222             break;
223         }
224         serviceProxy_ = iface_cast<IAccessibleAbilityManagerService>(object);
225         if (serviceProxy_ == nullptr) {
226             break;
227         }
228         if (accessibilityServiceDeathRecipient_ == nullptr) {
229             accessibilityServiceDeathRecipient_ = new(std::nothrow) AccessibilityServiceDeathRecipient(*this);
230         }
231         if (accessibilityServiceDeathRecipient_ == nullptr) {
232             break;
233         }
234         if (serviceProxy_->AsObject() != nullptr) {
235             serviceProxy_->AsObject()->AddDeathRecipient(accessibilityServiceDeathRecipient_);
236         }
237     } while (0);
238     proxyConVar_.notify_one();
239 }
240 
LoadSystemAbilityFail()241 void AccessibleAbilityClientImpl::LoadSystemAbilityFail()
242 {
243     std::lock_guard<ffrt::mutex> lock(conVarMutex_);
244     HILOG_WARN("LoadSystemAbilityFail.");
245     proxyConVar_.notify_one();
246 }
247 
GetRemoteObject()248 sptr<IRemoteObject> AccessibleAbilityClientImpl::GetRemoteObject()
249 {
250     HILOG_DEBUG();
251     return this->AsObject();
252 }
253 
RegisterAbilityListener(const std::shared_ptr<AccessibleAbilityListener> & listener)254 RetError AccessibleAbilityClientImpl::RegisterAbilityListener(
255     const std::shared_ptr<AccessibleAbilityListener> &listener)
256 {
257     HILOG_DEBUG();
258     std::lock_guard<ffrt::mutex> lock(mutex_);
259     if (listener_) {
260         HILOG_DEBUG("listener already exists.");
261         return RET_ERR_REGISTER_EXIST;
262     }
263 
264     listener_ = listener;
265     return RET_OK;
266 }
267 
Init(const sptr<IAccessibleAbilityChannel> & channel,const int32_t channelId)268 void AccessibleAbilityClientImpl::Init(const sptr<IAccessibleAbilityChannel> &channel, const int32_t channelId)
269 {
270     HILOG_DEBUG("channelId[%{public}d]", channelId);
271     if (!channel || channelId == INVALID_CHANNEL_ID) {
272         HILOG_ERROR("channel is nullptr, or channelId is invalid");
273         return;
274     }
275 
276     std::shared_ptr<AccessibleAbilityListener> listener = nullptr;
277     {
278         std::lock_guard<ffrt::mutex> lock(mutex_);
279         if (!listener_) {
280             HILOG_ERROR("listener_ is nullptr.");
281             return;
282         }
283         listener = listener_;
284         channelClient_ = std::make_shared<AccessibleAbilityChannelClient>(channelId, channel);
285 
286         // Add death recipient
287         if (deathRecipient_ == nullptr) {
288             deathRecipient_ = new(std::nothrow) AccessibleAbilityDeathRecipient(*this);
289             if (deathRecipient_ == nullptr) {
290                 HILOG_ERROR("Failed to create deathRecipient.");
291                 return;
292             }
293         }
294 
295         if (channel->AsObject()) {
296             HILOG_DEBUG("Add death recipient");
297             channel->AsObject()->AddDeathRecipient(deathRecipient_);
298         }
299     }
300 
301     isConnected_ = true;
302     std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_WINDOW_REGIST));
303     if (listener) {
304         listener->OnAbilityConnected();
305     }
306 }
307 
Disconnect(const int32_t channelId)308 void AccessibleAbilityClientImpl::Disconnect(const int32_t channelId)
309 {
310     HILOG_DEBUG("channelId[%{public}d]", channelId);
311 
312     std::shared_ptr<AccessibleAbilityListener> listener = nullptr;
313     {
314         isConnected_ = false;
315         std::lock_guard<ffrt::mutex> lock(mutex_);
316         // Delete death recipient
317         if (channelClient_ && channelClient_->GetRemote()) {
318             HILOG_ERROR("Remove death recipient");
319             channelClient_->GetRemote()->RemoveDeathRecipient(deathRecipient_);
320         }
321 
322         // Remove channel
323         channelClient_ = nullptr;
324         listener = listener_;
325         listener_ = nullptr;
326     }
327 
328     if (listener) {
329         listener->OnAbilityDisconnected();
330     }
331 }
332 
OnAccessibilityEvent(const AccessibilityEventInfo & eventInfo)333 void AccessibleAbilityClientImpl::OnAccessibilityEvent(const AccessibilityEventInfo &eventInfo)
334 {
335     HILOG_DEBUG();
336     std::shared_ptr<AccessibleAbilityListener> listener = nullptr;
337     {
338         std::lock_guard<ffrt::mutex> lock(mutex_);
339         if (!channelClient_) {
340             HILOG_ERROR("The channel is invalid.");
341             return;
342         }
343         listener = listener_;
344     }
345     if (listener) {
346         listener->OnAccessibilityEvent(eventInfo);
347     }
348 }
349 
OnKeyPressEvent(const MMI::KeyEvent & keyEvent,const int32_t sequence)350 void AccessibleAbilityClientImpl::OnKeyPressEvent(const MMI::KeyEvent &keyEvent, const int32_t sequence)
351 {
352     HILOG_DEBUG("sequence[%{public}d]", sequence);
353     std::shared_ptr<AccessibleAbilityListener> listener = nullptr;
354     std::shared_ptr<AccessibleAbilityChannelClient> channel = nullptr;
355     {
356         std::lock_guard<ffrt::mutex> lock(mutex_);
357         listener = listener_;
358         channel = channelClient_;
359     }
360 
361     if (!channel) {
362         HILOG_ERROR("The channel is invalid.");
363         return;
364     }
365     bool handled = false;
366     if (listener) {
367         std::shared_ptr<MMI::KeyEvent> tmp = std::make_shared<MMI::KeyEvent>(keyEvent);
368         handled = listener->OnKeyPressEvent(tmp);
369     }
370     channel->SetOnKeyPressEventResult(handled, sequence);
371 }
372 
GetFocus(const int32_t focusType,AccessibilityElementInfo & elementInfo)373 RetError AccessibleAbilityClientImpl::GetFocus(const int32_t focusType, AccessibilityElementInfo &elementInfo)
374 {
375     HILOG_DEBUG("focusType[%{public}d]", focusType);
376     if (!isConnected_) {
377         HILOG_ERROR("connection is broken");
378         return RET_ERR_NO_CONNECTION;
379     }
380 
381     std::lock_guard<ffrt::mutex> lock(mutex_);
382     if ((focusType != FOCUS_TYPE_INPUT) && (focusType != FOCUS_TYPE_ACCESSIBILITY)) {
383         HILOG_ERROR("focusType is not allowed.");
384         return RET_ERR_INVALID_PARAM;
385     }
386 
387     if (!channelClient_) {
388         HILOG_ERROR("The channel is invalid.");
389         return RET_ERR_NO_CONNECTION;
390     }
391 
392     return channelClient_->FindFocusedElementInfo(ANY_WINDOW_ID, ROOT_NODE_ID, focusType, elementInfo);
393 }
394 
GetFocusByElementInfo(const AccessibilityElementInfo & sourceInfo,const int32_t focusType,AccessibilityElementInfo & elementInfo)395 RetError AccessibleAbilityClientImpl::GetFocusByElementInfo(const AccessibilityElementInfo &sourceInfo,
396     const int32_t focusType, AccessibilityElementInfo &elementInfo)
397 {
398     HILOG_DEBUG("focusType[%{public}d]", focusType);
399     if (!isConnected_) {
400         HILOG_ERROR("connection is broken");
401         return RET_ERR_NO_CONNECTION;
402     }
403 
404     std::lock_guard<ffrt::mutex> lock(mutex_);
405     if ((focusType != FOCUS_TYPE_INPUT) && (focusType != FOCUS_TYPE_ACCESSIBILITY)) {
406         HILOG_ERROR("focusType is not allowed.");
407         return RET_ERR_INVALID_PARAM;
408     }
409 
410     if (!channelClient_) {
411         HILOG_ERROR("The channel is invalid.");
412         return RET_ERR_NO_CONNECTION;
413     }
414 
415     int32_t windowId = sourceInfo.GetWindowId();
416     int64_t elementId = sourceInfo.GetAccessibilityId();
417     HILOG_DEBUG("windowId[%{public}d], elementId[%{public}" PRId64 "], focusType[%{public}d]",
418         windowId, elementId, focusType);
419 
420     RetError ret = channelClient_->FindFocusedElementInfo(windowId, elementId, focusType, elementInfo);
421     if (ret == RET_OK) {
422         elementInfo.SetMainWindowId(sourceInfo.GetMainWindowId());
423     }
424     return ret;
425 }
426 
InjectGesture(const std::shared_ptr<AccessibilityGestureInjectPath> & gesturePath)427 RetError AccessibleAbilityClientImpl::InjectGesture(const std::shared_ptr<AccessibilityGestureInjectPath> &gesturePath)
428 {
429     HILOG_DEBUG();
430     if (!isConnected_) {
431         HILOG_ERROR("connection is broken");
432         return RET_ERR_NO_CONNECTION;
433     }
434 
435     std::lock_guard<ffrt::mutex> lock(mutex_);
436     if (!gesturePath) {
437         HILOG_ERROR("The gesturePath is null.");
438         return RET_ERR_INVALID_PARAM;
439     }
440 
441     std::vector<AccessibilityGesturePosition> positions = gesturePath->GetPositions();
442 
443     if (positions.size() == 0) {
444         HILOG_ERROR("The number of gesture path position is not allowed.");
445         return RET_ERR_INVALID_PARAM;
446     }
447 
448     if (!channelClient_) {
449         HILOG_ERROR("The channel is invalid.");
450         return RET_ERR_NO_CONNECTION;
451     }
452 
453     return channelClient_->SendSimulateGesture(gesturePath);
454 }
455 
GetRoot(AccessibilityElementInfo & elementInfo)456 RetError AccessibleAbilityClientImpl::GetRoot(AccessibilityElementInfo &elementInfo)
457 {
458     HILOG_DEBUG();
459     if (!isConnected_) {
460         HILOG_ERROR("connection is broken");
461         return RET_ERR_NO_CONNECTION;
462     }
463 
464     std::lock_guard<ffrt::mutex> lock(mutex_);
465     if (CheckServiceProxy() == false) {
466         HILOG_ERROR("failed to connect to aams.");
467         return RET_ERR_SAMGR;
468     }
469 
470     if (!channelClient_) {
471         HILOG_ERROR("The channel is invalid.");
472         return RET_ERR_NO_CONNECTION;
473     }
474 
475     int32_t activeWindow = serviceProxy_->GetActiveWindow();
476     HILOG_DEBUG("activeWindow[%{public}d]", activeWindow);
477     if (GetCacheElementInfo(activeWindow, ROOT_NONE_ID, elementInfo)) {
478         HILOG_DEBUG("get element info from cache");
479         return RET_OK;
480     }
481 
482     RetError ret = SearchElementInfoFromAce(activeWindow, ROOT_NONE_ID, cacheMode_, elementInfo);
483     if (ret == RET_OK) {
484         elementInfo.SetMainWindowId(activeWindow);
485     }
486     return ret;
487 }
488 
GetRootByWindow(const AccessibilityWindowInfo & windowInfo,AccessibilityElementInfo & elementInfo)489 RetError AccessibleAbilityClientImpl::GetRootByWindow(const AccessibilityWindowInfo &windowInfo,
490     AccessibilityElementInfo &elementInfo)
491 {
492     HILOG_DEBUG();
493     if (!isConnected_) {
494         HILOG_ERROR("connection is broken");
495         return RET_ERR_NO_CONNECTION;
496     }
497 
498     std::lock_guard<ffrt::mutex> lock(mutex_);
499     if (!channelClient_) {
500         HILOG_ERROR("The channel is invalid.");
501         return RET_ERR_NO_CONNECTION;
502     }
503 
504     int32_t windowId = windowInfo.GetWindowId();
505     HILOG_DEBUG("windowId[%{public}d]", windowId);
506     if (GetCacheElementInfo(windowId, ROOT_NONE_ID, elementInfo)) {
507         HILOG_DEBUG("get element info from cache");
508         return RET_OK;
509     }
510 
511     RetError ret = SearchElementInfoFromAce(windowId, ROOT_NONE_ID, cacheMode_, elementInfo);
512     if (ret == RET_OK) {
513         elementInfo.SetMainWindowId(windowId);
514     }
515     return ret;
516 }
517 
GetWindow(const int32_t windowId,AccessibilityWindowInfo & windowInfo)518 RetError AccessibleAbilityClientImpl::GetWindow(const int32_t windowId, AccessibilityWindowInfo &windowInfo)
519 {
520     HILOG_DEBUG("windowId[%{public}d]", windowId);
521     if (!isConnected_) {
522         HILOG_ERROR("connection is broken");
523         return RET_ERR_NO_CONNECTION;
524     }
525 
526     std::lock_guard<ffrt::mutex> lock(mutex_);
527     if (!channelClient_) {
528         HILOG_ERROR("The channel is invalid.");
529         return RET_ERR_NO_CONNECTION;
530     }
531     return channelClient_->GetWindow(windowId, windowInfo);
532 }
533 
GetRootBatch(std::vector<AccessibilityElementInfo> & elementInfos)534 RetError AccessibleAbilityClientImpl::GetRootBatch(std::vector<AccessibilityElementInfo>& elementInfos)
535 {
536     HILOG_DEBUG();
537     if (!isConnected_) {
538         HILOG_ERROR("connection is broken");
539         return RET_ERR_NO_CONNECTION;
540     }
541 
542     std::lock_guard<ffrt::mutex> lock(mutex_);
543     if (!channelClient_) {
544         HILOG_ERROR("channel is invalid.");
545         return RET_ERR_NO_CONNECTION;
546     }
547 
548     if (CheckServiceProxy() == false) {
549         HILOG_ERROR("failed to connect to aams.");
550         return RET_ERR_SAMGR;
551     }
552 
553     int32_t windowId = serviceProxy_->GetActiveWindow();
554     int64_t elementId = ROOT_NONE_ID;
555     RetError ret = SearchElementInfoRecursiveByWinid(windowId, elementId, PREFETCH_RECURSIVE_CHILDREN,
556         elementInfos, ROOT_TREE_ID);
557     if (ret != RET_OK) {
558         HILOG_ERROR("get window element failed.");
559         return ret;
560     }
561     return RET_OK;
562 }
563 
SortElementInfosIfNecessary(std::vector<AccessibilityElementInfo> & elementInfos)564 void AccessibleAbilityClientImpl::SortElementInfosIfNecessary(std::vector<AccessibilityElementInfo> &elementInfos)
565 {
566     HILOG_DEBUG();
567     std::map<int64_t, std::shared_ptr<AccessibilityElementInfo>> elementInfosMap;
568     std::vector<AccessibilityElementInfo> sortedElementInfos;
569     int64_t nodeId = NODE_ID_MAX;
570     int32_t count = 1;
571     AccessibilityElementInfo virtualRoot = elementInfos.front();
572     if (virtualRoot.GetAccessibilityId() != NODE_ID_MAX) {
573         return;
574     }
575     elementInfos.erase(elementInfos.begin());
576     for (auto &element : elementInfos) {
577         if (element.GetAccessibilityId() == NODE_ID_MAX) {
578             nodeId = NODE_ID_MAX - count;
579             element.SetAccessibilityId(nodeId);
580             element.SetParent(NODE_ID_MAX);
581             virtualRoot.AddChild(nodeId);
582             count += 1;
583         }
584         nodeId = element.GetAccessibilityId();
585         elementInfosMap[nodeId] = std::make_shared<AccessibilityElementInfo>(element);
586     }
587     elementInfosMap[NODE_ID_MAX] = std::make_shared<AccessibilityElementInfo>(virtualRoot);
588 
589     std::vector<int64_t> elementList;
590     elementList.push_back(NODE_ID_MAX);
591     uint32_t index = 0;
592     while (index < elementList.size()) {
593         auto iter = elementInfosMap.find(elementList[index]);
594         if (iter == elementInfosMap.end()) {
595             sortedElementInfos.clear();
596             elementInfos.insert(elementInfos.begin(), virtualRoot);
597             return;
598         }
599         sortedElementInfos.push_back(*(iter->second));
600         std::vector<int64_t> childNodeIds = iter->second->GetChildIds();
601         for (auto &id : childNodeIds) {
602             if (std::find(elementList.begin(), elementList.end(), id) == elementList.end()) {
603                 elementList.push_back(id);
604             }
605         }
606         index++;
607     }
608 
609     if (static_cast<int32_t>(sortedElementInfos.size()) > 0) {
610         elementInfos = sortedElementInfos;
611     }
612     elementInfosMap.clear();
613 }
614 
GetRootByWindowBatch(const AccessibilityWindowInfo & windowInfo,std::vector<AccessibilityElementInfo> & elementInfos,bool isFilter)615 RetError AccessibleAbilityClientImpl::GetRootByWindowBatch(const AccessibilityWindowInfo &windowInfo,
616     std::vector<AccessibilityElementInfo>& elementInfos, bool isFilter)
617 {
618     HILOG_DEBUG("GetRootByWindowBatch %{public}d", windowInfo.GetWindowId());
619     if (!isConnected_) {
620         HILOG_ERROR("connection is broken");
621         return RET_ERR_NO_CONNECTION;
622     }
623 
624     std::lock_guard<ffrt::mutex> lock(mutex_);
625     if (CheckServiceProxy() == false) {
626         HILOG_ERROR("failed to connect to aams.");
627         return RET_ERR_SAMGR;
628     }
629 
630     if (!channelClient_) {
631         HILOG_ERROR("channel is invalid.");
632         return RET_ERR_NO_CONNECTION;
633     }
634 
635     int32_t windowId = windowInfo.GetWindowId();
636     int64_t elementId = ROOT_NONE_ID;
637     RetError ret = SearchElementInfoRecursiveByWinid(windowId, elementId,
638         PREFETCH_RECURSIVE_CHILDREN, elementInfos, ROOT_TREE_ID, isFilter);
639     if (ret != RET_OK) {
640         HILOG_ERROR("get window element failed");
641         return ret;
642     }
643     SortElementInfosIfNecessary(elementInfos);
644     return RET_OK;
645 }
646 
GetWindows(std::vector<AccessibilityWindowInfo> & windows)647 RetError AccessibleAbilityClientImpl::GetWindows(std::vector<AccessibilityWindowInfo> &windows)
648 {
649     HILOG_DEBUG();
650     if (!isConnected_) {
651         HILOG_ERROR("connection is broken");
652         return RET_ERR_NO_CONNECTION;
653     }
654 
655     std::lock_guard<ffrt::mutex> lock(mutex_);
656     if (!channelClient_) {
657         HILOG_ERROR("The channel is invalid.");
658         return RET_ERR_NO_CONNECTION;
659     }
660     return channelClient_->GetWindows(windows);
661 }
662 
GetWindows(const uint64_t displayId,std::vector<AccessibilityWindowInfo> & windows)663 RetError AccessibleAbilityClientImpl::GetWindows(const uint64_t displayId,
664     std::vector<AccessibilityWindowInfo> &windows)
665 {
666     HILOG_DEBUG("displayId[%{public}" PRIu64 "]", displayId);
667     if (!isConnected_) {
668         HILOG_ERROR("connection is broken");
669         return RET_ERR_NO_CONNECTION;
670     }
671 
672     std::lock_guard<ffrt::mutex> lock(mutex_);
673     if (!channelClient_) {
674         HILOG_ERROR("The channel is invalid.");
675         return RET_ERR_NO_CONNECTION;
676     }
677     return channelClient_->GetWindows(displayId, windows);
678 }
679 
GetNext(const AccessibilityElementInfo & elementInfo,const FocusMoveDirection direction,AccessibilityElementInfo & nextElementInfo)680 RetError AccessibleAbilityClientImpl::GetNext(const AccessibilityElementInfo &elementInfo,
681     const FocusMoveDirection direction, AccessibilityElementInfo &nextElementInfo)
682 {
683     HILOG_DEBUG("windowId[%{public}d], elementId[%{public}" PRId64 "], direction[%{public}d]",
684         elementInfo.GetWindowId(), elementInfo.GetAccessibilityId(), direction);
685     if (!isConnected_) {
686         HILOG_ERROR("connection is broken");
687         return RET_ERR_NO_CONNECTION;
688     }
689 
690     std::lock_guard<ffrt::mutex> lock(mutex_);
691     if (!channelClient_) {
692         HILOG_ERROR("The channel is invalid.");
693         return RET_ERR_NO_CONNECTION;
694     }
695     if (direction == DIRECTION_INVALID) {
696         HILOG_ERROR("direction is invalid.");
697         return RET_ERR_INVALID_PARAM;
698     }
699     RetError ret = channelClient_->FocusMoveSearch(elementInfo.GetWindowId(),
700         elementInfo.GetAccessibilityId(), direction, nextElementInfo);
701     if (ret == RET_OK) {
702         nextElementInfo.SetMainWindowId(elementInfo.GetMainWindowId());
703     }
704     return ret;
705 }
706 
GetChildElementInfo(const int32_t index,const AccessibilityElementInfo & parent,AccessibilityElementInfo & child)707 RetError AccessibleAbilityClientImpl::GetChildElementInfo(const int32_t index, const AccessibilityElementInfo &parent,
708     AccessibilityElementInfo &child)
709 {
710     HILOG_DEBUG();
711     if (!isConnected_) {
712         HILOG_ERROR("connection is broken");
713         return RET_ERR_NO_CONNECTION;
714     }
715 
716     std::lock_guard<ffrt::mutex> lock(mutex_);
717     if (!channelClient_) {
718         HILOG_ERROR("The channel is invalid.");
719         return RET_ERR_NO_CONNECTION;
720     }
721 
722     int32_t windowId = parent.GetWindowId();
723     int64_t childId = parent.GetChildId(index);
724     HILOG_DEBUG("windowId[%{public}d], childId[%{public}" PRId64 "]", windowId, childId);
725     if (childId == -1) {
726         HILOG_ERROR("childId[%{public}" PRId64 "] is invalid", childId);
727         return RET_ERR_INVALID_PARAM;
728     }
729     if (GetCacheElementInfo(windowId, childId, child)) {
730         HILOG_DEBUG("get element info from cache");
731         return RET_OK;
732     }
733 
734     return SearchElementInfoFromAce(windowId, childId, cacheMode_, child);
735 }
736 
GetChildren(const AccessibilityElementInfo & parent,std::vector<AccessibilityElementInfo> & children)737 RetError AccessibleAbilityClientImpl::GetChildren(const AccessibilityElementInfo &parent,
738     std::vector<AccessibilityElementInfo> &children)
739 {
740     HILOG_DEBUG();
741     std::lock_guard<ffrt::mutex> lock(mutex_);
742     RetError ret = CheckConnection();
743     if (ret != RET_OK) {
744         return ret;
745     }
746     int32_t windowId = parent.GetWindowId();
747     std::vector<int64_t> childIds =  parent.GetChildIds();
748     HILOG_DEBUG("windowId[%{public}d], childIds.size[%{public}zu] childTreeId:%{public}d",
749         windowId, childIds.size(), parent.GetChildTreeId());
750     if ((childIds.size() == 0) && (parent.GetChildWindowId() > 0 || parent.GetChildTreeId() > 0)) {
751         std::vector<AccessibilityElementInfo> elementInfos {};
752         if (parent.GetChildWindowId() > 0 && (parent.GetChildWindowId() != windowId)) {
753             ret = channelClient_->SearchElementInfosByAccessibilityId(parent.GetChildWindowId(), ROOT_NONE_ID,
754                 GET_SOURCE_MODE, elementInfos, parent.GetChildTreeId());
755         } else if (parent.GetChildTreeId() > 0) {
756             ret = channelClient_->SearchElementInfosByAccessibilityId(parent.GetWindowId(), ROOT_NONE_ID,
757                 GET_SOURCE_MODE, elementInfos, parent.GetChildTreeId());
758         }
759         if (ret != RET_OK) {
760             HILOG_ERROR("Get element info from ace failed");
761             return ret;
762         }
763         if (elementInfos.empty()) {
764             HILOG_ERROR("elementInfos from ace is empty");
765             return RET_ERR_INVALID_ELEMENT_INFO_FROM_ACE;
766         }
767         SortElementInfosIfNecessary(elementInfos);
768         children.emplace_back(elementInfos.front());
769     } else if (childIds.size() > 0 && parent.GetChildTreeId() > 0) {
770         std::vector<AccessibilityElementInfo> elementInfos {};
771         ret = channelClient_->SearchElementInfosByAccessibilityId(parent.GetWindowId(), ROOT_NONE_ID,
772             GET_SOURCE_MODE, elementInfos, parent.GetChildTreeId());
773         if (ret != RET_OK) {
774             HILOG_ERROR("Get element info from ace failed");
775             return ret;
776         }
777         children.emplace_back(elementInfos.front());
778     }
779     ret = GetChildrenWork(windowId, childIds, children);
780     if (!children.empty()) {
781         for (auto &child : children) {
782             child.SetMainWindowId(parent.GetMainWindowId());
783         }
784     }
785     return ret;
786 }
787 
GetChildrenWork(const int32_t windowId,std::vector<int64_t> childIds,std::vector<AccessibilityElementInfo> & children)788 RetError AccessibleAbilityClientImpl::GetChildrenWork(const int32_t windowId, std::vector<int64_t> childIds,
789     std::vector<AccessibilityElementInfo> &children)
790 {
791     for (auto &childId : childIds) {
792         HILOG_DEBUG("childId[%{public}" PRId64 "]", childId);
793         if (childId == -1) {
794             HILOG_ERROR("childId is invalid");
795             return RET_ERR_INVALID_PARAM;
796         }
797         AccessibilityElementInfo child;
798         if (GetCacheElementInfo(windowId, childId, child)) {
799             HILOG_DEBUG("get element info from cache");
800             children.emplace_back(child);
801             continue;
802         }
803         RetError ret = SearchElementInfoFromAce(windowId, childId, cacheMode_, child);
804         if (ret != RET_OK) {
805             HILOG_ERROR("Get element info from ace failed");
806             return ret;
807         }
808         children.emplace_back(child);
809     }
810     return RET_OK;
811 }
812 
GetByContent(const AccessibilityElementInfo & elementInfo,const std::string & text,std::vector<AccessibilityElementInfo> & elementInfos)813 RetError AccessibleAbilityClientImpl::GetByContent(const AccessibilityElementInfo &elementInfo,
814     const std::string &text, std::vector<AccessibilityElementInfo> &elementInfos)
815 {
816     HILOG_DEBUG();
817     if (!isConnected_) {
818         HILOG_ERROR("connection is broken");
819         return RET_ERR_NO_CONNECTION;
820     }
821 
822     std::lock_guard<ffrt::mutex> lock(mutex_);
823     if (!channelClient_) {
824         HILOG_ERROR("The channel is invalid.");
825         return RET_ERR_NO_CONNECTION;
826     }
827 
828     int32_t windowId = elementInfo.GetWindowId();
829     int64_t elementId = elementInfo.GetAccessibilityId();
830     int32_t treeId = (static_cast<uint64_t>(elementId) >> ELEMENT_MOVE_BIT);
831 
832     RetError ret = RET_ERR_FAILED;
833     if (text != "") { // find element condition is null, so we will search all element info
834         ret = channelClient_->SearchElementInfosByText(windowId, elementId, text, elementInfos);
835         if (elementInfos.empty()) {
836             ret = SearchElementInfoRecursiveByContent(serviceProxy_->GetActiveWindow(),
837                 elementId, GET_SOURCE_MODE, elementInfos, text, ROOT_TREE_ID);
838         }
839     } else {
840         ret = SearchElementInfoRecursiveByWinid(windowId, elementId, GET_SOURCE_MODE, elementInfos, treeId);
841     }
842     if (!elementInfos.empty()) {
843         for (auto &element : elementInfos) {
844             element.SetMainWindowId(elementInfo.GetMainWindowId());
845         }
846     }
847     HILOG_INFO("ret:%{public}d, windowId:%{public}d, text:%{public}s", ret, windowId, text.c_str());
848     return ret;
849 }
850 
SearchElementInfoRecursiveByContent(const int32_t windowId,const int64_t elementId,uint32_t mode,std::vector<AccessibilityElementInfo> & elementInfos,const std::string text,int32_t treeId,bool isFilter)851 RetError AccessibleAbilityClientImpl::SearchElementInfoRecursiveByContent(const int32_t windowId,
852     const int64_t elementId, uint32_t mode, std::vector<AccessibilityElementInfo> &elementInfos,
853     const std::string text, int32_t treeId, bool isFilter)
854 {
855     HILOG_INFO("windowId %{public}d}, elementId %{public}" PRId64 "", windowId, elementId);
856     if (windowId <= 0) {
857         return RET_ERR_INVALID_ELEMENT_INFO_FROM_ACE;
858     }
859     std::vector<AccessibilityElementInfo> vecElementInfos = {};
860     std::vector<AccessibilityElementInfo> vecTextElementInfos = {};
861     RetError ret = channelClient_->SearchElementInfosByAccessibilityId(windowId, ROOT_NONE_ID,
862         mode, vecElementInfos, treeId, isFilter);
863     if (ret != RET_OK) {
864         HILOG_ERROR("search element info failed. windowId %{public}d}", windowId);
865         return ret;
866     }
867     if (vecElementInfos.empty()) {
868         HILOG_ERROR("elementInfos from ace is empty");
869         return RET_ERR_INVALID_ELEMENT_INFO_FROM_ACE;
870     }
871     HILOG_DEBUG("vecElementInfos Search ok");
872     for (auto info : vecElementInfos) {
873         HILOG_DEBUG("search element info success. windowId %{public}d}",
874             info.GetChildWindowId());
875         if (info.GetParentNodeId() == ROOT_PARENT_ELEMENT_ID) {
876             ret = channelClient_->SearchElementInfosByText(windowId, info.GetAccessibilityId(),
877                 text, vecTextElementInfos);
878             if (ret != RET_OK) {
879                 HILOG_ERROR("SearchElementInfosByText WindowId %{public}d} ret:%{public}d text:%{public}s",
880                     windowId, ret, text.c_str());
881                 return ret;
882             }
883             if (!vecTextElementInfos.empty()) {
884                 elementInfos.insert(elementInfos.end(), vecTextElementInfos.begin(), vecTextElementInfos.end());
885             }
886             HILOG_DEBUG("SearchByText get result size:%{public}zu windowId %{public}d elementId %{public}" PRId64 "",
887                 vecTextElementInfos.size(), windowId, info.GetAccessibilityId());
888         }
889         if (info.GetChildWindowId() > 0 && info.GetChildWindowId() != info.GetWindowId()) {
890             ret = SearchElementInfoRecursiveByContent(info.GetChildWindowId(),
891                 elementId, mode, elementInfos, text, info.GetChildTreeId(), isFilter);
892         } else if (info.GetChildTreeId() > 0) {
893             ret = SearchElementInfoRecursiveByContent(info.GetWindowId(),
894                 elementId, mode, elementInfos, text, info.GetChildTreeId(), isFilter);
895         }
896         if (ret != RET_OK) {
897             HILOG_ERROR("search element info failed.ChildWindowId %{public}d},ChildTreeId %{public}d},ret:%{public}d",
898                 info.GetChildWindowId(), info.GetChildTreeId(), ret);
899         }
900     }
901     return RET_OK;
902 }
903 
GetSource(const AccessibilityEventInfo & eventInfo,AccessibilityElementInfo & elementInfo)904 RetError AccessibleAbilityClientImpl::GetSource(const AccessibilityEventInfo &eventInfo,
905     AccessibilityElementInfo &elementInfo)
906 {
907     HILOG_DEBUG();
908     if (!isConnected_) {
909         HILOG_ERROR("connection is broken");
910         return RET_ERR_NO_CONNECTION;
911     }
912 
913     std::lock_guard<ffrt::mutex> lock(mutex_);
914     if (!channelClient_) {
915         HILOG_ERROR("The channel is invalid.");
916         return RET_ERR_NO_CONNECTION;
917     }
918     int32_t windowId = eventInfo.GetWindowId();
919     int64_t elementId = eventInfo.GetAccessibilityId();
920     HILOG_DEBUG("windowId[%{public}d], elementId[%{public}" PRId64 "]", windowId, elementId);
921     if (GetCacheElementInfo(windowId, elementId, elementInfo)) {
922         HILOG_DEBUG("get element info from cache");
923         return RET_OK;
924     }
925     return SearchElementInfoFromAce(windowId, elementId, cacheMode_, elementInfo);
926 }
927 
GetParentElementInfo(const AccessibilityElementInfo & child,AccessibilityElementInfo & parent)928 RetError AccessibleAbilityClientImpl::GetParentElementInfo(const AccessibilityElementInfo &child,
929     AccessibilityElementInfo &parent)
930 {
931     HILOG_DEBUG();
932     if (!isConnected_) {
933         HILOG_ERROR("connection is broken");
934         return RET_ERR_NO_CONNECTION;
935     }
936 
937     std::lock_guard<ffrt::mutex> lock(mutex_);
938     if (!channelClient_) {
939         HILOG_ERROR("The channel is invalid.");
940         return RET_ERR_NO_CONNECTION;
941     }
942     int32_t windowId = child.GetWindowId();
943     int64_t parentElementId = child.GetParentNodeId();
944     int32_t parentWindowId = child.GetParentWindowId();
945     int32_t treeId = (static_cast<uint64_t>(child.GetAccessibilityId()) >> ELEMENT_MOVE_BIT);
946     HILOG_DEBUG("windowId[%{public}d], parentWindowId[%{public}d], parentId[%{public}" PRId64 "]",
947         windowId, parentWindowId, parentElementId);
948     if (GetCacheElementInfo(windowId, parentElementId, parent)) {
949         HILOG_DEBUG("get element info from cache");
950         return RET_OK;
951     }
952     RetError ret = RET_ERR_FAILED;
953     if ((parentElementId == ROOT_PARENT_ELEMENT_ID) && (parentWindowId > 0)) {
954         parentElementId = serviceProxy_->GetRootParentId(windowId, treeId);
955         if (parentElementId > 0) {
956             treeId = (static_cast<uint64_t>(parentElementId) >> ELEMENT_MOVE_BIT);
957             HILOG_DEBUG("find root parentId and search parentElementId [%{public}" PRId64 "] treeId[%{public}d]",
958                 parentElementId, treeId);
959             ret = SearchElementInfoByElementId(child.GetParentWindowId(), parentElementId, cacheMode_, parent, treeId);
960             parent.SetMainWindowId(child.GetMainWindowId());
961             return ret;
962         } else {
963             HILOG_DEBUG("GetRootParentId faild, parentElement:%{public}" PRId64 "", parentElementId);
964             return RET_ERR_INVALID_ELEMENT_INFO_FROM_ACE;
965         }
966     }
967     ret = SearchElementInfoByElementId(windowId, parentElementId, cacheMode_, parent, treeId);
968     parent.SetMainWindowId(child.GetMainWindowId());
969     return ret;
970 }
971 
GetByElementId(const int64_t elementId,const int32_t windowId,AccessibilityElementInfo & targetElementInfo)972 RetError AccessibleAbilityClientImpl::GetByElementId(const int64_t elementId, const int32_t windowId,
973     AccessibilityElementInfo &targetElementInfo)
974 {
975     HILOG_DEBUG();
976     if (!isConnected_) {
977         HILOG_ERROR("connection is broken");
978         return RET_ERR_NO_CONNECTION;
979     }
980 
981     std::lock_guard<ffrt::mutex> lock(mutex_);
982     if (CheckServiceProxy() == false) {
983         HILOG_ERROR("failed to connect to aams.");
984         return RET_ERR_SAMGR;
985     }
986 
987     if (!channelClient_) {
988         HILOG_ERROR("channel is invalid.");
989         return RET_ERR_NO_CONNECTION;
990     }
991 
992     int32_t treeId = (static_cast<uint64_t>(elementId) >> ELEMENT_MOVE_BIT);
993     HILOG_DEBUG("window:[%{public}d],treeId:%{public}d,elementId:%{public}" PRId64 "",
994         windowId, treeId, elementId);
995     if (GetCacheElementInfo(windowId, elementId, targetElementInfo)) {
996         HILOG_DEBUG("get element info from cache");
997         return RET_OK;
998     }
999 
1000     return SearchElementInfoByElementId(windowId, elementId, cacheMode_, targetElementInfo, treeId);
1001 }
1002 
GetCursorPosition(const AccessibilityElementInfo & elementInfo,int32_t & position)1003 RetError AccessibleAbilityClientImpl::GetCursorPosition(const AccessibilityElementInfo &elementInfo, int32_t &position)
1004 {
1005     HILOG_DEBUG();
1006     if (!isConnected_) {
1007         HILOG_ERROR("connection is broken");
1008         return RET_ERR_NO_CONNECTION;
1009     }
1010 
1011     std::lock_guard<ffrt::mutex> lock(mutex_);
1012     if (!channelClient_) {
1013         HILOG_ERROR("The channel is invalid.");
1014         return RET_ERR_NO_CONNECTION;
1015     }
1016     int32_t windowId = elementInfo.GetWindowId();
1017     int64_t elementId = elementInfo.GetAccessibilityId();
1018     HILOG_DEBUG("windowId[%{public}d], elementId[%{public}" PRId64 "]d", windowId, elementId);
1019     return channelClient_->GetCursorPosition(windowId, elementId, position);
1020 }
1021 
ExecuteAction(const AccessibilityElementInfo & elementInfo,const ActionType action,const std::map<std::string,std::string> & actionArguments)1022 RetError AccessibleAbilityClientImpl::ExecuteAction(const AccessibilityElementInfo &elementInfo,
1023     const ActionType action, const std::map<std::string, std::string> &actionArguments)
1024 {
1025     HILOG_DEBUG();
1026     if (!isConnected_) {
1027         HILOG_ERROR("connection is broken");
1028         return RET_ERR_NO_CONNECTION;
1029     }
1030 
1031     std::lock_guard<ffrt::mutex> lock(mutex_);
1032     if (!channelClient_) {
1033         HILOG_ERROR("The channel is invalid.");
1034         return RET_ERR_NO_CONNECTION;
1035     }
1036     if (action == ACCESSIBILITY_ACTION_INVALID) {
1037         HILOG_ERROR("action is invalid.");
1038         return RET_ERR_INVALID_PARAM;
1039     }
1040     int32_t windowId = elementInfo.GetWindowId();
1041     int64_t elementId = elementInfo.GetAccessibilityId();
1042     HILOG_DEBUG("windowId[%{public}d], elementId[%{public}" PRId64 "], action[%{public}d", windowId, elementId, action);
1043     return channelClient_->ExecuteAction(windowId, elementId, action,
1044         const_cast<std::map<std::string, std::string> &>(actionArguments));
1045 }
1046 
EnableScreenCurtain(bool isEnable)1047 RetError AccessibleAbilityClientImpl::EnableScreenCurtain(bool isEnable)
1048 {
1049     if (!channelClient_) {
1050         HILOG_ERROR("The channel is invalid.");
1051         return RET_ERR_NO_CONNECTION;
1052     }
1053 
1054     return channelClient_->EnableScreenCurtain(isEnable);
1055 }
1056 
SetTargetBundleName(const std::vector<std::string> & targetBundleNames)1057 RetError AccessibleAbilityClientImpl::SetTargetBundleName(const std::vector<std::string> &targetBundleNames)
1058 {
1059     HILOG_DEBUG("targetBundleNames size[%{public}zu]", targetBundleNames.size());
1060     if (!isConnected_) {
1061         HILOG_ERROR("connection is broken");
1062         return RET_ERR_NO_CONNECTION;
1063     }
1064 
1065     std::lock_guard<ffrt::mutex> lock(mutex_);
1066     if (!channelClient_) {
1067         HILOG_ERROR("The channel is invalid.");
1068         return RET_ERR_NO_CONNECTION;
1069     }
1070     return channelClient_->SetTargetBundleName(targetBundleNames);
1071 }
1072 
OnRemoteDied(const wptr<IRemoteObject> & remote)1073 void AccessibleAbilityClientImpl::AccessibleAbilityDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& remote)
1074 {
1075     HILOG_ERROR();
1076     client_.ResetAAClient(remote);
1077 }
1078 
OnRemoteDied(const wptr<IRemoteObject> & remote)1079 void AccessibleAbilityClientImpl::AccessibilityServiceDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& remote)
1080 {
1081     HILOG_ERROR();
1082     client_.NotifyServiceDied(remote);
1083 }
1084 
NotifyServiceDied(const wptr<IRemoteObject> & remote)1085 void AccessibleAbilityClientImpl::NotifyServiceDied(const wptr<IRemoteObject> &remote)
1086 {
1087     std::shared_ptr<AccessibleAbilityListener> listener = nullptr;
1088     {
1089         std::lock_guard<ffrt::mutex> lock(mutex_);
1090         if (!serviceProxy_) {
1091             HILOG_ERROR("serviceProxy_ is nullptr");
1092             return;
1093         }
1094         sptr<IRemoteObject> object = serviceProxy_->AsObject();
1095         if (object && (remote == object)) {
1096             listener = listener_;
1097             listener_ = nullptr;
1098             object->RemoveDeathRecipient(accessibilityServiceDeathRecipient_);
1099             serviceProxy_ = nullptr;
1100             channelClient_ = nullptr;
1101             HILOG_INFO("NotifyServiceDied OK");
1102         }
1103     }
1104 
1105     isConnected_ = false;
1106     if (listener) {
1107         listener->OnAbilityDisconnected();
1108     }
1109 }
1110 
ResetAAClient(const wptr<IRemoteObject> & remote)1111 void AccessibleAbilityClientImpl::ResetAAClient(const wptr<IRemoteObject> &remote)
1112 {
1113     HILOG_DEBUG();
1114     std::lock_guard<ffrt::mutex> lock(mutex_);
1115     if (channelClient_) {
1116         sptr<IRemoteObject> object = channelClient_->GetRemote();
1117         if (object && (remote == object)) {
1118             object->RemoveDeathRecipient(deathRecipient_);
1119             channelClient_ = nullptr;
1120             HILOG_INFO("ResetAAClient OK");
1121         }
1122     }
1123 
1124     isConnected_ = false;
1125 }
1126 
SetCacheMode(const int32_t cacheMode)1127 RetError AccessibleAbilityClientImpl::SetCacheMode(const int32_t cacheMode)
1128 {
1129     HILOG_DEBUG("set cache mode: [%{public}d]", cacheMode);
1130     std::lock_guard<ffrt::mutex> lock(mutex_);
1131     cacheWindowId_ = -1;
1132     cacheElementInfos_.clear();
1133     if (cacheMode < 0) {
1134         cacheMode_ = 0;
1135     } else {
1136         uint32_t mode = static_cast<uint32_t>(cacheMode);
1137         cacheMode_ = mode & static_cast<uint32_t>(GET_SOURCE_PREFETCH_MODE);
1138     }
1139     return RET_OK;
1140 }
1141 
GetCacheElementInfo(const int32_t windowId,const int64_t elementId,AccessibilityElementInfo & elementInfo) const1142 bool AccessibleAbilityClientImpl::GetCacheElementInfo(const int32_t windowId,
1143     const int64_t elementId, AccessibilityElementInfo &elementInfo) const
1144 {
1145     HILOG_DEBUG();
1146     if (cacheWindowId_ == -1 || cacheWindowId_ != windowId) {
1147         HILOG_DEBUG("cacheWindowId[%{public}d], windowId[%{public}d]", cacheWindowId_, windowId);
1148         return false;
1149     }
1150 
1151     auto iter = cacheElementInfos_.find(elementId);
1152     if (iter == cacheElementInfos_.end()) {
1153         HILOG_DEBUG("the element id[%{public}" PRId64 "] is not in cache", elementId);
1154         return false;
1155     }
1156 
1157     elementInfo = iter->second;
1158     return true;
1159 }
1160 
SetCacheElementInfo(const int32_t windowId,const std::vector<OHOS::Accessibility::AccessibilityElementInfo> & elementInfos)1161 void AccessibleAbilityClientImpl::SetCacheElementInfo(const int32_t windowId,
1162     const std::vector<OHOS::Accessibility::AccessibilityElementInfo> &elementInfos)
1163 {
1164     HILOG_DEBUG("windowId[%{public}d], elementInfos size[%{public}zu]", windowId, elementInfos.size());
1165     cacheElementInfos_.clear();
1166     cacheWindowId_ = windowId;
1167     for (auto &elementInfo : elementInfos) {
1168         cacheElementInfos_.insert(std::make_pair(elementInfo.GetAccessibilityId(), elementInfo));
1169     }
1170 }
1171 
SearchElementInfoByElementId(const int32_t windowId,const int64_t elementId,const uint32_t mode,AccessibilityElementInfo & info,int32_t treeId)1172 RetError AccessibleAbilityClientImpl::SearchElementInfoByElementId(const int32_t windowId, const int64_t elementId,
1173     const uint32_t mode, AccessibilityElementInfo &info, int32_t treeId)
1174 {
1175     if (channelClient_ == nullptr) {
1176         HILOG_ERROR("The channel is invalid.");
1177         return RET_ERR_NO_CONNECTION;
1178     }
1179 
1180     HILOG_INFO("windowId %{public}d}, elementId %{public}" PRId64 "", windowId, elementId);
1181     std::vector<AccessibilityElementInfo> elementInfos {};
1182     RetError ret = channelClient_->SearchElementInfosByAccessibilityId(
1183         windowId, elementId, static_cast<int32_t>(mode), elementInfos, treeId);
1184     if (ret != RET_OK) {
1185         HILOG_ERROR("SearchElementInfosByAccessibilityId failed. windowId[%{public}d] ", windowId);
1186         return ret;
1187     }
1188     if (elementInfos.empty()) {
1189         HILOG_ERROR("elementInfos from ace is empty");
1190         return RET_ERR_INVALID_ELEMENT_INFO_FROM_ACE;
1191     }
1192 
1193     HILOG_DEBUG("element [elementSize:%{public}zu]", elementInfos.size());
1194     SetCacheElementInfo(windowId, elementInfos);
1195     info = elementInfos.front();
1196     return RET_OK;
1197 }
1198 
SearchElementInfoFromAce(const int32_t windowId,const int64_t elementId,const uint32_t mode,AccessibilityElementInfo & info)1199 RetError AccessibleAbilityClientImpl::SearchElementInfoFromAce(const int32_t windowId, const int64_t elementId,
1200     const uint32_t mode, AccessibilityElementInfo &info)
1201 {
1202     if (channelClient_ == nullptr) {
1203         HILOG_ERROR("The channel is invalid.");
1204         return RET_ERR_NO_CONNECTION;
1205     }
1206     HILOG_INFO("windowId %{public}d}, elementId %{public}" PRId64 "", windowId, elementId);
1207     std::vector<AccessibilityElementInfo> elementInfos {};
1208     int32_t treeId = 0;
1209     if (elementId != ROOT_NONE_ID) {
1210         treeId = (static_cast<uint64_t>(elementId) >> ELEMENT_MOVE_BIT);
1211     }
1212     RetError ret = channelClient_->SearchElementInfosByAccessibilityId(windowId, elementId,
1213         static_cast<int32_t>(mode), elementInfos, treeId);
1214     if (ret != RET_OK) {
1215         HILOG_ERROR("search element info failed. windowId[%{public}d] elementId[%{public}" PRId64 "] mode[%{public}d]",
1216             windowId, elementId, mode);
1217         return ret;
1218     }
1219     if (!elementInfos.empty()) {
1220         HILOG_DEBUG("element [elementSize:%{public}zu]", elementInfos.size());
1221         SetCacheElementInfo(windowId, elementInfos);
1222         info = elementInfos.front();
1223         HILOG_DEBUG("elementId:%{public}" PRId64 ", windowId:%{public}d, treeId:%{public}d",
1224             info.GetAccessibilityId(), info.GetWindowId(), info.GetBelongTreeId());
1225         return RET_OK;
1226     }
1227 
1228     HILOG_DEBUG("elementInfos from ace is empty find all element");
1229     ret = SearchElementInfoRecursiveByWinid(windowId, ROOT_NONE_ID, GET_SOURCE_MODE, elementInfos, ROOT_TREE_ID);
1230     if (ret != RET_OK) {
1231         HILOG_ERROR("SearchElementInfoRecursiveByWinid failed. windowId[%{public}d]", windowId);
1232         return ret;
1233     }
1234     HILOG_DEBUG("SetCacheElementInfo windowId:%{public}d, element [elementSize:%{public}zu]",
1235         windowId, elementInfos.size());
1236     SetCacheElementInfo(windowId, elementInfos);
1237     if (!GetCacheElementInfo(windowId, elementId, info)) {
1238         return RET_ERR_INVALID_ELEMENT_INFO_FROM_ACE;
1239     }
1240     info.SetMainWindowId(windowId);
1241     HILOG_DEBUG("elementId:%{public}" PRId64 ", windowId:%{public}d, treeId:%{public}d",
1242         info.GetAccessibilityId(), info.GetWindowId(), info.GetBelongTreeId());
1243     return RET_OK;
1244 }
1245 
SearchElementInfoByInspectorKey(const std::string & inspectorKey,AccessibilityElementInfo & elementInfo)1246 RetError AccessibleAbilityClientImpl::SearchElementInfoByInspectorKey(const std::string &inspectorKey,
1247     AccessibilityElementInfo &elementInfo)
1248 {
1249     HILOG_DEBUG();
1250     if (!isConnected_) {
1251         HILOG_ERROR("connection is broken");
1252         return RET_ERR_NO_CONNECTION;
1253     }
1254 
1255     std::lock_guard<ffrt::mutex> lock(mutex_);
1256     if (!channelClient_) {
1257         HILOG_ERROR("The channel is invalid.");
1258         return RET_ERR_NO_CONNECTION;
1259     }
1260 
1261     if (CheckServiceProxy() == false) {
1262         HILOG_ERROR("failed to connect to aams.");
1263         return RET_ERR_SAMGR;
1264     }
1265 
1266     int32_t windowId = serviceProxy_->GetActiveWindow();
1267     HILOG_DEBUG("windowId[%{public}d]", windowId);
1268     std::vector<AccessibilityElementInfo> elementInfos {};
1269 
1270     RetError ret = channelClient_->SearchElementInfosByAccessibilityId(windowId, ROOT_NONE_ID,
1271         static_cast<int32_t>(GET_SOURCE_MODE), elementInfos, ROOT_TREE_ID);
1272     if (ret != RET_OK) {
1273         HILOG_ERROR("search element info failed.");
1274         return ret;
1275     }
1276 
1277     ret = SearchElementInfoRecursiveByWinid(windowId, ROOT_NONE_ID, GET_SOURCE_MODE, elementInfos, ROOT_TREE_ID);
1278     if (ret != RET_OK) {
1279         HILOG_ERROR("get window element failed.");
1280         return ret;
1281     }
1282 
1283     if (elementInfos.empty()) {
1284         HILOG_ERROR("elementInfos from ace is empty");
1285         return RET_ERR_INVALID_ELEMENT_INFO_FROM_ACE;
1286     }
1287     SortElementInfosIfNecessary(elementInfos);
1288     for (auto &info : elementInfos) {
1289         if (info.GetInspectorKey() == inspectorKey) {
1290             HILOG_INFO("find elementInfo by inspectorKey success, inspectorKey: %{public}s", inspectorKey.c_str());
1291             elementInfo = info;
1292             elementInfo.SetMainWindowId(windowId);
1293             return RET_OK;
1294         }
1295     }
1296     HILOG_INFO("SearchElementInfoByInspectorKey failed, inspectorKey: %{public}s", inspectorKey.c_str());
1297     return RET_ERR_FAILED;
1298 }
1299 
Connect()1300 RetError AccessibleAbilityClientImpl::Connect()
1301 {
1302     HILOG_DEBUG();
1303     std::lock_guard<ffrt::mutex> lock(mutex_);
1304     if (CheckServiceProxy() == false) {
1305         HILOG_ERROR("failed to connect to aams.");
1306         return RET_ERR_SAMGR;
1307     }
1308 
1309     return serviceProxy_->EnableUITestAbility(this->AsObject());
1310 }
1311 
Disconnect()1312 RetError AccessibleAbilityClientImpl::Disconnect()
1313 {
1314     HILOG_DEBUG();
1315     std::lock_guard<ffrt::mutex> lock(mutex_);
1316     if (CheckServiceProxy() == false) {
1317         HILOG_ERROR("failed to connect to aams.");
1318         return RET_ERR_SAMGR;
1319     }
1320     return serviceProxy_->DisableUITestAbility();
1321 }
1322 
SetConnectionState(bool state)1323 void AccessibleAbilityClientImpl::SetConnectionState(bool state)
1324 {
1325     isConnected_ = state;
1326 }
1327 
AddWindowElementMapByWMS(int32_t windowId,int64_t elementId)1328 void AccessibleAbilityClientImpl::AddWindowElementMapByWMS(int32_t windowId, int64_t elementId)
1329 {
1330     // only used for scene board window, non scene board window not need window element map
1331     int32_t realWindowId = windowId;
1332     int64_t realElementId = elementId;
1333     serviceProxy_->GetRealWindowAndElementId(realWindowId, realElementId);
1334     HILOG_DEBUG("windowId %{public}d, real windowId %{public}d, real elementId %{public}" PRId64 "",
1335         windowId, realWindowId, realElementId);
1336     if (windowId != realElementId) {
1337         windowElementMap_.AddWindowElementIdPair(windowId, realElementId);
1338     }
1339 }
1340 
AddWindowElementMapByAce(int32_t windowId,int64_t elementId)1341 void AccessibleAbilityClientImpl::AddWindowElementMapByAce(int32_t windowId, int64_t elementId)
1342 {
1343     // only used for scene board window, non scene board window not need window element map
1344     if (windowId == SCENE_BOARD_WINDOW_ID) {
1345         int32_t innerWid = INVALID_SCENE_BOARD_INNER_WINDOW_ID;
1346         serviceProxy_->GetSceneBoardInnerWinId(windowId, elementId, innerWid);
1347         HILOG_DEBUG("windowId %{public}d, elementId %{public}" PRId64 ", innerWid %{public}d",
1348             windowId, elementId, innerWid);
1349         if (innerWid != INVALID_SCENE_BOARD_INNER_WINDOW_ID) {
1350             windowElementMap_.AddWindowElementIdPair(innerWid, elementId);
1351         }
1352     }
1353 }
1354 
GetElementInfoFromCache(int32_t windowId,int64_t elementId,std::vector<AccessibilityElementInfo> & elementInfos)1355 RetError AccessibleAbilityClientImpl::GetElementInfoFromCache(int32_t windowId, int64_t elementId,
1356     std::vector<AccessibilityElementInfo> &elementInfos)
1357 {
1358     if (windowId == SCENE_BOARD_WINDOW_ID) { // sceneboard window id
1359         if (elementCacheInfo_.GetElementByWindowId(windowId, elementId, elementInfos)) {
1360             HILOG_DEBUG("get element info from cache");
1361             return RET_OK;
1362         }
1363 
1364         std::vector<int32_t> windowsList = windowElementMap_.GetWindowIdList();
1365         for (auto tmpWindowId : windowsList) {
1366             if (elementCacheInfo_.GetElementByWindowId(tmpWindowId, elementId, elementInfos)) {
1367                 HILOG_DEBUG("get element info from cache");
1368                 return RET_OK;
1369             }
1370         }
1371     } else {
1372         if (elementCacheInfo_.GetElementByWindowId(windowId, elementId, elementInfos)) {
1373             HILOG_DEBUG("get element info from cache");
1374             return RET_OK;
1375         }
1376     }
1377 
1378     return RET_ERR_FAILED;
1379 }
1380 
SearchElementInfoRecursive(int32_t windowId,int64_t elementId,uint32_t mode,std::vector<AccessibilityElementInfo> & elementInfos,bool isFilter)1381 RetError AccessibleAbilityClientImpl::SearchElementInfoRecursive(int32_t windowId, int64_t elementId, uint32_t mode,
1382     std::vector<AccessibilityElementInfo> &elementInfos, bool isFilter)
1383 {
1384     HILOG_INFO("windowId %{public}d}, elementId %{public}" PRId64 "", windowId, elementId);
1385     RetError ret = channelClient_->SearchElementInfosByAccessibilityId(windowId, elementId,
1386         mode, elementInfos, ROOT_TREE_ID, isFilter);
1387     if (ret != RET_OK) {
1388         HILOG_ERROR("search element info failed. windowId %{public}d elementId %{public}" PRId64 "",
1389             windowId, elementId);
1390         return ret;
1391     }
1392 
1393     if (elementInfos.empty()) {
1394         HILOG_ERROR("elementInfos from ace is empty");
1395         return RET_ERR_INVALID_ELEMENT_INFO_FROM_ACE;
1396     }
1397 
1398     return RET_OK;
1399 }
1400 
SearchElementInfoRecursiveByWinid(const int32_t windowId,const int64_t elementId,uint32_t mode,std::vector<AccessibilityElementInfo> & elementInfos,int32_t treeId,bool isFilter,AccessibilityElementInfo * parentInfo)1401 RetError AccessibleAbilityClientImpl::SearchElementInfoRecursiveByWinid(const int32_t windowId,
1402     const int64_t elementId, uint32_t mode, std::vector<AccessibilityElementInfo> &elementInfos,
1403     int32_t treeId, bool isFilter, AccessibilityElementInfo *parentInfo)
1404 {
1405     HILOG_DEBUG();
1406     if (windowId <= 0) {
1407         HILOG_ERROR("window Id is failed windowId %{public}d}", windowId);
1408         return RET_ERR_INVALID_ELEMENT_INFO_FROM_ACE;
1409     }
1410     HILOG_INFO("window Id is success windowId %{public}d}, elementId %{public}" PRId64 "", windowId, elementId);
1411     std::vector<AccessibilityElementInfo> vecElementInfos = {};
1412     RetError ret = channelClient_->SearchElementInfosByAccessibilityId(windowId, elementId,
1413         mode, vecElementInfos, treeId, isFilter);
1414     if (ret != RET_OK) {
1415         HILOG_ERROR("search element info failed. windowId %{public}d}", windowId);
1416         return ret;
1417     }
1418     if (vecElementInfos.empty()) {
1419         HILOG_ERROR("elementInfos from ace is empty");
1420         return RET_ERR_INVALID_ELEMENT_INFO_FROM_ACE;
1421     }
1422     HILOG_DEBUG("SearchElementInfoRecursiveByWinid : vecElementInfos Search ok");
1423     SortElementInfosIfNecessary(vecElementInfos);
1424     uint64_t elementInfosCountAdded = 0;
1425     uint64_t elementInfosCount = elementInfos.size();
1426     for (auto info : vecElementInfos) {
1427         if ((info.GetParentNodeId() == ROOT_PARENT_ELEMENT_ID) && (parentInfo != nullptr)) {
1428             parentInfo->AddChild(info.GetAccessibilityId());
1429             info.SetParent(parentInfo->GetAccessibilityId());
1430             HILOG_DEBUG("Give the father a child. %{public}" PRId64 ",Give the child a father.  %{public}" PRId64 "",
1431                 info.GetAccessibilityId(), parentInfo->GetAccessibilityId());
1432         }
1433         elementInfos.push_back(info);
1434         elementInfosCountAdded++;
1435     }
1436     for (uint64_t i = elementInfosCount; i < elementInfosCount + elementInfosCountAdded; i++) {
1437         HILOG_DEBUG("SearchElementInfoRecursiveByWinid :search element info success. windowId %{public}d}",
1438             elementInfos[i].GetChildWindowId());
1439         if ((elementInfos[i].GetChildWindowId() > 0) &&
1440             (elementInfos[i].GetChildWindowId() != elementInfos[i].GetWindowId())) {
1441             ret = SearchElementInfoRecursiveByWinid(elementInfos[i].GetChildWindowId(),
1442                 elementId, mode, elementInfos, elementInfos[i].GetChildTreeId(), isFilter, &elementInfos[i]);
1443             HILOG_DEBUG("ChildWindowId %{public}d}. ret:%{public}d", elementInfos[i].GetChildWindowId(), ret);
1444         } else if (elementInfos[i].GetChildTreeId() > 0) {
1445             ret = SearchElementInfoRecursiveByWinid(elementInfos[i].GetWindowId(),
1446                 elementId, mode, elementInfos, elementInfos[i].GetChildTreeId(), isFilter, &elementInfos[i]);
1447             HILOG_DEBUG("windowId %{public}d}.treeId:%{public}d. ret:%{public}d",
1448                 elementInfos[i].GetWindowId(), elementInfos[i].GetChildTreeId(), ret);
1449         }
1450     }
1451     return RET_OK;
1452 }
1453 
RemoveCacheData(const AccessibilityEventInfo & eventInfo)1454 void AccessibleAbilityClientImpl::RemoveCacheData(const AccessibilityEventInfo& eventInfo)
1455 {
1456     EventType type = eventInfo.GetEventType();
1457     if (type == TYPE_VIEW_TEXT_UPDATE_EVENT || type == TYPE_PAGE_STATE_UPDATE ||
1458         type == TYPE_NOTIFICATION_UPDATE_EVENT || type == TYPE_PAGE_CONTENT_UPDATE ||
1459         type == TYPE_VIEW_TEXT_SELECTION_UPDATE_EVENT || type == TYPE_WINDOW_UPDATE) {
1460         int32_t windowId = eventInfo.GetWindowId();
1461         HILOG_DEBUG("RemoveCacheData windowId %{public}d", windowId);
1462         if (windowId == SCENE_BOARD_WINDOW_ID) {
1463             elementCacheInfo_.RemoveElementByWindowId(windowId);
1464             windowElementMap_.RemovePairByWindowId(windowId);
1465 
1466             auto windowList = windowElementMap_.GetWindowIdList();
1467             windowElementMap_.RemovePairByWindowIdList(windowList);
1468             for (auto window: windowList) {
1469                 elementCacheInfo_.RemoveElementByWindowId(window);
1470             }
1471         } else {
1472             elementCacheInfo_.RemoveElementByWindowId(windowId);
1473             windowElementMap_.RemovePairByWindowId(windowId);
1474         }
1475     }
1476 }
1477 
AddCacheByWMS(int32_t windowId,int64_t elementId,std::vector<AccessibilityElementInfo> & elementInfos)1478 void AccessibleAbilityClientImpl::AddCacheByWMS(int32_t windowId, int64_t elementId,
1479     std::vector<AccessibilityElementInfo>& elementInfos)
1480 {
1481     HILOG_DEBUG("elementSize %{public}zu", elementInfos.size());
1482     AddWindowElementMapByWMS(windowId, elementId);
1483     elementCacheInfo_.AddElementCache(windowId, elementInfos);
1484 }
1485 
AddCacheByAce(int32_t windowId,int64_t elementId,std::vector<AccessibilityElementInfo> & elementInfos)1486 void AccessibleAbilityClientImpl::AddCacheByAce(int32_t windowId, int64_t elementId,
1487     std::vector<AccessibilityElementInfo>& elementInfos)
1488 {
1489     AddWindowElementMapByAce(windowId, elementId);
1490     HILOG_DEBUG("elementSize %{public}zu", elementInfos.size());
1491     if (windowId == SCENE_BOARD_WINDOW_ID) {
1492         windowId = windowElementMap_.GetWindowIdByElementId(elementId);
1493         HILOG_DEBUG("windowId convert to %{public}d", windowId);
1494         if (windowId == INVALID_SCENE_BOARD_INNER_WINDOW_ID) {
1495             elementCacheInfo_.AddElementCache(SCENE_BOARD_WINDOW_ID, elementInfos);
1496         } else {
1497             elementCacheInfo_.AddElementCache(windowId, elementInfos);
1498         }
1499     } else {
1500         elementCacheInfo_.AddElementCache(windowId, elementInfos);
1501     }
1502 }
1503 
SearchElementInfoByAccessibilityId(const int32_t windowId,const int64_t elementId,const uint32_t mode,AccessibilityElementInfo & info,bool isFilter)1504 RetError AccessibleAbilityClientImpl::SearchElementInfoByAccessibilityId(const int32_t windowId,
1505     const int64_t elementId, const uint32_t mode, AccessibilityElementInfo &info, bool isFilter)
1506 {
1507     HILOG_DEBUG();
1508     if (isConnected_ == false) {
1509         HILOG_ERROR("connection is broken.");
1510         return RET_ERR_NO_CONNECTION;
1511     }
1512 
1513     std::lock_guard<ffrt::mutex> lock(mutex_);
1514     if (CheckServiceProxy() == false) {
1515         HILOG_ERROR("failed to connect to aams.");
1516         return RET_ERR_SAMGR;
1517     }
1518     if (channelClient_ == nullptr) {
1519         HILOG_ERROR("the channel is invalid.");
1520         return RET_ERR_NO_CONNECTION;
1521     }
1522     std::vector<AccessibilityElementInfo> elementInfos {};
1523     int32_t treeId = 0;
1524     if (elementId > 0) {
1525         treeId = (static_cast<uint64_t>(elementId) >> ELEMENT_MOVE_BIT);
1526     }
1527     RetError ret = channelClient_->SearchElementInfosByAccessibilityId(windowId,
1528         elementId, static_cast<int32_t>(mode), elementInfos, treeId, isFilter);
1529     if (ret != RET_OK) {
1530         HILOG_ERROR("search element info failed, ret = %{public}d.", ret);
1531         return ret;
1532     }
1533     if (elementInfos.empty()) {
1534         HILOG_ERROR("elementInfos from ace is empty.");
1535         return RET_ERR_INVALID_ELEMENT_INFO_FROM_ACE;
1536     }
1537 
1538     SetCacheElementInfo(windowId, elementInfos);
1539     info = elementInfos.front();
1540     info.SetMainWindowId(windowId);
1541     return RET_OK;
1542 }
1543 
AddElementCache(const int32_t windowId,const std::vector<AccessibilityElementInfo> & elementInfos)1544 void AccessibleAbilityClientImpl::ElementCacheInfo::AddElementCache(const int32_t windowId,
1545     const std::vector<AccessibilityElementInfo>& elementInfos)
1546 {
1547     std::lock_guard<ffrt::mutex> lock(elementCacheMutex_);
1548     if (windowIdSet_.size() >= MAX_CACHE_WINDOW_SIZE) {
1549         auto winId = windowIdSet_.front();
1550         windowIdSet_.pop_front();
1551         elementCache_.erase(winId);
1552     }
1553 
1554     elementCache_.erase(windowId);
1555 
1556     std::map<int32_t, std::shared_ptr<AccessibilityElementInfo>> cache;
1557     for (auto& elementInfo : elementInfos) {
1558         int64_t elementId = elementInfo.GetAccessibilityId();
1559         cache[elementId] = std::make_shared<AccessibilityElementInfo>(elementInfo);
1560     }
1561 
1562     elementCache_[windowId] = std::move(cache);
1563     windowIdSet_.push_back(windowId);
1564 }
1565 
GetElementByWindowIdBFS(const int64_t realElementId,std::vector<AccessibilityElementInfo> & elementInfos,std::map<int32_t,std::shared_ptr<AccessibilityElementInfo>> & cache)1566 bool AccessibleAbilityClientImpl::ElementCacheInfo::GetElementByWindowIdBFS(const int64_t realElementId,
1567     std::vector<AccessibilityElementInfo>& elementInfos,
1568     std::map<int32_t, std::shared_ptr<AccessibilityElementInfo>>& cache)
1569 {
1570     std::vector<int64_t> elementList;
1571     elementList.push_back(realElementId);
1572     uint32_t index = 0;
1573     while (index < elementList.size()) {
1574         auto iter = cache.find(elementList[index]);
1575         if (iter == cache.end()) {
1576             elementInfos.clear();
1577             HILOG_DEBUG("element data abnormal, clear elementInfos");
1578             return false;
1579         }
1580 
1581         elementInfos.push_back(*(iter->second));
1582         std::vector<int64_t> childrenNode = iter->second->GetChildIds();
1583         for (auto& node : childrenNode) {
1584             elementList.push_back(node);
1585         }
1586         index++;
1587     }
1588     return true;
1589 }
1590 
1591 // window id is true, element id is true
GetElementByWindowId(const int32_t windowId,const int64_t elementId,std::vector<AccessibilityElementInfo> & elementInfos)1592 bool AccessibleAbilityClientImpl::ElementCacheInfo::GetElementByWindowId(const int32_t windowId,
1593     const int64_t elementId, std::vector<AccessibilityElementInfo>& elementInfos)
1594 {
1595     elementInfos.clear(); // clear
1596     std::lock_guard<ffrt::mutex> lock(elementCacheMutex_);
1597     if (elementCache_.find(windowId) == elementCache_.end()) {
1598         HILOG_DEBUG("windowId %{public}d is not existed", windowId);
1599         return false;
1600     }
1601 
1602     auto& cache = elementCache_.find(windowId)->second;
1603     if (cache.size() == 0) {
1604         HILOG_DEBUG("windowId %{public}d element is null", windowId);
1605         return false;
1606     }
1607 
1608     if (cache.find(elementId) == cache.end() && elementId != ROOT_NONE_ID) {
1609         HILOG_DEBUG("elementId %{public}" PRId64 " is not existed", elementId);
1610         return false;
1611     }
1612 
1613     int64_t realElementId = elementId;
1614     if (realElementId == ROOT_NONE_ID) {
1615         for (auto iter = cache.begin(); iter != cache.end(); iter++) {
1616             if (iter->second->GetComponentType() == "root") {
1617                 realElementId = iter->first;
1618                 HILOG_DEBUG("find realElementId %{public}" PRId64 "", realElementId);
1619                 break;
1620             }
1621         }
1622     }
1623 
1624     if (realElementId == ROOT_NONE_ID) {
1625         HILOG_ERROR("elementId %{public}" PRId64 " is not existed", realElementId);
1626         return false;
1627     }
1628 
1629     if (!GetElementByWindowIdBFS(realElementId, elementInfos, cache)) {
1630         HILOG_DEBUG("get window element fail");
1631         return false;
1632     }
1633 
1634     HILOG_DEBUG("get element info success, element size %{public}zu", elementInfos.size());
1635     return true;
1636 }
1637 
RemoveElementByWindowId(const int32_t windowId)1638 void AccessibleAbilityClientImpl::ElementCacheInfo::RemoveElementByWindowId(const int32_t windowId)
1639 {
1640     std::lock_guard<ffrt::mutex> lock(elementCacheMutex_);
1641     HILOG_DEBUG("erase windowId %{public}d cache", windowId);
1642     for (auto iter = windowIdSet_.begin(); iter != windowIdSet_.end(); iter++) {
1643         if (*iter == windowId) {
1644             windowIdSet_.erase(iter);
1645             break;
1646         }
1647     }
1648 
1649     elementCache_.erase(windowId);
1650 }
1651 
IsExistWindowId(int32_t windowId)1652 bool AccessibleAbilityClientImpl::ElementCacheInfo::IsExistWindowId(int32_t windowId)
1653 {
1654     std::lock_guard<ffrt::mutex> lock(elementCacheMutex_);
1655     for (auto iter = windowIdSet_.begin(); iter != windowIdSet_.end(); iter++) {
1656         if (*iter == windowId) {
1657             return true;
1658         }
1659     }
1660 
1661     return false;
1662 }
1663 
IsExistWindowId(int32_t windowId)1664 bool AccessibleAbilityClientImpl::SceneBoardWindowElementMap::IsExistWindowId(int32_t windowId)
1665 {
1666     std::lock_guard<ffrt::mutex> lock(mapMutex_);
1667     if (windowElementMap_.find(windowId) != windowElementMap_.end()) {
1668         return true;
1669     }
1670 
1671     return false;
1672 }
1673 
AddWindowElementIdPair(int32_t windowId,int64_t elementId)1674 void AccessibleAbilityClientImpl::SceneBoardWindowElementMap::AddWindowElementIdPair(int32_t windowId,
1675     int64_t elementId)
1676 {
1677     std::lock_guard<ffrt::mutex> lock(mapMutex_);
1678     windowElementMap_[windowId] = elementId;
1679 }
1680 
GetWindowIdList()1681 std::vector<int32_t> AccessibleAbilityClientImpl::SceneBoardWindowElementMap::GetWindowIdList()
1682 {
1683     std::lock_guard<ffrt::mutex> lock(mapMutex_);
1684     std::vector<int32_t> windowList;
1685     for (auto iter = windowElementMap_.begin(); iter != windowElementMap_.end(); iter++) {
1686         windowList.push_back(iter->first);
1687     }
1688 
1689     return windowList;
1690 }
1691 
GetWindowIdByElementId(int64_t elementId)1692 int32_t AccessibleAbilityClientImpl::SceneBoardWindowElementMap::GetWindowIdByElementId(int64_t elementId)
1693 {
1694     std::lock_guard<ffrt::mutex> lock(mapMutex_);
1695     for (auto iter = windowElementMap_.begin(); iter != windowElementMap_.end(); iter++) {
1696         if (iter->second == elementId) {
1697             return iter->first;
1698         }
1699     }
1700 
1701     return INVALID_SCENE_BOARD_INNER_WINDOW_ID;
1702 }
1703 
RemovePairByWindowIdList(std::vector<int32_t> & windowIdList)1704 void AccessibleAbilityClientImpl::SceneBoardWindowElementMap::RemovePairByWindowIdList(
1705     std::vector<int32_t>& windowIdList)
1706 {
1707     std::lock_guard<ffrt::mutex> lock(mapMutex_);
1708     for (auto windowId : windowIdList) {
1709         windowElementMap_.erase(windowId);
1710     }
1711 }
1712 
RemovePairByWindowId(int32_t windowId)1713 void AccessibleAbilityClientImpl::SceneBoardWindowElementMap::RemovePairByWindowId(int32_t windowId)
1714 {
1715     std::lock_guard<ffrt::mutex> lock(mapMutex_);
1716     windowElementMap_.erase(windowId);
1717 }
1718 
OnLoadSystemAbilitySuccess(int32_t systemAbilityId,const sptr<IRemoteObject> & remoteObject)1719 void AccessibleAbilityClientImpl::AccessibilityLoadCallback::OnLoadSystemAbilitySuccess(int32_t systemAbilityId,
1720     const sptr<IRemoteObject> &remoteObject)
1721 {
1722     if (AccessibleAbilityClientImpl::GetAbilityClientImplement()) {
1723         AccessibleAbilityClientImpl::GetAbilityClientImplement()->LoadSystemAbilitySuccess(remoteObject);
1724     }
1725 }
1726 
OnLoadSystemAbilityFail(int32_t systemAbilityId)1727 void AccessibleAbilityClientImpl::AccessibilityLoadCallback::OnLoadSystemAbilityFail(int32_t systemAbilityId)
1728 {
1729     if (AccessibleAbilityClientImpl::GetAbilityClientImplement()) {
1730         AccessibleAbilityClientImpl::GetAbilityClientImplement()->LoadSystemAbilityFail();
1731     }
1732 }
1733 } // namespace Accessibility
1734 } // namespace OHOS