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