• 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     std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_WINDOW_REGIST));
217     if (listener) {
218         listener->OnAbilityConnected();
219     }
220 }
221 
Disconnect(const int32_t channelId)222 void AccessibleAbilityClientImpl::Disconnect(const int32_t channelId)
223 {
224     HILOG_INFO("channelId[%{public}d]", channelId);
225 
226     std::shared_ptr<AccessibleAbilityListener> listener = nullptr;
227     {
228         std::lock_guard<std::mutex> lock(mutex_);
229         // Delete death recipient
230         if (channelClient_ && channelClient_->GetRemote()) {
231             HILOG_ERROR("Remove death recipient");
232             channelClient_->GetRemote()->RemoveDeathRecipient(deathRecipient_);
233         }
234 
235         // Remove channel
236         channelClient_ = nullptr;
237         listener = listener_;
238         listener_ = nullptr;
239     }
240 
241     if (listener) {
242         listener->OnAbilityDisconnected();
243     }
244 }
245 
OnAccessibilityEvent(const AccessibilityEventInfo & eventInfo)246 void AccessibleAbilityClientImpl::OnAccessibilityEvent(const AccessibilityEventInfo &eventInfo)
247 {
248     HILOG_INFO();
249     std::shared_ptr<AccessibleAbilityListener> listener = nullptr;
250     {
251         std::lock_guard<std::mutex> lock(mutex_);
252         if (!channelClient_) {
253             HILOG_ERROR("The channel is invalid.");
254             return;
255         }
256         listener = listener_;
257     }
258     if (listener) {
259         listener->OnAccessibilityEvent(eventInfo);
260     }
261 }
262 
OnKeyPressEvent(const MMI::KeyEvent & keyEvent,const int32_t sequence)263 void AccessibleAbilityClientImpl::OnKeyPressEvent(const MMI::KeyEvent &keyEvent, const int32_t sequence)
264 {
265     HILOG_INFO("sequence[%{public}d]", sequence);
266     std::shared_ptr<AccessibleAbilityListener> listener = nullptr;
267     std::shared_ptr<AccessibleAbilityChannelClient> channel = nullptr;
268     {
269         std::lock_guard<std::mutex> lock(mutex_);
270         listener = listener_;
271         channel = channelClient_;
272     }
273 
274     if (!channel) {
275         HILOG_ERROR("The channel is invalid.");
276         return;
277     }
278     bool handled = false;
279     if (listener) {
280         std::shared_ptr<MMI::KeyEvent> tmp = std::make_shared<MMI::KeyEvent>(keyEvent);
281         handled = listener->OnKeyPressEvent(tmp);
282     }
283     channel->SetOnKeyPressEventResult(handled, sequence);
284 }
285 
GetFocus(const int32_t focusType,AccessibilityElementInfo & elementInfo)286 RetError AccessibleAbilityClientImpl::GetFocus(const int32_t focusType, AccessibilityElementInfo &elementInfo)
287 {
288     HILOG_INFO("focusType[%{public}d]", focusType);
289     std::lock_guard<std::mutex> lock(mutex_);
290     if ((focusType != FOCUS_TYPE_INPUT) && (focusType != FOCUS_TYPE_ACCESSIBILITY)) {
291         HILOG_ERROR("focusType is not allowed.");
292         return RET_ERR_INVALID_PARAM;
293     }
294 
295     if (!channelClient_) {
296         HILOG_ERROR("The channel is invalid.");
297         return RET_ERR_NO_CONNECTION;
298     }
299 
300     return channelClient_->FindFocusedElementInfo(ANY_WINDOW_ID, ROOT_NODE_ID, focusType, elementInfo);
301 }
302 
GetFocusByElementInfo(const AccessibilityElementInfo & sourceInfo,const int32_t focusType,AccessibilityElementInfo & elementInfo)303 RetError AccessibleAbilityClientImpl::GetFocusByElementInfo(const AccessibilityElementInfo &sourceInfo,
304     const int32_t focusType, AccessibilityElementInfo &elementInfo)
305 {
306     HILOG_INFO("focusType[%{public}d]", focusType);
307     std::lock_guard<std::mutex> lock(mutex_);
308     if ((focusType != FOCUS_TYPE_INPUT) && (focusType != FOCUS_TYPE_ACCESSIBILITY)) {
309         HILOG_ERROR("focusType is not allowed.");
310         return RET_ERR_INVALID_PARAM;
311     }
312 
313     if (!channelClient_) {
314         HILOG_ERROR("The channel is invalid.");
315         return RET_ERR_NO_CONNECTION;
316     }
317 
318     int32_t windowId = sourceInfo.GetWindowId();
319     int32_t elementId = sourceInfo.GetAccessibilityId();
320     HILOG_INFO("windowId[%{public}d], elementId[%{public}d], focusType[%{public}d]", windowId, elementId, focusType);
321 
322     return channelClient_->FindFocusedElementInfo(windowId, elementId, focusType, elementInfo);
323 }
324 
InjectGesture(const std::shared_ptr<AccessibilityGestureInjectPath> & gesturePath)325 RetError AccessibleAbilityClientImpl::InjectGesture(const std::shared_ptr<AccessibilityGestureInjectPath> &gesturePath)
326 {
327     HILOG_INFO();
328     std::lock_guard<std::mutex> lock(mutex_);
329 
330     if (!gesturePath) {
331         HILOG_ERROR("The gesturePath is null.");
332         return RET_ERR_INVALID_PARAM;
333     }
334 
335     std::vector<AccessibilityGesturePosition> positions = gesturePath->GetPositions();
336 
337     if (positions.size() == 0) {
338         HILOG_ERROR("The number of gesture path position is not allowed.");
339         return RET_ERR_INVALID_PARAM;
340     }
341 
342     if (!channelClient_) {
343         HILOG_ERROR("The channel is invalid.");
344         return RET_ERR_NO_CONNECTION;
345     }
346 
347     return channelClient_->SendSimulateGesture(gesturePath);
348 }
349 
GetRoot(AccessibilityElementInfo & elementInfo)350 RetError AccessibleAbilityClientImpl::GetRoot(AccessibilityElementInfo &elementInfo)
351 {
352     HILOG_DEBUG();
353     std::lock_guard<std::mutex> lock(mutex_);
354     if (!serviceProxy_) {
355         HILOG_ERROR("Failed to connect to aams");
356         return RET_ERR_SAMGR;
357     }
358 
359     if (!channelClient_) {
360         HILOG_ERROR("The channel is invalid.");
361         return RET_ERR_NO_CONNECTION;
362     }
363 
364     int32_t activeWindow = serviceProxy_->GetActiveWindow();
365     HILOG_INFO("activeWindow[%{public}d]", activeWindow);
366     if (GetCacheElementInfo(activeWindow, ROOT_NONE_ID, elementInfo)) {
367         HILOG_DEBUG("get element info from cache");
368         return RET_OK;
369     }
370 
371     return SearchElementInfoFromAce(activeWindow, ROOT_NONE_ID, cacheMode_, elementInfo);
372 }
373 
GetRootByWindow(const AccessibilityWindowInfo & windowInfo,AccessibilityElementInfo & elementInfo)374 RetError AccessibleAbilityClientImpl::GetRootByWindow(const AccessibilityWindowInfo &windowInfo,
375     AccessibilityElementInfo &elementInfo)
376 {
377     HILOG_DEBUG();
378     std::lock_guard<std::mutex> lock(mutex_);
379     if (!channelClient_) {
380         HILOG_ERROR("The channel is invalid.");
381         return RET_ERR_NO_CONNECTION;
382     }
383 
384     int32_t windowId = windowInfo.GetWindowId();
385     HILOG_INFO("windowId[%{public}d]", windowId);
386     if (GetCacheElementInfo(windowId, ROOT_NONE_ID, elementInfo)) {
387         HILOG_DEBUG("get element info from cache");
388         return RET_OK;
389     }
390 
391     return SearchElementInfoFromAce(windowId, ROOT_NONE_ID, cacheMode_, elementInfo);
392 }
393 
GetWindow(const int32_t windowId,AccessibilityWindowInfo & windowInfo)394 RetError AccessibleAbilityClientImpl::GetWindow(const int32_t windowId, AccessibilityWindowInfo &windowInfo)
395 {
396     HILOG_INFO("windowId[%{public}d]", windowId);
397     std::lock_guard<std::mutex> lock(mutex_);
398     if (!channelClient_) {
399         HILOG_ERROR("The channel is invalid.");
400         return RET_ERR_NO_CONNECTION;
401     }
402     return channelClient_->GetWindow(windowId, windowInfo);
403 }
404 
GetWindows(std::vector<AccessibilityWindowInfo> & windows)405 RetError AccessibleAbilityClientImpl::GetWindows(std::vector<AccessibilityWindowInfo> &windows)
406 {
407     HILOG_INFO();
408     std::lock_guard<std::mutex> lock(mutex_);
409     if (!channelClient_) {
410         HILOG_ERROR("The channel is invalid.");
411         return RET_ERR_NO_CONNECTION;
412     }
413     return channelClient_->GetWindows(windows);
414 }
415 
GetWindows(const uint64_t displayId,std::vector<AccessibilityWindowInfo> & windows)416 RetError AccessibleAbilityClientImpl::GetWindows(const uint64_t displayId,
417     std::vector<AccessibilityWindowInfo> &windows)
418 {
419     HILOG_INFO("displayId[%{public}" PRIu64 "]", displayId);
420     std::lock_guard<std::mutex> lock(mutex_);
421     if (!channelClient_) {
422         HILOG_ERROR("The channel is invalid.");
423         return RET_ERR_NO_CONNECTION;
424     }
425     return channelClient_->GetWindows(displayId, windows);
426 }
427 
GetNext(const AccessibilityElementInfo & elementInfo,const FocusMoveDirection direction,AccessibilityElementInfo & nextElementInfo)428 RetError AccessibleAbilityClientImpl::GetNext(const AccessibilityElementInfo &elementInfo,
429     const FocusMoveDirection direction, AccessibilityElementInfo &nextElementInfo)
430 {
431     HILOG_INFO("windowId[%{public}d], elementId[%{public}d], direction[%{public}d]",
432         elementInfo.GetWindowId(), elementInfo.GetAccessibilityId(), direction);
433     std::lock_guard<std::mutex> lock(mutex_);
434     if (!channelClient_) {
435         HILOG_ERROR("The channel is invalid.");
436         return RET_ERR_NO_CONNECTION;
437     }
438     if (direction == DIRECTION_INVALID) {
439         HILOG_ERROR("direction is invalid.");
440         return RET_ERR_INVALID_PARAM;
441     }
442     return channelClient_->FocusMoveSearch(elementInfo.GetWindowId(),
443         elementInfo.GetAccessibilityId(), direction, nextElementInfo);
444 }
445 
GetChildElementInfo(const int32_t index,const AccessibilityElementInfo & parent,AccessibilityElementInfo & child)446 RetError AccessibleAbilityClientImpl::GetChildElementInfo(const int32_t index, const AccessibilityElementInfo &parent,
447     AccessibilityElementInfo &child)
448 {
449     HILOG_DEBUG();
450     std::lock_guard<std::mutex> lock(mutex_);
451     if (!channelClient_) {
452         HILOG_ERROR("The channel is invalid.");
453         return RET_ERR_NO_CONNECTION;
454     }
455 
456     int32_t windowId = parent.GetWindowId();
457     int32_t childId = parent.GetChildId(index);
458     HILOG_INFO("windowId[%{public}d], childId[%{public}d]", windowId, childId);
459     if (childId == -1) {
460         HILOG_ERROR("childId[%{public}d] is invalid", childId);
461         return RET_ERR_INVALID_PARAM;
462     }
463     if (GetCacheElementInfo(windowId, childId, child)) {
464         HILOG_DEBUG("get element info from cache");
465         return RET_OK;
466     }
467 
468     return SearchElementInfoFromAce(windowId, childId, cacheMode_, child);
469 }
470 
GetChildren(const AccessibilityElementInfo & parent,std::vector<AccessibilityElementInfo> & children)471 RetError AccessibleAbilityClientImpl::GetChildren(const AccessibilityElementInfo &parent,
472     std::vector<AccessibilityElementInfo> &children)
473 {
474     HILOG_DEBUG();
475     std::lock_guard<std::mutex> lock(mutex_);
476     if (!channelClient_) {
477         HILOG_ERROR("The channel is invalid.");
478         return RET_ERR_NO_CONNECTION;
479     }
480 
481     int32_t windowId = parent.GetWindowId();
482     std::vector<int32_t> childIds =  parent.GetChildIds();
483     HILOG_INFO("windowId[%{public}d], childIds.size[%{public}zu]", windowId, childIds.size());
484     for (auto &childId : childIds) {
485         HILOG_DEBUG("childId[%{public}d]", childId);
486         if (childId == -1) {
487             HILOG_ERROR("childId is invalid");
488             return RET_ERR_INVALID_PARAM;
489         }
490 
491         AccessibilityElementInfo child;
492         if (GetCacheElementInfo(windowId, childId, child)) {
493             HILOG_DEBUG("get element info from cache");
494             children.emplace_back(child);
495             continue;
496         }
497 
498         RetError ret = SearchElementInfoFromAce(windowId, childId, cacheMode_, child);
499         if (ret != RET_OK) {
500             HILOG_ERROR("Get element info from ace failed");
501             return ret;
502         }
503         children.emplace_back(child);
504     }
505     return RET_OK;
506 }
507 
GetByContent(const AccessibilityElementInfo & elementInfo,const std::string & text,std::vector<AccessibilityElementInfo> & elementInfos)508 RetError AccessibleAbilityClientImpl::GetByContent(const AccessibilityElementInfo &elementInfo,
509     const std::string &text, std::vector<AccessibilityElementInfo> &elementInfos)
510 {
511     HILOG_DEBUG();
512     std::lock_guard<std::mutex> lock(mutex_);
513     if (!channelClient_) {
514         HILOG_ERROR("The channel is invalid.");
515         return RET_ERR_NO_CONNECTION;
516     }
517     int32_t windowId = elementInfo.GetWindowId();
518     int32_t elementId = elementInfo.GetAccessibilityId();
519     HILOG_INFO("windowId[%{public}d], elementId[%{public}d], text[%{public}s]", windowId, elementId, text.c_str());
520     return channelClient_->SearchElementInfosByText(windowId, elementId, text, elementInfos);
521 }
522 
GetSource(const AccessibilityEventInfo & eventInfo,AccessibilityElementInfo & elementInfo)523 RetError AccessibleAbilityClientImpl::GetSource(const AccessibilityEventInfo &eventInfo,
524     AccessibilityElementInfo &elementInfo)
525 {
526     HILOG_DEBUG();
527     std::lock_guard<std::mutex> lock(mutex_);
528     if (!channelClient_) {
529         HILOG_ERROR("The channel is invalid.");
530         return RET_ERR_NO_CONNECTION;
531     }
532     int32_t windowId = eventInfo.GetWindowId();
533     int32_t elementId = eventInfo.GetAccessibilityId();
534     HILOG_INFO("windowId[%{public}d], elementId[%{public}d]", windowId, elementId);
535     if (GetCacheElementInfo(windowId, elementId, elementInfo)) {
536         HILOG_DEBUG("get element info from cache");
537         return RET_OK;
538     }
539     return SearchElementInfoFromAce(windowId, elementId, cacheMode_, elementInfo);
540 }
541 
GetParentElementInfo(const AccessibilityElementInfo & child,AccessibilityElementInfo & parent)542 RetError AccessibleAbilityClientImpl::GetParentElementInfo(const AccessibilityElementInfo &child,
543     AccessibilityElementInfo &parent)
544 {
545     HILOG_DEBUG();
546     std::lock_guard<std::mutex> lock(mutex_);
547     if (!channelClient_) {
548         HILOG_ERROR("The channel is invalid.");
549         return RET_ERR_NO_CONNECTION;
550     }
551     int32_t windowId = child.GetWindowId();
552     int32_t elementId = child.GetParentNodeId();
553     HILOG_INFO("windowId[%{public}d], parentId[%{public}d]", windowId, elementId);
554     if (GetCacheElementInfo(windowId, elementId, parent)) {
555         HILOG_DEBUG("get element info from cache");
556         return RET_OK;
557     }
558 
559     return SearchElementInfoFromAce(windowId, elementId, cacheMode_, parent);
560 }
561 
ExecuteAction(const AccessibilityElementInfo & elementInfo,const ActionType action,const std::map<std::string,std::string> & actionArguments)562 RetError AccessibleAbilityClientImpl::ExecuteAction(const AccessibilityElementInfo &elementInfo,
563     const ActionType action, const std::map<std::string, std::string> &actionArguments)
564 {
565     HILOG_DEBUG();
566     std::lock_guard<std::mutex> lock(mutex_);
567     if (!channelClient_) {
568         HILOG_ERROR("The channel is invalid.");
569         return RET_ERR_NO_CONNECTION;
570     }
571     if (action == ACCESSIBILITY_ACTION_INVALID) {
572         HILOG_ERROR("action is invalid.");
573         return RET_ERR_INVALID_PARAM;
574     }
575     int32_t windowId = elementInfo.GetWindowId();
576     int32_t elementId = elementInfo.GetAccessibilityId();
577     HILOG_INFO("windowId[%{public}d], elementId[%{public}d], action[%{public}d", windowId, elementId, action);
578     return channelClient_->ExecuteAction(windowId, elementId, action,
579         const_cast<std::map<std::string, std::string> &>(actionArguments));
580 }
581 
SetTargetBundleName(const std::vector<std::string> & targetBundleNames)582 RetError AccessibleAbilityClientImpl::SetTargetBundleName(const std::vector<std::string> &targetBundleNames)
583 {
584     HILOG_INFO("targetBundleNames size[%{public}zu]", targetBundleNames.size());
585     std::lock_guard<std::mutex> lock(mutex_);
586     if (!channelClient_) {
587         HILOG_ERROR("The channel is invalid.");
588         return RET_ERR_NO_CONNECTION;
589     }
590     return channelClient_->SetTargetBundleName(targetBundleNames);
591 }
592 
OnRemoteDied(const wptr<IRemoteObject> & remote)593 void AccessibleAbilityClientImpl::AccessibleAbilityDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& remote)
594 {
595     HILOG_ERROR();
596     client_.ResetAAClient(remote);
597 }
598 
OnRemoteDied(const wptr<IRemoteObject> & remote)599 void AccessibleAbilityClientImpl::AccessibilityServiceDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& remote)
600 {
601     HILOG_ERROR();
602     client_.NotifyServiceDied(remote);
603 }
604 
NotifyServiceDied(const wptr<IRemoteObject> & remote)605 void AccessibleAbilityClientImpl::NotifyServiceDied(const wptr<IRemoteObject> &remote)
606 {
607     std::shared_ptr<AccessibleAbilityListener> listener = nullptr;
608     {
609         std::lock_guard<std::mutex> lock(mutex_);
610         if (!serviceProxy_) {
611             HILOG_ERROR("serviceProxy_ is nullptr");
612             return;
613         }
614         sptr<IRemoteObject> object = serviceProxy_->AsObject();
615         if (object && (remote == object)) {
616             listener = listener_;
617             listener_ = nullptr;
618 
619             object->RemoveDeathRecipient(accessibilityServiceDeathRecipient_);
620             serviceProxy_ = nullptr;
621             channelClient_ = nullptr;
622             HILOG_DEBUG("ResetAAClient OK");
623         }
624     }
625 
626     if (listener) {
627         listener->OnAbilityDisconnected();
628     }
629 }
630 
ResetAAClient(const wptr<IRemoteObject> & remote)631 void AccessibleAbilityClientImpl::ResetAAClient(const wptr<IRemoteObject> &remote)
632 {
633     HILOG_DEBUG();
634     std::lock_guard<std::mutex> lock(mutex_);
635     if (channelClient_) {
636         sptr<IRemoteObject> object = channelClient_->GetRemote();
637         if (object && (remote == object)) {
638             object->RemoveDeathRecipient(deathRecipient_);
639             channelClient_ = nullptr;
640             HILOG_DEBUG("ResetAAClient OK");
641         }
642     }
643 }
644 
SetCacheMode(const int32_t cacheMode)645 RetError AccessibleAbilityClientImpl::SetCacheMode(const int32_t cacheMode)
646 {
647     HILOG_INFO("set cache mode: [%{public}d]", cacheMode);
648     std::lock_guard<std::mutex> lock(mutex_);
649     cacheWindowId_ = -1;
650     cacheElementInfos_.clear();
651     if (cacheMode < 0) {
652         cacheMode_ = 0;
653     } else {
654         uint32_t mode = static_cast<uint32_t>(cacheMode);
655         cacheMode_ = mode & static_cast<uint32_t>(GET_SOURCE_PREFETCH_MODE);
656     }
657     return RET_OK;
658 }
659 
GetCacheElementInfo(const int32_t windowId,const int32_t elementId,AccessibilityElementInfo & elementInfo) const660 bool AccessibleAbilityClientImpl::GetCacheElementInfo(const int32_t windowId,
661     const int32_t elementId, AccessibilityElementInfo &elementInfo) const
662 {
663     HILOG_DEBUG();
664     if (cacheWindowId_ == -1 || cacheWindowId_ != windowId) {
665         HILOG_DEBUG("cacheWindowId[%{public}d], windowId[%{public}d]", cacheWindowId_, windowId);
666         return false;
667     }
668 
669     auto iter = cacheElementInfos_.find(elementId);
670     if (iter == cacheElementInfos_.end()) {
671         HILOG_DEBUG("the element id[%{public}d] is not in cache", elementId);
672         return false;
673     }
674 
675     elementInfo = iter->second;
676     return true;
677 }
678 
SetCacheElementInfo(const int32_t windowId,const std::vector<OHOS::Accessibility::AccessibilityElementInfo> & elementInfos)679 void AccessibleAbilityClientImpl::SetCacheElementInfo(const int32_t windowId,
680     const std::vector<OHOS::Accessibility::AccessibilityElementInfo> &elementInfos)
681 {
682     HILOG_DEBUG("windowId[%{public}d], elementInfos size[%{public}zu]", windowId, elementInfos.size());
683     cacheElementInfos_.clear();
684     cacheWindowId_ = windowId;
685     for (auto &elementInfo : elementInfos) {
686         cacheElementInfos_.insert(std::make_pair(elementInfo.GetAccessibilityId(), elementInfo));
687     }
688 }
689 
SearchElementInfoFromAce(const int32_t windowId,const int32_t elementId,const uint32_t mode,AccessibilityElementInfo & info)690 RetError AccessibleAbilityClientImpl::SearchElementInfoFromAce(const int32_t windowId, const int32_t elementId,
691     const uint32_t mode, AccessibilityElementInfo &info)
692 {
693     if (!channelClient_) {
694         HILOG_ERROR("The channel is invalid.");
695         return RET_ERR_NO_CONNECTION;
696     }
697 
698     std::vector<AccessibilityElementInfo> elementInfos {};
699 
700     RetError ret = channelClient_->SearchElementInfosByAccessibilityId(
701         windowId, elementId, static_cast<int32_t>(mode), elementInfos);
702     if (ret != RET_OK) {
703         HILOG_ERROR("search element info failed. windowId[%{public}d] elementId[%{public}d] mode[%{public}d]",
704             windowId, elementId, mode);
705         return ret;
706     }
707     if (elementInfos.empty()) {
708         HILOG_ERROR("elementInfos from ace is empty");
709         return RET_ERR_INVALID_ELEMENT_INFO_FROM_ACE;
710     }
711 
712     HILOG_DEBUG("element [elementSize:%{public}zu]", elementInfos.size());
713     SetCacheElementInfo(windowId, elementInfos);
714     info = elementInfos.front();
715     return RET_OK;
716 }
717 
Connect()718 RetError AccessibleAbilityClientImpl::Connect()
719 {
720     HILOG_DEBUG();
721     std::lock_guard<std::mutex> lock(mutex_);
722     if (!serviceProxy_) {
723         HILOG_ERROR("Failed to get aams service");
724         return RET_ERR_SAMGR;
725     }
726 
727     return serviceProxy_->EnableUITestAbility(this->AsObject());
728 }
729 
Disconnect()730 RetError AccessibleAbilityClientImpl::Disconnect()
731 {
732     HILOG_DEBUG();
733     std::lock_guard<std::mutex> lock(mutex_);
734     if (!serviceProxy_) {
735         HILOG_ERROR("Failed to get aams service");
736         return RET_ERR_SAMGR;
737     }
738     return serviceProxy_->DisableUITestAbility();
739 }
740 } // namespace Accessibility
741 } // namespace OHOS