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