• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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