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