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 "accessibility_system_ability_client_impl.h"
17 #include "hilog_wrapper.h"
18 #include "if_system_ability_manager.h"
19 #include "iservice_registry.h"
20 #include "parameter.h"
21 #include "system_ability_definition.h"
22
23 namespace OHOS {
24 namespace Accessibility {
25 namespace {
26 constexpr int32_t REQUEST_WINDOW_ID_MASK_BIT = 16;
27 constexpr int32_t CONFIG_PARAMETER_VALUE_SIZE = 10;
28 const std::string SYSTEM_PARAMETER_AAMS_NAME = "accessibility.config.ready";
29 } // namespaces
30
31 static std::mutex g_Mutex;
32 static std::shared_ptr<AccessibilitySystemAbilityClientImpl> g_Instance = nullptr;
GetInstance()33 std::shared_ptr<AccessibilitySystemAbilityClient> AccessibilitySystemAbilityClient::GetInstance()
34 {
35 HILOG_DEBUG();
36 std::lock_guard<std::mutex> lock(g_Mutex);
37 if (!g_Instance) {
38 g_Instance = std::make_shared<AccessibilitySystemAbilityClientImpl>();
39 } else {
40 HILOG_DEBUG("AccessibilitySystemAbilityClient had construct instance");
41 }
42
43 return g_Instance;
44 }
45
AccessibilitySystemAbilityClientImpl()46 AccessibilitySystemAbilityClientImpl::AccessibilitySystemAbilityClientImpl()
47 {
48 HILOG_DEBUG();
49
50 stateArray_.fill(false);
51 char value[CONFIG_PARAMETER_VALUE_SIZE] = "default";
52 int retSysParam = GetParameter(SYSTEM_PARAMETER_AAMS_NAME.c_str(), "false", value, CONFIG_PARAMETER_VALUE_SIZE);
53 if (retSysParam >= 0 && !std::strcmp(value, "true")) {
54 HILOG_ERROR("accessibility service is ready.");
55 if (!ConnectToService()) {
56 HILOG_ERROR("Failed to connect to aams service");
57 return;
58 }
59 Init();
60 }
61
62 retSysParam = WatchParameter(SYSTEM_PARAMETER_AAMS_NAME.c_str(), &OnParameterChanged, this);
63 if (retSysParam) {
64 HILOG_ERROR("Watch parameter failed, error = %{public}d", retSysParam);
65 }
66 }
67
~AccessibilitySystemAbilityClientImpl()68 AccessibilitySystemAbilityClientImpl::~AccessibilitySystemAbilityClientImpl()
69 {
70 HILOG_DEBUG();
71 }
72
ConnectToService()73 bool AccessibilitySystemAbilityClientImpl::ConnectToService()
74 {
75 HILOG_DEBUG();
76
77 if (serviceProxy_) {
78 HILOG_DEBUG("AAMS Service is connected");
79 return true;
80 }
81
82 sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
83 if (!samgr) {
84 HILOG_ERROR("Failed to get ISystemAbilityManager");
85 return false;
86 }
87
88 sptr<IRemoteObject> object = samgr->GetSystemAbility(ACCESSIBILITY_MANAGER_SERVICE_ID);
89 if (!object) {
90 HILOG_ERROR("Get IAccessibleAbilityManagerService object from samgr failed");
91 return false;
92 }
93
94 if (!deathRecipient_) {
95 deathRecipient_ = new(std::nothrow) DeathRecipient(*this);
96 if (!deathRecipient_) {
97 HILOG_ERROR("Failed to create deathRecipient.");
98 return false;
99 }
100 }
101
102 if ((object->IsProxyObject()) && (!object->AddDeathRecipient(deathRecipient_))) {
103 HILOG_ERROR("Failed to add death recipient");
104 }
105
106 HILOG_DEBUG("Get remote object ok");
107 serviceProxy_ = iface_cast<IAccessibleAbilityManagerService>(object);
108 if (!serviceProxy_) {
109 HILOG_ERROR("IAccessibleAbilityManagerService iface_cast failed");
110 return false;
111 }
112 return true;
113 }
114
OnParameterChanged(const char * key,const char * value,void * context)115 void AccessibilitySystemAbilityClientImpl::OnParameterChanged(const char *key, const char *value, void *context)
116 {
117 HILOG_DEBUG("Parameter key = [%{public}s] value = [%{public}s]", key, value);
118
119 if (!key || std::strcmp(key, SYSTEM_PARAMETER_AAMS_NAME.c_str())) {
120 HILOG_WARN("not accessibility.config.ready callback");
121 return;
122 }
123
124 if (!value || std::strcmp(value, "true")) {
125 HILOG_WARN("accessibility.config.ready value not true");
126 return;
127 }
128
129 if (!context) {
130 HILOG_ERROR("accessibility.config.ready context NULL");
131 return;
132 }
133
134 AccessibilitySystemAbilityClientImpl* implPtr = static_cast<AccessibilitySystemAbilityClientImpl*>(context);
135 {
136 HILOG_DEBUG("ConnectToService start.");
137 std::lock_guard<std::mutex> lock(implPtr->mutex_);
138 if (implPtr->serviceProxy_) {
139 HILOG_DEBUG("service is already started.");
140 return;
141 }
142 if (!implPtr->ConnectToService()) {
143 HILOG_ERROR("Failed to connect to aams service");
144 return;
145 }
146 implPtr->Init();
147 implPtr->ReregisterElementOperator();
148 }
149 }
150
Init()151 void AccessibilitySystemAbilityClientImpl::Init()
152 {
153 HILOG_DEBUG();
154 stateArray_.fill(false);
155 if (!stateObserver_) {
156 stateObserver_ = new(std::nothrow) AccessibleAbilityManagerStateObserverImpl(*this);
157 if (!stateObserver_) {
158 HILOG_ERROR("Failed to create stateObserver.");
159 return;
160 }
161 }
162 uint32_t stateType = serviceProxy_->RegisterStateObserver(stateObserver_);
163 if (stateType & STATE_ACCESSIBILITY_ENABLED) {
164 stateArray_[AccessibilityStateEventType::EVENT_ACCESSIBILITY_STATE_CHANGED] = true;
165 }
166 if (stateType & STATE_EXPLORATION_ENABLED) {
167 stateArray_[AccessibilityStateEventType::EVENT_TOUCH_GUIDE_STATE_CHANGED] = true;
168 }
169 if (stateType & STATE_KEYEVENT_ENABLED) {
170 stateArray_[AccessibilityStateEventType::EVENT_KEVEVENT_STATE_CHANGED] = true;
171 }
172 if (stateType & STATE_GESTURE_ENABLED) {
173 stateArray_[AccessibilityStateEventType::EVENT_GESTURE_STATE_CHANGED] = true;
174 }
175 }
176
ResetService(const wptr<IRemoteObject> & remote)177 void AccessibilitySystemAbilityClientImpl::ResetService(const wptr<IRemoteObject> &remote)
178 {
179 HILOG_DEBUG();
180 std::lock_guard<std::mutex> lock(mutex_);
181 if (serviceProxy_) {
182 sptr<IRemoteObject> object = serviceProxy_->AsObject();
183 if (object && (remote == object)) {
184 object->RemoveDeathRecipient(deathRecipient_);
185 serviceProxy_ = nullptr;
186 HILOG_DEBUG("Reset OK");
187 }
188 }
189 }
190
RegisterElementOperator(const int32_t windowId,const std::shared_ptr<AccessibilityElementOperator> & operation)191 RetError AccessibilitySystemAbilityClientImpl::RegisterElementOperator(
192 const int32_t windowId, const std::shared_ptr<AccessibilityElementOperator> &operation)
193 {
194 HILOG_INFO("Register windowId[%{public}d] start", windowId);
195 std::lock_guard<std::mutex> lock(mutex_);
196 if (!operation) {
197 HILOG_ERROR("Input operation is null");
198 return RET_ERR_INVALID_PARAM;
199 }
200 if (!serviceProxy_) {
201 HILOG_ERROR("Failed to get aams service");
202 return RET_ERR_SAMGR;
203 }
204
205 auto iter = elementOperators_.find(windowId);
206 if (iter != elementOperators_.end()) {
207 HILOG_ERROR("windowID[%{public}d] is exited", windowId);
208 return RET_ERR_CONNECTION_EXIST;
209 }
210
211 sptr<AccessibilityElementOperatorImpl> aamsInteractionOperator =
212 new(std::nothrow) AccessibilityElementOperatorImpl(windowId, operation, *this);
213 if (!aamsInteractionOperator) {
214 HILOG_ERROR("Failed to create aamsInteractionOperator.");
215 return RET_ERR_NULLPTR;
216 }
217 elementOperators_[windowId] = aamsInteractionOperator;
218 return serviceProxy_->RegisterElementOperator(windowId, aamsInteractionOperator);
219 }
220
ReregisterElementOperator()221 void AccessibilitySystemAbilityClientImpl::ReregisterElementOperator()
222 {
223 HILOG_DEBUG();
224
225 if (!serviceProxy_) {
226 HILOG_ERROR("serviceProxy_ is null.");
227 return;
228 }
229 for (auto iter = elementOperators_.begin(); iter != elementOperators_.end(); iter++) {
230 serviceProxy_->RegisterElementOperator(iter->first, iter->second);
231 }
232 }
233
DeregisterElementOperator(const int32_t windowId)234 RetError AccessibilitySystemAbilityClientImpl::DeregisterElementOperator(const int32_t windowId)
235 {
236 HILOG_INFO("Deregister windowId[%{public}d] start", windowId);
237 std::lock_guard<std::mutex> lock(mutex_);
238
239 if (!serviceProxy_) {
240 HILOG_ERROR("Failed to get aams service");
241 return RET_ERR_SAMGR;
242 }
243 auto iter = elementOperators_.find(windowId);
244 if (iter != elementOperators_.end()) {
245 HILOG_DEBUG("windowID[%{public}d] is erase", windowId);
246 elementOperators_.erase(iter);
247 } else {
248 HILOG_WARN("Not find windowID[%{public}d]", windowId);
249 return RET_ERR_NO_REGISTER;
250 }
251 return serviceProxy_->DeregisterElementOperator(windowId);
252 }
253
IsEnabled(bool & isEnabled)254 RetError AccessibilitySystemAbilityClientImpl::IsEnabled(bool &isEnabled)
255 {
256 HILOG_DEBUG();
257 std::lock_guard<std::mutex> lock(mutex_);
258 isEnabled = stateArray_[AccessibilityStateEventType::EVENT_ACCESSIBILITY_STATE_CHANGED];
259 return RET_OK;
260 }
261
IsTouchExplorationEnabled(bool & isEnabled)262 RetError AccessibilitySystemAbilityClientImpl::IsTouchExplorationEnabled(bool &isEnabled)
263 {
264 HILOG_DEBUG();
265 std::lock_guard<std::mutex> lock(mutex_);
266 isEnabled = stateArray_[AccessibilityStateEventType::EVENT_TOUCH_GUIDE_STATE_CHANGED];
267 return RET_OK;
268 }
269
GetAbilityList(const uint32_t accessibilityAbilityTypes,const AbilityStateType stateType,std::vector<AccessibilityAbilityInfo> & infos)270 RetError AccessibilitySystemAbilityClientImpl::GetAbilityList(const uint32_t accessibilityAbilityTypes,
271 const AbilityStateType stateType, std::vector<AccessibilityAbilityInfo> &infos)
272 {
273 HILOG_DEBUG();
274 std::lock_guard<std::mutex> lock(mutex_);
275 bool check = false;
276 if ((accessibilityAbilityTypes & AccessibilityAbilityTypes::ACCESSIBILITY_ABILITY_TYPE_SPOKEN) ||
277 (accessibilityAbilityTypes & AccessibilityAbilityTypes::ACCESSIBILITY_ABILITY_TYPE_HAPTIC) ||
278 (accessibilityAbilityTypes & AccessibilityAbilityTypes::ACCESSIBILITY_ABILITY_TYPE_AUDIBLE) ||
279 (accessibilityAbilityTypes & AccessibilityAbilityTypes::ACCESSIBILITY_ABILITY_TYPE_VISUAL) ||
280 (accessibilityAbilityTypes & AccessibilityAbilityTypes::ACCESSIBILITY_ABILITY_TYPE_GENERIC)) {
281 check = true;
282 }
283 if (stateType == ABILITY_STATE_INVALID) {
284 check = false;
285 }
286 if (!check) {
287 HILOG_ERROR("Invalid params: accessibilityAbilityTypes[%{public}d] stateType[%{public}d]",
288 accessibilityAbilityTypes, stateType);
289 return RET_ERR_INVALID_PARAM;
290 }
291 if (!serviceProxy_) {
292 HILOG_ERROR("Failed to get aams service");
293 return RET_ERR_SAMGR;
294 }
295 return serviceProxy_->GetAbilityList(accessibilityAbilityTypes, stateType, infos);
296 }
297
CheckEventType(EventType eventType)298 bool AccessibilitySystemAbilityClientImpl::CheckEventType(EventType eventType)
299 {
300 if ((eventType < EventType::TYPE_VIEW_CLICKED_EVENT) ||
301 ((eventType >= EventType::TYPE_MAX_NUM) && (eventType != EventType::TYPES_ALL_MASK))) {
302 HILOG_ERROR("event type is invalid");
303 return false;
304 } else {
305 return true;
306 }
307 }
308
SendEvent(const EventType eventType,const int32_t componentId)309 RetError AccessibilitySystemAbilityClientImpl::SendEvent(const EventType eventType, const int32_t componentId)
310 {
311 HILOG_DEBUG("componentId[%{public}d], eventType[%{public}d]", componentId, eventType);
312 std::lock_guard<std::mutex> lock(mutex_);
313 if (!CheckEventType(eventType)) {
314 return RET_ERR_INVALID_PARAM;
315 }
316 AccessibilityEventInfo event;
317 event.SetEventType(eventType);
318 event.SetSource(componentId);
319 if (!serviceProxy_) {
320 HILOG_ERROR("Failed to get aams service");
321 return RET_ERR_SAMGR;
322 }
323 return serviceProxy_->SendEvent(event);
324 }
325
SendEvent(const AccessibilityEventInfo & event)326 RetError AccessibilitySystemAbilityClientImpl::SendEvent(const AccessibilityEventInfo &event)
327 {
328 HILOG_DEBUG("EventType[%{public}d]", event.GetEventType());
329 std::lock_guard<std::mutex> lock(mutex_);
330 if (!CheckEventType(event.GetEventType())) {
331 return RET_ERR_INVALID_PARAM;
332 }
333 if (!serviceProxy_) {
334 HILOG_ERROR("Failed to get aams service");
335 return RET_ERR_SAMGR;
336 }
337 return serviceProxy_->SendEvent(event);
338 }
339
SubscribeStateObserver(const std::shared_ptr<AccessibilityStateObserver> & observer,const uint32_t eventType)340 RetError AccessibilitySystemAbilityClientImpl::SubscribeStateObserver(
341 const std::shared_ptr<AccessibilityStateObserver> &observer, const uint32_t eventType)
342 {
343 HILOG_DEBUG();
344 std::lock_guard<std::mutex> lock(mutex_);
345 if (eventType >= AccessibilityStateEventType::EVENT_TYPE_MAX) {
346 HILOG_ERROR("Input eventType is out of scope");
347 return RET_ERR_INVALID_PARAM;
348 }
349 if (!observer) {
350 HILOG_ERROR("Input observer is null");
351 return RET_ERR_INVALID_PARAM;
352 }
353
354 StateObserverVector &observerVector = stateObserversArray_[eventType];
355 for (auto iter = observerVector.begin(); iter != observerVector.end(); ++iter) {
356 if (*iter == observer) {
357 HILOG_INFO("Observer has subscribed!");
358 return RET_ERR_REGISTER_EXIST;
359 }
360 }
361 observerVector.push_back(observer);
362 return RET_OK;
363 }
364
UnsubscribeStateObserver(const std::shared_ptr<AccessibilityStateObserver> & observer,const uint32_t eventType)365 RetError AccessibilitySystemAbilityClientImpl::UnsubscribeStateObserver(
366 const std::shared_ptr<AccessibilityStateObserver> &observer, const uint32_t eventType)
367 {
368 HILOG_DEBUG("eventType is [%{public}d]", eventType);
369 std::lock_guard<std::mutex> lock(mutex_);
370 if (eventType >= AccessibilityStateEventType::EVENT_TYPE_MAX) {
371 HILOG_ERROR("Input eventType is out of scope");
372 return RET_ERR_INVALID_PARAM;
373 }
374 if (!observer) {
375 HILOG_ERROR("Input observer is null");
376 return RET_ERR_INVALID_PARAM;
377 }
378
379 StateObserverVector &observerVector = stateObserversArray_[eventType];
380 for (auto iter = observerVector.begin(); iter != observerVector.end(); ++iter) {
381 if (*iter == observer) {
382 observerVector.erase(iter);
383 return RET_OK;
384 }
385 }
386 HILOG_ERROR("The observer has not subscribed.");
387 return RET_ERR_NO_REGISTER;
388 }
389
NotifyStateChanged(uint32_t eventType,bool value)390 void AccessibilitySystemAbilityClientImpl::NotifyStateChanged(uint32_t eventType, bool value)
391 {
392 HILOG_DEBUG("EventType is %{public}d, value is %{public}d", eventType, value);
393 if (eventType >= AccessibilityStateEventType::EVENT_TYPE_MAX) {
394 HILOG_ERROR("EventType is invalid");
395 return;
396 }
397
398 if (stateArray_[eventType] == value) {
399 HILOG_DEBUG("State value is not changed");
400 return;
401 }
402
403 stateArray_[eventType] = value;
404 StateObserverVector &observers = stateObserversArray_[eventType];
405 for (auto &observer : observers) {
406 if (observer) {
407 observer->OnStateChanged(value);
408 } else {
409 HILOG_ERROR("end stateObserversArray[%{public}d] is null", eventType);
410 }
411 }
412 HILOG_DEBUG("end");
413 }
414
GetEnabledAbilities(std::vector<std::string> & enabledAbilities)415 RetError AccessibilitySystemAbilityClientImpl::GetEnabledAbilities(std::vector<std::string> &enabledAbilities)
416 {
417 HILOG_DEBUG();
418 std::lock_guard<std::mutex> lock(mutex_);
419 if (!serviceProxy_) {
420 HILOG_ERROR("Failed to get aams service");
421 return RET_ERR_SAMGR;
422 }
423 return serviceProxy_->GetEnabledAbilities(enabledAbilities);
424 }
425
OnAccessibleAbilityManagerStateChanged(const uint32_t stateType)426 void AccessibilitySystemAbilityClientImpl::OnAccessibleAbilityManagerStateChanged(const uint32_t stateType)
427 {
428 HILOG_DEBUG("stateType[%{public}d}", stateType);
429 std::lock_guard<std::mutex> lock(mutex_);
430 if (stateType & STATE_ACCESSIBILITY_ENABLED) {
431 NotifyStateChanged(AccessibilityStateEventType::EVENT_ACCESSIBILITY_STATE_CHANGED, true);
432 } else {
433 NotifyStateChanged(AccessibilityStateEventType::EVENT_ACCESSIBILITY_STATE_CHANGED, false);
434 }
435
436 if (stateType & STATE_EXPLORATION_ENABLED) {
437 NotifyStateChanged(AccessibilityStateEventType::EVENT_TOUCH_GUIDE_STATE_CHANGED, true);
438 } else {
439 NotifyStateChanged(AccessibilityStateEventType::EVENT_TOUCH_GUIDE_STATE_CHANGED, false);
440 }
441
442 if (stateType & STATE_KEYEVENT_ENABLED) {
443 NotifyStateChanged(AccessibilityStateEventType::EVENT_KEVEVENT_STATE_CHANGED, true);
444 } else {
445 NotifyStateChanged(AccessibilityStateEventType::EVENT_KEVEVENT_STATE_CHANGED, false);
446 }
447
448 if (stateType & STATE_GESTURE_ENABLED) {
449 NotifyStateChanged(AccessibilityStateEventType::EVENT_GESTURE_STATE_CHANGED, true);
450 } else {
451 NotifyStateChanged(AccessibilityStateEventType::EVENT_GESTURE_STATE_CHANGED, false);
452 }
453 }
454
SetSearchElementInfoByAccessibilityIdResult(const std::list<AccessibilityElementInfo> & infos,const int32_t requestId)455 void AccessibilitySystemAbilityClientImpl::SetSearchElementInfoByAccessibilityIdResult(
456 const std::list<AccessibilityElementInfo> &infos, const int32_t requestId)
457 {
458 std::lock_guard<std::mutex> lock(mutex_);
459 HILOG_DEBUG("requestId[%{public}d]", requestId);
460 if (requestId >= 0) {
461 auto iter = elementOperators_.find(static_cast<uint32_t>(requestId) >> REQUEST_WINDOW_ID_MASK_BIT);
462 if (iter != elementOperators_.end()) {
463 if (iter->second) {
464 iter->second->SetSearchElementInfoByAccessibilityIdResult(infos, requestId);
465 }
466 }
467 }
468 }
469
SetSearchElementInfoByTextResult(const std::list<AccessibilityElementInfo> & infos,const int32_t requestId)470 void AccessibilitySystemAbilityClientImpl::SetSearchElementInfoByTextResult(
471 const std::list<AccessibilityElementInfo> &infos, const int32_t requestId)
472 {
473 std::lock_guard<std::mutex> lock(mutex_);
474 HILOG_DEBUG("requestId[%{public}d]", requestId);
475 if (requestId >= 0) {
476 auto iter = elementOperators_.find(static_cast<uint32_t>(requestId) >> REQUEST_WINDOW_ID_MASK_BIT);
477 if (iter != elementOperators_.end()) {
478 if (iter->second) {
479 iter->second->SetSearchElementInfoByTextResult(infos, requestId);
480 }
481 }
482 }
483 }
484
SetFindFocusedElementInfoResult(const AccessibilityElementInfo & info,const int32_t requestId)485 void AccessibilitySystemAbilityClientImpl::SetFindFocusedElementInfoResult(
486 const AccessibilityElementInfo &info, const int32_t requestId)
487 {
488 std::lock_guard<std::mutex> lock(mutex_);
489 HILOG_DEBUG("requestId[%{public}d]", requestId);
490 if (requestId >= 0) {
491 auto iter = elementOperators_.find(static_cast<uint32_t>(requestId) >> REQUEST_WINDOW_ID_MASK_BIT);
492 if (iter != elementOperators_.end()) {
493 if (iter->second) {
494 iter->second->SetFindFocusedElementInfoResult(info, requestId);
495 }
496 }
497 }
498 }
499
SetFocusMoveSearchResult(const AccessibilityElementInfo & info,const int32_t requestId)500 void AccessibilitySystemAbilityClientImpl::SetFocusMoveSearchResult(
501 const AccessibilityElementInfo &info, const int32_t requestId)
502 {
503 std::lock_guard<std::mutex> lock(mutex_);
504 HILOG_DEBUG("requestId[%{public}d]", requestId);
505 if (requestId >= 0) {
506 auto iter = elementOperators_.find(static_cast<uint32_t>(requestId) >> REQUEST_WINDOW_ID_MASK_BIT);
507 if (iter != elementOperators_.end()) {
508 if (iter->second) {
509 iter->second->SetFocusMoveSearchResult(info, requestId);
510 }
511 }
512 }
513 }
514
SetExecuteActionResult(const bool succeeded,const int32_t requestId)515 void AccessibilitySystemAbilityClientImpl::SetExecuteActionResult(
516 const bool succeeded, const int32_t requestId)
517 {
518 std::lock_guard<std::mutex> lock(mutex_);
519 HILOG_DEBUG("requestId[%{public}d]", requestId);
520 if (requestId >= 0) {
521 auto iter = elementOperators_.find(static_cast<uint32_t>(requestId) >> REQUEST_WINDOW_ID_MASK_BIT);
522 if (iter != elementOperators_.end()) {
523 if (iter->second) {
524 iter->second->SetExecuteActionResult(succeeded, requestId);
525 }
526 }
527 }
528 }
529 } // namespace Accessibility
530 } // namespace OHOS