1 /*
2 * Copyright (C) 2022-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "accessible_ability_client_impl.h"
17
18 #include <chrono>
19 #include <cinttypes>
20 #include <thread>
21
22 #include "accessible_ability_client.h"
23 #include "hilog_wrapper.h"
24 #include "if_system_ability_manager.h"
25 #include "iservice_registry.h"
26 #include "parameter.h"
27 #include "system_ability_definition.h"
28
29 namespace OHOS {
30 namespace Accessibility {
31 // tmp: wait for window registing when client connect done
32 constexpr int WAIT_WINDOW_REGIST = 500;
33 namespace {
34 const std::string SYSTEM_PARAMETER_AAMS_NAME = "accessibility.config.ready";
35 constexpr int32_t CONFIG_PARAMETER_VALUE_SIZE = 10;
36 constexpr int32_t ROOT_NONE_ID = -1;
37 std::mutex g_Mutex;
38 sptr<AccessibleAbilityClientImpl> g_Instance = nullptr;
39 } // namespace
40
GetInstance()41 sptr<AccessibleAbilityClient> AccessibleAbilityClient::GetInstance()
42 {
43 HILOG_DEBUG();
44 std::lock_guard<std::mutex> lock(g_Mutex);
45 if (!g_Instance) {
46 g_Instance = new(std::nothrow) AccessibleAbilityClientImpl();
47 }
48 return g_Instance;
49 }
50
GetAbilityClientImplement()51 sptr<AccessibleAbilityClientImpl> AccessibleAbilityClientImpl::GetAbilityClientImplement()
52 {
53 HILOG_DEBUG();
54 std::lock_guard<std::mutex> lock(g_Mutex);
55 if (!g_Instance) {
56 g_Instance = new(std::nothrow) AccessibleAbilityClientImpl();
57 }
58 return g_Instance;
59 }
60
AccessibleAbilityClientImpl()61 AccessibleAbilityClientImpl::AccessibleAbilityClientImpl()
62 {
63 HILOG_DEBUG();
64 char value[CONFIG_PARAMETER_VALUE_SIZE] = "default";
65 int retSysParam = GetParameter(SYSTEM_PARAMETER_AAMS_NAME.c_str(), "false", value, CONFIG_PARAMETER_VALUE_SIZE);
66 if (retSysParam >= 0 && !std::strcmp(value, "true")) {
67 // Accessibility service is ready
68 if (!InitAccessibilityServiceProxy()) {
69 HILOG_ERROR("Init accessibility service proxy failed");
70 }
71 }
72
73 HILOG_DEBUG("Start watching accessibility service.");
74 retSysParam = WatchParameter(SYSTEM_PARAMETER_AAMS_NAME.c_str(),
75 &AccessibleAbilityClientImpl::OnParameterChanged, this);
76 if (retSysParam) {
77 HILOG_ERROR("Watch parameter failed, error = %{public}d", retSysParam);
78 }
79 }
80
~AccessibleAbilityClientImpl()81 AccessibleAbilityClientImpl::~AccessibleAbilityClientImpl()
82 {
83 HILOG_DEBUG();
84 std::lock_guard<std::mutex> lock(mutex_);
85 if (serviceProxy_ && serviceProxy_->AsObject()) {
86 HILOG_DEBUG("Remove service death recipient");
87 serviceProxy_->AsObject()->RemoveDeathRecipient(accessibilityServiceDeathRecipient_);
88 }
89 }
90
InitAccessibilityServiceProxy()91 bool AccessibleAbilityClientImpl::InitAccessibilityServiceProxy()
92 {
93 if (serviceProxy_) {
94 HILOG_DEBUG("Accessibility Service is connected");
95 return true;
96 }
97
98 sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
99 if (!samgr) {
100 HILOG_ERROR("Failed to get ISystemAbilityManager");
101 return false;
102 }
103 HILOG_DEBUG("ISystemAbilityManager obtained");
104
105 sptr<IRemoteObject> object = samgr->GetSystemAbility(ACCESSIBILITY_MANAGER_SERVICE_ID);
106 if (!object) {
107 HILOG_ERROR("Get IAccessibleAbilityManagerService object from samgr failed");
108 return false;
109 }
110 HILOG_DEBUG("Get remote object ok");
111
112 serviceProxy_ = iface_cast<IAccessibleAbilityManagerService>(object);
113 if (!serviceProxy_) {
114 HILOG_ERROR("Get aams proxy failed");
115 return false;
116 }
117
118 // Add death recipient
119 if (!accessibilityServiceDeathRecipient_) {
120 accessibilityServiceDeathRecipient_ = new(std::nothrow) AccessibilityServiceDeathRecipient(*this);
121 if (!accessibilityServiceDeathRecipient_) {
122 HILOG_ERROR("Failed to create service deathRecipient.");
123 return false;
124 }
125 }
126
127 if (serviceProxy_->AsObject()) {
128 HILOG_DEBUG("Add death recipient");
129 serviceProxy_->AsObject()->AddDeathRecipient(accessibilityServiceDeathRecipient_);
130 }
131 return true;
132 }
133
OnParameterChanged(const char * key,const char * value,void * context)134 void AccessibleAbilityClientImpl::OnParameterChanged(const char *key, const char *value, void *context)
135 {
136 HILOG_DEBUG("Parameter key = [%{public}s] value = [%{public}s]", key, value);
137
138 if (!key || std::strcmp(key, SYSTEM_PARAMETER_AAMS_NAME.c_str())) {
139 HILOG_WARN("not accessibility.config.ready callback");
140 return;
141 }
142
143 if (!value || std::strcmp(value, "true")) {
144 HILOG_WARN("accessibility.config.ready value not true");
145 return;
146 }
147
148 if (!context) {
149 HILOG_ERROR("accessibility.config.ready context NULL");
150 return;
151 }
152
153 AccessibleAbilityClientImpl* implPtr = static_cast<AccessibleAbilityClientImpl*>(context);
154 {
155 HILOG_DEBUG("ConnectToService start.");
156 std::lock_guard<std::mutex> lock(implPtr->mutex_);
157 if (implPtr->InitAccessibilityServiceProxy()) {
158 HILOG_DEBUG("ConnectToService Success");
159 }
160 }
161 }
162
GetRemoteObject()163 sptr<IRemoteObject> AccessibleAbilityClientImpl::GetRemoteObject()
164 {
165 HILOG_INFO();
166 return this->AsObject();
167 }
168
RegisterAbilityListener(const std::shared_ptr<AccessibleAbilityListener> & listener)169 RetError AccessibleAbilityClientImpl::RegisterAbilityListener(
170 const std::shared_ptr<AccessibleAbilityListener> &listener)
171 {
172 HILOG_INFO();
173 std::lock_guard<std::mutex> lock(mutex_);
174 if (listener_) {
175 HILOG_DEBUG("listener already exists.");
176 return RET_ERR_REGISTER_EXIST;
177 }
178
179 listener_ = listener;
180 return RET_OK;
181 }
182
Init(const sptr<IAccessibleAbilityChannel> & channel,const int32_t channelId)183 void AccessibleAbilityClientImpl::Init(const sptr<IAccessibleAbilityChannel> &channel, const int32_t channelId)
184 {
185 HILOG_INFO("channelId[%{public}d]", channelId);
186 if (!channel || channelId == INVALID_CHANNEL_ID) {
187 HILOG_ERROR("channel is nullptr, or channelId is invalid");
188 return;
189 }
190
191 std::shared_ptr<AccessibleAbilityListener> listener = nullptr;
192 {
193 std::lock_guard<std::mutex> lock(mutex_);
194 if (!listener_) {
195 HILOG_ERROR("listener_ is nullptr.");
196 return;
197 }
198 listener = listener_;
199 channelClient_ = std::make_shared<AccessibleAbilityChannelClient>(channelId, channel);
200
201 // Add death recipient
202 if (!deathRecipient_) {
203 deathRecipient_ = new(std::nothrow) AccessibleAbilityDeathRecipient(*this);
204 if (!deathRecipient_) {
205 HILOG_ERROR("Failed to create deathRecipient.");
206 return;
207 }
208 }
209
210 if (channel->AsObject()) {
211 HILOG_DEBUG("Add death recipient");
212 channel->AsObject()->AddDeathRecipient(deathRecipient_);
213 }
214 }
215
216 isConnected_ = true;
217 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_WINDOW_REGIST));
218 if (listener) {
219 listener->OnAbilityConnected();
220 }
221 }
222
Disconnect(const int32_t channelId)223 void AccessibleAbilityClientImpl::Disconnect(const int32_t channelId)
224 {
225 HILOG_INFO("channelId[%{public}d]", channelId);
226
227 std::shared_ptr<AccessibleAbilityListener> listener = nullptr;
228 {
229 isConnected_ = false;
230 std::lock_guard<std::mutex> lock(mutex_);
231 // Delete death recipient
232 if (channelClient_ && channelClient_->GetRemote()) {
233 HILOG_ERROR("Remove death recipient");
234 channelClient_->GetRemote()->RemoveDeathRecipient(deathRecipient_);
235 }
236
237 // Remove channel
238 channelClient_ = nullptr;
239 listener = listener_;
240 listener_ = nullptr;
241 }
242
243 if (listener) {
244 listener->OnAbilityDisconnected();
245 }
246 }
247
OnAccessibilityEvent(const AccessibilityEventInfo & eventInfo)248 void AccessibleAbilityClientImpl::OnAccessibilityEvent(const AccessibilityEventInfo &eventInfo)
249 {
250 HILOG_INFO();
251 std::shared_ptr<AccessibleAbilityListener> listener = nullptr;
252 {
253 std::lock_guard<std::mutex> lock(mutex_);
254 if (!channelClient_) {
255 HILOG_ERROR("The channel is invalid.");
256 return;
257 }
258 listener = listener_;
259 }
260 if (listener) {
261 listener->OnAccessibilityEvent(eventInfo);
262 }
263 }
264
OnKeyPressEvent(const MMI::KeyEvent & keyEvent,const int32_t sequence)265 void AccessibleAbilityClientImpl::OnKeyPressEvent(const MMI::KeyEvent &keyEvent, const int32_t sequence)
266 {
267 HILOG_INFO("sequence[%{public}d]", sequence);
268 std::shared_ptr<AccessibleAbilityListener> listener = nullptr;
269 std::shared_ptr<AccessibleAbilityChannelClient> channel = nullptr;
270 {
271 std::lock_guard<std::mutex> lock(mutex_);
272 listener = listener_;
273 channel = channelClient_;
274 }
275
276 if (!channel) {
277 HILOG_ERROR("The channel is invalid.");
278 return;
279 }
280 bool handled = false;
281 if (listener) {
282 std::shared_ptr<MMI::KeyEvent> tmp = std::make_shared<MMI::KeyEvent>(keyEvent);
283 handled = listener->OnKeyPressEvent(tmp);
284 }
285 channel->SetOnKeyPressEventResult(handled, sequence);
286 }
287
GetFocus(const int32_t focusType,AccessibilityElementInfo & elementInfo)288 RetError AccessibleAbilityClientImpl::GetFocus(const int32_t focusType, AccessibilityElementInfo &elementInfo)
289 {
290 HILOG_INFO("focusType[%{public}d]", focusType);
291 if (!isConnected_) {
292 HILOG_ERROR("connection is broken");
293 return RET_ERR_NO_CONNECTION;
294 }
295
296 std::lock_guard<std::mutex> lock(mutex_);
297 if ((focusType != FOCUS_TYPE_INPUT) && (focusType != FOCUS_TYPE_ACCESSIBILITY)) {
298 HILOG_ERROR("focusType is not allowed.");
299 return RET_ERR_INVALID_PARAM;
300 }
301
302 if (!channelClient_) {
303 HILOG_ERROR("The channel is invalid.");
304 return RET_ERR_NO_CONNECTION;
305 }
306
307 return channelClient_->FindFocusedElementInfo(ANY_WINDOW_ID, ROOT_NODE_ID, focusType, elementInfo);
308 }
309
GetFocusByElementInfo(const AccessibilityElementInfo & sourceInfo,const int32_t focusType,AccessibilityElementInfo & elementInfo)310 RetError AccessibleAbilityClientImpl::GetFocusByElementInfo(const AccessibilityElementInfo &sourceInfo,
311 const int32_t focusType, AccessibilityElementInfo &elementInfo)
312 {
313 HILOG_INFO("focusType[%{public}d]", focusType);
314 if (!isConnected_) {
315 HILOG_ERROR("connection is broken");
316 return RET_ERR_NO_CONNECTION;
317 }
318
319 std::lock_guard<std::mutex> lock(mutex_);
320 if ((focusType != FOCUS_TYPE_INPUT) && (focusType != FOCUS_TYPE_ACCESSIBILITY)) {
321 HILOG_ERROR("focusType is not allowed.");
322 return RET_ERR_INVALID_PARAM;
323 }
324
325 if (!channelClient_) {
326 HILOG_ERROR("The channel is invalid.");
327 return RET_ERR_NO_CONNECTION;
328 }
329
330 int32_t windowId = sourceInfo.GetWindowId();
331 int32_t elementId = sourceInfo.GetAccessibilityId();
332 HILOG_INFO("windowId[%{public}d], elementId[%{public}d], focusType[%{public}d]", windowId, elementId, focusType);
333
334 return channelClient_->FindFocusedElementInfo(windowId, elementId, focusType, elementInfo);
335 }
336
InjectGesture(const std::shared_ptr<AccessibilityGestureInjectPath> & gesturePath)337 RetError AccessibleAbilityClientImpl::InjectGesture(const std::shared_ptr<AccessibilityGestureInjectPath> &gesturePath)
338 {
339 HILOG_INFO();
340 if (!isConnected_) {
341 HILOG_ERROR("connection is broken");
342 return RET_ERR_NO_CONNECTION;
343 }
344
345 std::lock_guard<std::mutex> lock(mutex_);
346 if (!gesturePath) {
347 HILOG_ERROR("The gesturePath is null.");
348 return RET_ERR_INVALID_PARAM;
349 }
350
351 std::vector<AccessibilityGesturePosition> positions = gesturePath->GetPositions();
352
353 if (positions.size() == 0) {
354 HILOG_ERROR("The number of gesture path position is not allowed.");
355 return RET_ERR_INVALID_PARAM;
356 }
357
358 if (!channelClient_) {
359 HILOG_ERROR("The channel is invalid.");
360 return RET_ERR_NO_CONNECTION;
361 }
362
363 return channelClient_->SendSimulateGesture(gesturePath);
364 }
365
GetRoot(AccessibilityElementInfo & elementInfo)366 RetError AccessibleAbilityClientImpl::GetRoot(AccessibilityElementInfo &elementInfo)
367 {
368 HILOG_DEBUG();
369 if (!isConnected_) {
370 HILOG_ERROR("connection is broken");
371 return RET_ERR_NO_CONNECTION;
372 }
373
374 std::lock_guard<std::mutex> lock(mutex_);
375 if (!serviceProxy_) {
376 HILOG_ERROR("Failed to connect to aams");
377 return RET_ERR_SAMGR;
378 }
379
380 if (!channelClient_) {
381 HILOG_ERROR("The channel is invalid.");
382 return RET_ERR_NO_CONNECTION;
383 }
384
385 int32_t activeWindow = serviceProxy_->GetActiveWindow();
386 HILOG_INFO("activeWindow[%{public}d]", activeWindow);
387 if (GetCacheElementInfo(activeWindow, ROOT_NONE_ID, elementInfo)) {
388 HILOG_DEBUG("get element info from cache");
389 return RET_OK;
390 }
391
392 return SearchElementInfoFromAce(activeWindow, ROOT_NONE_ID, cacheMode_, elementInfo);
393 }
394
GetRootByWindow(const AccessibilityWindowInfo & windowInfo,AccessibilityElementInfo & elementInfo)395 RetError AccessibleAbilityClientImpl::GetRootByWindow(const AccessibilityWindowInfo &windowInfo,
396 AccessibilityElementInfo &elementInfo)
397 {
398 HILOG_DEBUG();
399 if (!isConnected_) {
400 HILOG_ERROR("connection is broken");
401 return RET_ERR_NO_CONNECTION;
402 }
403
404 std::lock_guard<std::mutex> lock(mutex_);
405 if (!channelClient_) {
406 HILOG_ERROR("The channel is invalid.");
407 return RET_ERR_NO_CONNECTION;
408 }
409
410 int32_t windowId = windowInfo.GetWindowId();
411 HILOG_INFO("windowId[%{public}d]", windowId);
412 if (GetCacheElementInfo(windowId, ROOT_NONE_ID, elementInfo)) {
413 HILOG_DEBUG("get element info from cache");
414 return RET_OK;
415 }
416
417 return SearchElementInfoFromAce(windowId, ROOT_NONE_ID, cacheMode_, elementInfo);
418 }
419
GetWindow(const int32_t windowId,AccessibilityWindowInfo & windowInfo)420 RetError AccessibleAbilityClientImpl::GetWindow(const int32_t windowId, AccessibilityWindowInfo &windowInfo)
421 {
422 HILOG_INFO("windowId[%{public}d]", windowId);
423 if (!isConnected_) {
424 HILOG_ERROR("connection is broken");
425 return RET_ERR_NO_CONNECTION;
426 }
427
428 std::lock_guard<std::mutex> lock(mutex_);
429 if (!channelClient_) {
430 HILOG_ERROR("The channel is invalid.");
431 return RET_ERR_NO_CONNECTION;
432 }
433 return channelClient_->GetWindow(windowId, windowInfo);
434 }
435
GetWindows(std::vector<AccessibilityWindowInfo> & windows)436 RetError AccessibleAbilityClientImpl::GetWindows(std::vector<AccessibilityWindowInfo> &windows)
437 {
438 HILOG_INFO();
439 if (!isConnected_) {
440 HILOG_ERROR("connection is broken");
441 return RET_ERR_NO_CONNECTION;
442 }
443
444 std::lock_guard<std::mutex> lock(mutex_);
445 if (!channelClient_) {
446 HILOG_ERROR("The channel is invalid.");
447 return RET_ERR_NO_CONNECTION;
448 }
449 return channelClient_->GetWindows(windows);
450 }
451
GetWindows(const uint64_t displayId,std::vector<AccessibilityWindowInfo> & windows)452 RetError AccessibleAbilityClientImpl::GetWindows(const uint64_t displayId,
453 std::vector<AccessibilityWindowInfo> &windows)
454 {
455 HILOG_INFO("displayId[%{public}" PRIu64 "]", displayId);
456 if (!isConnected_) {
457 HILOG_ERROR("connection is broken");
458 return RET_ERR_NO_CONNECTION;
459 }
460
461 std::lock_guard<std::mutex> lock(mutex_);
462 if (!channelClient_) {
463 HILOG_ERROR("The channel is invalid.");
464 return RET_ERR_NO_CONNECTION;
465 }
466 return channelClient_->GetWindows(displayId, windows);
467 }
468
GetNext(const AccessibilityElementInfo & elementInfo,const FocusMoveDirection direction,AccessibilityElementInfo & nextElementInfo)469 RetError AccessibleAbilityClientImpl::GetNext(const AccessibilityElementInfo &elementInfo,
470 const FocusMoveDirection direction, AccessibilityElementInfo &nextElementInfo)
471 {
472 HILOG_INFO("windowId[%{public}d], elementId[%{public}d], direction[%{public}d]",
473 elementInfo.GetWindowId(), elementInfo.GetAccessibilityId(), direction);
474 if (!isConnected_) {
475 HILOG_ERROR("connection is broken");
476 return RET_ERR_NO_CONNECTION;
477 }
478
479 std::lock_guard<std::mutex> lock(mutex_);
480 if (!channelClient_) {
481 HILOG_ERROR("The channel is invalid.");
482 return RET_ERR_NO_CONNECTION;
483 }
484 if (direction == DIRECTION_INVALID) {
485 HILOG_ERROR("direction is invalid.");
486 return RET_ERR_INVALID_PARAM;
487 }
488 return channelClient_->FocusMoveSearch(elementInfo.GetWindowId(),
489 elementInfo.GetAccessibilityId(), direction, nextElementInfo);
490 }
491
GetChildElementInfo(const int32_t index,const AccessibilityElementInfo & parent,AccessibilityElementInfo & child)492 RetError AccessibleAbilityClientImpl::GetChildElementInfo(const int32_t index, const AccessibilityElementInfo &parent,
493 AccessibilityElementInfo &child)
494 {
495 HILOG_DEBUG();
496 if (!isConnected_) {
497 HILOG_ERROR("connection is broken");
498 return RET_ERR_NO_CONNECTION;
499 }
500
501 std::lock_guard<std::mutex> lock(mutex_);
502 if (!channelClient_) {
503 HILOG_ERROR("The channel is invalid.");
504 return RET_ERR_NO_CONNECTION;
505 }
506
507 int32_t windowId = parent.GetWindowId();
508 int32_t childId = parent.GetChildId(index);
509 HILOG_DEBUG("windowId[%{public}d], childId[%{public}d]", windowId, childId);
510 if (childId == -1) {
511 HILOG_ERROR("childId[%{public}d] is invalid", childId);
512 return RET_ERR_INVALID_PARAM;
513 }
514 if (GetCacheElementInfo(windowId, childId, child)) {
515 HILOG_DEBUG("get element info from cache");
516 return RET_OK;
517 }
518
519 return SearchElementInfoFromAce(windowId, childId, cacheMode_, child);
520 }
521
GetChildren(const AccessibilityElementInfo & parent,std::vector<AccessibilityElementInfo> & children)522 RetError AccessibleAbilityClientImpl::GetChildren(const AccessibilityElementInfo &parent,
523 std::vector<AccessibilityElementInfo> &children)
524 {
525 HILOG_DEBUG();
526 if (!isConnected_) {
527 HILOG_ERROR("connection is broken");
528 return RET_ERR_NO_CONNECTION;
529 }
530
531 std::lock_guard<std::mutex> lock(mutex_);
532 if (!channelClient_) {
533 HILOG_ERROR("The channel is invalid.");
534 return RET_ERR_NO_CONNECTION;
535 }
536
537 int32_t windowId = parent.GetWindowId();
538 std::vector<int32_t> childIds = parent.GetChildIds();
539 HILOG_INFO("windowId[%{public}d], childIds.size[%{public}zu]", windowId, childIds.size());
540 for (auto &childId : childIds) {
541 HILOG_DEBUG("childId[%{public}d]", childId);
542 if (childId == -1) {
543 HILOG_ERROR("childId is invalid");
544 return RET_ERR_INVALID_PARAM;
545 }
546
547 AccessibilityElementInfo child;
548 if (GetCacheElementInfo(windowId, childId, child)) {
549 HILOG_DEBUG("get element info from cache");
550 children.emplace_back(child);
551 continue;
552 }
553
554 RetError ret = SearchElementInfoFromAce(windowId, childId, cacheMode_, child);
555 if (ret != RET_OK) {
556 HILOG_ERROR("Get element info from ace failed");
557 return ret;
558 }
559 children.emplace_back(child);
560 }
561 return RET_OK;
562 }
563
GetByContent(const AccessibilityElementInfo & elementInfo,const std::string & text,std::vector<AccessibilityElementInfo> & elementInfos)564 RetError AccessibleAbilityClientImpl::GetByContent(const AccessibilityElementInfo &elementInfo,
565 const std::string &text, std::vector<AccessibilityElementInfo> &elementInfos)
566 {
567 HILOG_DEBUG();
568 if (!isConnected_) {
569 HILOG_ERROR("connection is broken");
570 return RET_ERR_NO_CONNECTION;
571 }
572
573 std::lock_guard<std::mutex> lock(mutex_);
574 if (!channelClient_) {
575 HILOG_ERROR("The channel is invalid.");
576 return RET_ERR_NO_CONNECTION;
577 }
578 int32_t windowId = elementInfo.GetWindowId();
579 int32_t elementId = elementInfo.GetAccessibilityId();
580 HILOG_INFO("windowId[%{public}d], elementId[%{public}d], text[%{public}s]", windowId, elementId, text.c_str());
581 return channelClient_->SearchElementInfosByText(windowId, elementId, text, elementInfos);
582 }
583
GetSource(const AccessibilityEventInfo & eventInfo,AccessibilityElementInfo & elementInfo)584 RetError AccessibleAbilityClientImpl::GetSource(const AccessibilityEventInfo &eventInfo,
585 AccessibilityElementInfo &elementInfo)
586 {
587 HILOG_DEBUG();
588 if (!isConnected_) {
589 HILOG_ERROR("connection is broken");
590 return RET_ERR_NO_CONNECTION;
591 }
592
593 std::lock_guard<std::mutex> lock(mutex_);
594 if (!channelClient_) {
595 HILOG_ERROR("The channel is invalid.");
596 return RET_ERR_NO_CONNECTION;
597 }
598 int32_t windowId = eventInfo.GetWindowId();
599 int32_t elementId = eventInfo.GetAccessibilityId();
600 HILOG_INFO("windowId[%{public}d], elementId[%{public}d]", windowId, elementId);
601 if (GetCacheElementInfo(windowId, elementId, elementInfo)) {
602 HILOG_DEBUG("get element info from cache");
603 return RET_OK;
604 }
605 return SearchElementInfoFromAce(windowId, elementId, cacheMode_, elementInfo);
606 }
607
GetParentElementInfo(const AccessibilityElementInfo & child,AccessibilityElementInfo & parent)608 RetError AccessibleAbilityClientImpl::GetParentElementInfo(const AccessibilityElementInfo &child,
609 AccessibilityElementInfo &parent)
610 {
611 HILOG_DEBUG();
612 if (!isConnected_) {
613 HILOG_ERROR("connection is broken");
614 return RET_ERR_NO_CONNECTION;
615 }
616
617 std::lock_guard<std::mutex> lock(mutex_);
618 if (!channelClient_) {
619 HILOG_ERROR("The channel is invalid.");
620 return RET_ERR_NO_CONNECTION;
621 }
622 int32_t windowId = child.GetWindowId();
623 int32_t elementId = child.GetParentNodeId();
624 HILOG_INFO("windowId[%{public}d], parentId[%{public}d]", windowId, elementId);
625 if (GetCacheElementInfo(windowId, elementId, parent)) {
626 HILOG_DEBUG("get element info from cache");
627 return RET_OK;
628 }
629
630 return SearchElementInfoFromAce(windowId, elementId, cacheMode_, parent);
631 }
632
ExecuteAction(const AccessibilityElementInfo & elementInfo,const ActionType action,const std::map<std::string,std::string> & actionArguments)633 RetError AccessibleAbilityClientImpl::ExecuteAction(const AccessibilityElementInfo &elementInfo,
634 const ActionType action, const std::map<std::string, std::string> &actionArguments)
635 {
636 HILOG_DEBUG();
637 if (!isConnected_) {
638 HILOG_ERROR("connection is broken");
639 return RET_ERR_NO_CONNECTION;
640 }
641
642 std::lock_guard<std::mutex> lock(mutex_);
643 if (!channelClient_) {
644 HILOG_ERROR("The channel is invalid.");
645 return RET_ERR_NO_CONNECTION;
646 }
647 if (action == ACCESSIBILITY_ACTION_INVALID) {
648 HILOG_ERROR("action is invalid.");
649 return RET_ERR_INVALID_PARAM;
650 }
651 int32_t windowId = elementInfo.GetWindowId();
652 int32_t elementId = elementInfo.GetAccessibilityId();
653 HILOG_INFO("windowId[%{public}d], elementId[%{public}d], action[%{public}d", windowId, elementId, action);
654 return channelClient_->ExecuteAction(windowId, elementId, action,
655 const_cast<std::map<std::string, std::string> &>(actionArguments));
656 }
657
SetTargetBundleName(const std::vector<std::string> & targetBundleNames)658 RetError AccessibleAbilityClientImpl::SetTargetBundleName(const std::vector<std::string> &targetBundleNames)
659 {
660 HILOG_INFO("targetBundleNames size[%{public}zu]", targetBundleNames.size());
661 if (!isConnected_) {
662 HILOG_ERROR("connection is broken");
663 return RET_ERR_NO_CONNECTION;
664 }
665
666 std::lock_guard<std::mutex> lock(mutex_);
667 if (!channelClient_) {
668 HILOG_ERROR("The channel is invalid.");
669 return RET_ERR_NO_CONNECTION;
670 }
671 return channelClient_->SetTargetBundleName(targetBundleNames);
672 }
673
OnRemoteDied(const wptr<IRemoteObject> & remote)674 void AccessibleAbilityClientImpl::AccessibleAbilityDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& remote)
675 {
676 HILOG_ERROR();
677 client_.ResetAAClient(remote);
678 }
679
OnRemoteDied(const wptr<IRemoteObject> & remote)680 void AccessibleAbilityClientImpl::AccessibilityServiceDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& remote)
681 {
682 HILOG_ERROR();
683 client_.NotifyServiceDied(remote);
684 }
685
NotifyServiceDied(const wptr<IRemoteObject> & remote)686 void AccessibleAbilityClientImpl::NotifyServiceDied(const wptr<IRemoteObject> &remote)
687 {
688 std::shared_ptr<AccessibleAbilityListener> listener = nullptr;
689 {
690 std::lock_guard<std::mutex> lock(mutex_);
691 if (!serviceProxy_) {
692 HILOG_ERROR("serviceProxy_ is nullptr");
693 return;
694 }
695 sptr<IRemoteObject> object = serviceProxy_->AsObject();
696 if (object && (remote == object)) {
697 listener = listener_;
698 listener_ = nullptr;
699
700 object->RemoveDeathRecipient(accessibilityServiceDeathRecipient_);
701 serviceProxy_ = nullptr;
702 channelClient_ = nullptr;
703 HILOG_DEBUG("ResetAAClient OK");
704 }
705 }
706
707 isConnected_ = false;
708 if (listener) {
709 listener->OnAbilityDisconnected();
710 }
711 }
712
ResetAAClient(const wptr<IRemoteObject> & remote)713 void AccessibleAbilityClientImpl::ResetAAClient(const wptr<IRemoteObject> &remote)
714 {
715 HILOG_DEBUG();
716 std::lock_guard<std::mutex> lock(mutex_);
717 if (channelClient_) {
718 sptr<IRemoteObject> object = channelClient_->GetRemote();
719 if (object && (remote == object)) {
720 object->RemoveDeathRecipient(deathRecipient_);
721 channelClient_ = nullptr;
722 HILOG_DEBUG("ResetAAClient OK");
723 }
724 }
725
726 isConnected_ = false;
727 }
728
SetCacheMode(const int32_t cacheMode)729 RetError AccessibleAbilityClientImpl::SetCacheMode(const int32_t cacheMode)
730 {
731 HILOG_INFO("set cache mode: [%{public}d]", cacheMode);
732 std::lock_guard<std::mutex> lock(mutex_);
733 cacheWindowId_ = -1;
734 cacheElementInfos_.clear();
735 if (cacheMode < 0) {
736 cacheMode_ = 0;
737 } else {
738 uint32_t mode = static_cast<uint32_t>(cacheMode);
739 cacheMode_ = mode & static_cast<uint32_t>(GET_SOURCE_PREFETCH_MODE);
740 }
741 return RET_OK;
742 }
743
GetCacheElementInfo(const int32_t windowId,const int32_t elementId,AccessibilityElementInfo & elementInfo) const744 bool AccessibleAbilityClientImpl::GetCacheElementInfo(const int32_t windowId,
745 const int32_t elementId, AccessibilityElementInfo &elementInfo) const
746 {
747 HILOG_DEBUG();
748 if (cacheWindowId_ == -1 || cacheWindowId_ != windowId) {
749 HILOG_DEBUG("cacheWindowId[%{public}d], windowId[%{public}d]", cacheWindowId_, windowId);
750 return false;
751 }
752
753 auto iter = cacheElementInfos_.find(elementId);
754 if (iter == cacheElementInfos_.end()) {
755 HILOG_DEBUG("the element id[%{public}d] is not in cache", elementId);
756 return false;
757 }
758
759 elementInfo = iter->second;
760 return true;
761 }
762
SetCacheElementInfo(const int32_t windowId,const std::vector<OHOS::Accessibility::AccessibilityElementInfo> & elementInfos)763 void AccessibleAbilityClientImpl::SetCacheElementInfo(const int32_t windowId,
764 const std::vector<OHOS::Accessibility::AccessibilityElementInfo> &elementInfos)
765 {
766 HILOG_DEBUG("windowId[%{public}d], elementInfos size[%{public}zu]", windowId, elementInfos.size());
767 cacheElementInfos_.clear();
768 cacheWindowId_ = windowId;
769 for (auto &elementInfo : elementInfos) {
770 cacheElementInfos_.insert(std::make_pair(elementInfo.GetAccessibilityId(), elementInfo));
771 }
772 }
773
SearchElementInfoFromAce(const int32_t windowId,const int32_t elementId,const uint32_t mode,AccessibilityElementInfo & info)774 RetError AccessibleAbilityClientImpl::SearchElementInfoFromAce(const int32_t windowId, const int32_t elementId,
775 const uint32_t mode, AccessibilityElementInfo &info)
776 {
777 if (!channelClient_) {
778 HILOG_ERROR("The channel is invalid.");
779 return RET_ERR_NO_CONNECTION;
780 }
781
782 std::vector<AccessibilityElementInfo> elementInfos {};
783
784 RetError ret = channelClient_->SearchElementInfosByAccessibilityId(
785 windowId, elementId, static_cast<int32_t>(mode), elementInfos);
786 if (ret != RET_OK) {
787 HILOG_ERROR("search element info failed. windowId[%{public}d] elementId[%{public}d] mode[%{public}d]",
788 windowId, elementId, mode);
789 return ret;
790 }
791 if (elementInfos.empty()) {
792 HILOG_ERROR("elementInfos from ace is empty");
793 return RET_ERR_INVALID_ELEMENT_INFO_FROM_ACE;
794 }
795
796 HILOG_DEBUG("element [elementSize:%{public}zu]", elementInfos.size());
797 SetCacheElementInfo(windowId, elementInfos);
798 info = elementInfos.front();
799 return RET_OK;
800 }
801
Connect()802 RetError AccessibleAbilityClientImpl::Connect()
803 {
804 HILOG_DEBUG();
805 std::lock_guard<std::mutex> lock(mutex_);
806 if (!serviceProxy_) {
807 HILOG_ERROR("Failed to get aams service");
808 return RET_ERR_SAMGR;
809 }
810
811 return serviceProxy_->EnableUITestAbility(this->AsObject());
812 }
813
Disconnect()814 RetError AccessibleAbilityClientImpl::Disconnect()
815 {
816 HILOG_DEBUG();
817 std::lock_guard<std::mutex> lock(mutex_);
818 if (!serviceProxy_) {
819 HILOG_ERROR("Failed to get aams service");
820 return RET_ERR_SAMGR;
821 }
822 return serviceProxy_->DisableUITestAbility();
823 }
824 } // namespace Accessibility
825 } // namespace OHOS