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