1 /*
2 * Copyright (C) 2022-2024 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_input_interceptor.h"
17 #include "accessibility_keyevent_filter.h"
18 #include "accessibility_mouse_autoclick.h"
19 #include "accessibility_short_key.h"
20 #include "accessibility_screen_touch.h"
21 #include "accessibility_touch_exploration.h"
22 #include "accessibility_touchEvent_injector.h"
23 #include "accessibility_zoom_gesture.h"
24 #include "accessible_ability_manager_service.h"
25 #include "hilog_wrapper.h"
26 #include "key_event.h"
27 #include "input_event.h"
28 #ifdef ACCESSIBILITY_WATCH_FEATURE
29 #include "res_type.h"
30 #include "res_sched_client.h"
31 #endif // ACCESSIBILITY_WATCH_FEATURE
32
33 namespace OHOS {
34 namespace Accessibility {
35 sptr<AccessibilityInputInterceptor> AccessibilityInputInterceptor::instance_ = nullptr;
GetInstance()36 sptr<AccessibilityInputInterceptor> AccessibilityInputInterceptor::GetInstance()
37 {
38 HILOG_DEBUG();
39
40 if (!instance_) {
41 instance_ = new(std::nothrow) AccessibilityInputInterceptor();
42 if (!instance_) {
43 HILOG_ERROR("instance_ is null");
44 return nullptr;
45 }
46 }
47 return instance_;
48 }
49
AccessibilityInputInterceptor()50 AccessibilityInputInterceptor::AccessibilityInputInterceptor()
51 {
52 HILOG_DEBUG();
53
54 inputManager_ = MMI::InputManager::GetInstance();
55 eventHandler_ = std::make_shared<AppExecFwk::EventHandler>(
56 Singleton<AccessibleAbilityManagerService>::GetInstance().GetInputManagerRunner());
57 }
58
~AccessibilityInputInterceptor()59 AccessibilityInputInterceptor::~AccessibilityInputInterceptor()
60 {
61 HILOG_DEBUG();
62
63 availableFunctions_ = 0;
64 DestroyInterceptor();
65 DestroyTransmitters();
66 inputManager_ = nullptr;
67 inputEventConsumer_ = nullptr;
68 }
69
OnKeyEvent(MMI::KeyEvent & event)70 bool AccessibilityInputInterceptor::OnKeyEvent(MMI::KeyEvent &event)
71 {
72 HILOG_DEBUG();
73
74 event.AddFlag(MMI::InputEvent::EVENT_FLAG_NO_INTERCEPT);
75 std::shared_ptr<MMI::KeyEvent> keyEvent = std::make_shared<MMI::KeyEvent>(event);
76 if (inputManager_) {
77 inputManager_->SimulateInputEvent(keyEvent);
78 } else {
79 HILOG_ERROR("inputManager_ is null.");
80 }
81 return true;
82 }
83
OnPointerEvent(MMI::PointerEvent & event)84 bool AccessibilityInputInterceptor::OnPointerEvent(MMI::PointerEvent &event)
85 {
86 if (event.GetPointerAction() != MMI::PointerEvent::POINTER_ACTION_MOVE &&
87 event.GetPointerAction() != MMI::PointerEvent::POINTER_ACTION_HOVER_MOVE) {
88 HILOG_INFO("PointerAction:%{public}d, SourceType:%{public}d, PointerId:%{public}d",
89 event.GetPointerAction(), event.GetSourceType(), event.GetPointerId());
90 } else {
91 HILOG_DEBUG("PointerAction:%{public}d, SourceType:%{public}d, PointerId:%{public}d",
92 event.GetPointerAction(), event.GetSourceType(), event.GetPointerId());
93 }
94
95 event.AddFlag(MMI::InputEvent::EVENT_FLAG_NO_INTERCEPT);
96 std::shared_ptr<MMI::PointerEvent> pointerEvent = std::make_shared<MMI::PointerEvent>(event);
97 if (inputManager_) {
98 inputManager_->SimulateInputEvent(pointerEvent);
99 } else {
100 HILOG_ERROR("inputManager_ is null.");
101 }
102 return true;
103 }
104
OnMoveMouse(int32_t offsetX,int32_t offsetY)105 void AccessibilityInputInterceptor::OnMoveMouse(int32_t offsetX, int32_t offsetY)
106 {
107 HILOG_DEBUG("offsetX:%{public}d, offsetY:%{public}d", offsetX, offsetY);
108 if (inputManager_) {
109 inputManager_->MoveMouse(offsetX, offsetY);
110 } else {
111 HILOG_ERROR("inputManager_ is null.");
112 }
113 }
114
SetAvailableFunctions(uint32_t availableFunctions)115 void AccessibilityInputInterceptor::SetAvailableFunctions(uint32_t availableFunctions)
116 {
117 HILOG_INFO("function[%{public}d].", availableFunctions);
118
119 if (((availableFunctions_ & FEATURE_SCREEN_MAGNIFICATION) != FEATURE_SCREEN_MAGNIFICATION) &&
120 (availableFunctions_ == availableFunctions) && ((availableFunctions & FEATURE_SCREEN_TOUCH) == 0)) {
121 return;
122 }
123 availableFunctions_ = availableFunctions;
124
125 if (!eventHandler_) {
126 HILOG_ERROR("eventHandler is empty!");
127 return;
128 }
129 eventHandler_->PostTask([this] {
130 DestroyTransmitters();
131 CreateTransmitters();
132 UpdateInterceptor();
133 });
134 }
135
CreateTransmitters()136 void AccessibilityInputInterceptor::CreateTransmitters()
137 {
138 HILOG_DEBUG("function[%{public}u].", availableFunctions_);
139
140 if (!availableFunctions_) {
141 return;
142 }
143
144 if ((availableFunctions_ & FEATURE_MOUSE_KEY) && (!mouseKey_)) {
145 mouseKey_ = new(std::nothrow) AccessibilityMouseKey();
146 if (mouseKey_) {
147 mouseKey_->SetNext(instance_);
148 }
149 }
150
151 if ((availableFunctions_ & FEATURE_MOUSE_AUTOCLICK) ||
152 (availableFunctions_ & FEATURE_INJECT_TOUCH_EVENTS) ||
153 (availableFunctions_ & FEATURE_TOUCH_EXPLORATION) ||
154 (availableFunctions_ & FEATURE_SCREEN_MAGNIFICATION) ||
155 (availableFunctions_ & FEATURE_SCREEN_TOUCH)) {
156 CreatePointerEventTransmitters();
157 }
158
159 if (availableFunctions_ & FEATURE_FILTER_KEY_EVENTS) {
160 CreateKeyEventTransmitters();
161 }
162 }
163
CreatePointerEventTransmitters()164 void AccessibilityInputInterceptor::CreatePointerEventTransmitters()
165 {
166 HILOG_DEBUG();
167
168 sptr<EventTransmission> header = nullptr;
169 sptr<EventTransmission> current = nullptr;
170
171 if (availableFunctions_& FEATURE_MOUSE_AUTOCLICK) {
172 sptr<AccessibilityMouseAutoclick> mouseAutoclick = new(std::nothrow) AccessibilityMouseAutoclick();
173 if (!mouseAutoclick) {
174 HILOG_ERROR("mouseAutoclick is null");
175 return;
176 }
177 SetNextEventTransmitter(header, current, mouseAutoclick);
178 }
179
180 if (availableFunctions_& FEATURE_INJECT_TOUCH_EVENTS) {
181 sptr<TouchEventInjector> touchEventInjector = new(std::nothrow) TouchEventInjector();
182 if (!touchEventInjector) {
183 HILOG_ERROR("touchEventInjector is null");
184 return;
185 }
186 SetNextEventTransmitter(header, current, touchEventInjector);
187 Singleton<AccessibleAbilityManagerService>::GetInstance().SetTouchEventInjector(touchEventInjector);
188 }
189
190 if (availableFunctions_& FEATURE_SCREEN_MAGNIFICATION) {
191 sptr<AccessibilityZoomGesture> zoomGesture = new(std::nothrow) AccessibilityZoomGesture();
192 if (!zoomGesture) {
193 HILOG_ERROR("zoomGesture is null");
194 return;
195 }
196 SetNextEventTransmitter(header, current, zoomGesture);
197 }
198
199 if (availableFunctions_& FEATURE_TOUCH_EXPLORATION) {
200 sptr<TouchExploration> touchExploration = new(std::nothrow) TouchExploration();
201 if (!touchExploration) {
202 HILOG_ERROR("touchExploration is null");
203 return;
204 }
205 touchExploration->StartUp();
206 SetNextEventTransmitter(header, current, touchExploration);
207 }
208
209 if ((availableFunctions_ & FEATURE_SCREEN_TOUCH) && ((availableFunctions_ & FEATURE_TOUCH_EXPLORATION) == 0)) {
210 sptr<AccessibilityScreenTouch> screenTouch = new(std::nothrow) AccessibilityScreenTouch();
211 if (!screenTouch) {
212 HILOG_ERROR("screenTouch is null");
213 return;
214 }
215 SetNextEventTransmitter(header, current, screenTouch);
216 }
217
218 SetNextEventTransmitter(header, current, instance_);
219 pointerEventTransmitters_ = header;
220 }
221
CreateKeyEventTransmitters()222 void AccessibilityInputInterceptor::CreateKeyEventTransmitters()
223 {
224 HILOG_DEBUG();
225
226 sptr<EventTransmission> header = nullptr;
227 sptr<EventTransmission> current = nullptr;
228
229 if (availableFunctions_& FEATURE_FILTER_KEY_EVENTS) {
230 sptr<KeyEventFilter> keyEventFilter = new(std::nothrow) KeyEventFilter();
231 if (!keyEventFilter) {
232 HILOG_ERROR("keyEventFilter is null");
233 return;
234 }
235 Singleton<AccessibleAbilityManagerService>::GetInstance().SetKeyEventFilter(keyEventFilter);
236 SetNextEventTransmitter(header, current, keyEventFilter);
237 }
238
239 SetNextEventTransmitter(header, current, instance_);
240 keyEventTransmitters_ = header;
241 }
242
UpdateInterceptor()243 void AccessibilityInputInterceptor::UpdateInterceptor()
244 {
245 std::lock_guard<ffrt::mutex> lock(mutex_);
246 HILOG_DEBUG();
247 if (!inputManager_) {
248 HILOG_ERROR("inputManger is null.");
249 return;
250 }
251
252 if (interceptorId_ >= 0) {
253 inputManager_->RemoveInterceptor(interceptorId_);
254 interceptorId_ = -1;
255 }
256
257 if ((availableFunctions_ & FEATURE_MOUSE_AUTOCLICK) ||
258 (availableFunctions_ & FEATURE_TOUCH_EXPLORATION) ||
259 (availableFunctions_ & FEATURE_SCREEN_MAGNIFICATION) ||
260 (availableFunctions_ & FEATURE_MOUSE_KEY) ||
261 (availableFunctions_ & FEATURE_SCREEN_TOUCH)) {
262 inputEventConsumer_ = std::make_shared<AccessibilityInputEventConsumer>();
263 interceptorId_ = inputManager_->AddInterceptor(inputEventConsumer_);
264 } else if (availableFunctions_ & FEATURE_FILTER_KEY_EVENTS) {
265 inputEventConsumer_ = std::make_shared<AccessibilityInputEventConsumer>();
266 interceptorId_ = inputManager_->AddInterceptor(inputEventConsumer_, PRIORITY_EVENT,
267 MMI::CapabilityToTags(MMI::INPUT_DEV_CAP_KEYBOARD));
268 }
269 HILOG_INFO("interceptorId:%{public}d", interceptorId_);
270 }
271
DestroyInterceptor()272 void AccessibilityInputInterceptor::DestroyInterceptor()
273 {
274 HILOG_DEBUG("interceptorId:%{public}d.", interceptorId_);
275
276 if (!inputManager_) {
277 HILOG_ERROR("inputManager_ is null.");
278 return;
279 }
280 if (interceptorId_ >= 0) {
281 inputManager_->RemoveInterceptor(interceptorId_);
282 }
283 interceptorId_ = -1;
284 }
285
DestroyTransmitters()286 void AccessibilityInputInterceptor::DestroyTransmitters()
287 {
288 std::lock_guard<ffrt::mutex> lock(mutex_);
289 HILOG_DEBUG();
290
291 if ((availableFunctions_ & FEATURE_MOUSE_KEY) != FEATURE_MOUSE_KEY) {
292 if (mouseKey_) {
293 mouseKey_->DestroyEvents();
294 mouseKey_ = nullptr;
295 }
296 }
297
298 if (pointerEventTransmitters_ != nullptr) {
299 pointerEventTransmitters_->DestroyEvents();
300 Singleton<AccessibleAbilityManagerService>::GetInstance().SetTouchEventInjector(nullptr);
301 pointerEventTransmitters_= nullptr;
302 }
303 if (keyEventTransmitters_ != nullptr) {
304 keyEventTransmitters_->DestroyEvents();
305 Singleton<AccessibleAbilityManagerService>::GetInstance().SetKeyEventFilter(nullptr);
306 keyEventTransmitters_ = nullptr;
307 }
308 }
309
ProcessPointerEvent(std::shared_ptr<MMI::PointerEvent> event)310 void AccessibilityInputInterceptor::ProcessPointerEvent(std::shared_ptr<MMI::PointerEvent> event)
311 {
312 std::lock_guard<ffrt::mutex> lock(mutex_);
313 HILOG_DEBUG();
314
315 if (mouseKey_) {
316 mouseKey_->OnPointerEvent(*event);
317 }
318
319 if (!pointerEventTransmitters_) {
320 HILOG_DEBUG("pointerEventTransmitters_ is empty.");
321 const_cast<AccessibilityInputInterceptor*>(this)->OnPointerEvent(*event);
322 return;
323 }
324
325 pointerEventTransmitters_->OnPointerEvent(*event);
326 }
327
ProcessKeyEvent(std::shared_ptr<MMI::KeyEvent> event)328 void AccessibilityInputInterceptor::ProcessKeyEvent(std::shared_ptr<MMI::KeyEvent> event)
329 {
330 std::lock_guard<ffrt::mutex> lock(mutex_);
331 HILOG_DEBUG();
332
333 if (mouseKey_) {
334 bool result = mouseKey_->OnKeyEvent(*event);
335 if (result) {
336 HILOG_DEBUG("The event is mouse key event.");
337 return;
338 }
339 }
340
341 if (!keyEventTransmitters_) {
342 HILOG_DEBUG("keyEventTransmitters_ is empty.");
343 const_cast<AccessibilityInputInterceptor*>(this)->OnKeyEvent(*event);
344 return;
345 }
346
347 keyEventTransmitters_->OnKeyEvent(*event);
348 }
349
SetNextEventTransmitter(sptr<EventTransmission> & header,sptr<EventTransmission> & current,const sptr<EventTransmission> & next)350 void AccessibilityInputInterceptor::SetNextEventTransmitter(sptr<EventTransmission> &header,
351 sptr<EventTransmission> ¤t, const sptr<EventTransmission> &next)
352 {
353 HILOG_DEBUG();
354
355 if (current != nullptr) {
356 current->SetNext(next);
357 } else {
358 header = next;
359 }
360 current = next;
361 }
362
AccessibilityInputEventConsumer()363 AccessibilityInputEventConsumer::AccessibilityInputEventConsumer()
364 {
365 HILOG_DEBUG();
366 eventHandler_ = std::make_shared<AppExecFwk::EventHandler>(
367 Singleton<AccessibleAbilityManagerService>::GetInstance().GetInputManagerRunner());
368 #ifdef ACCESSIBILITY_WATCH_FEATURE
369 eventHandler_->PostTask([] {
370 auto pid = getpid();
371 auto tid = gettid();
372 uint32_t qosLevel = 7; // set thread qos to RT
373 std::string strBundleName = "accessibility";
374 std::string strPid = std::to_string(pid);
375 std::string strTid = std::to_string(tid);
376 std::string strQos = std::to_string(qosLevel);
377 std::unordered_map<std::string, std::string> mapPayLoad;
378 mapPayLoad["pid"] = strPid;
379 mapPayLoad[strTid] = strQos;
380 mapPayLoad["bundleName"] = strBundleName;
381 uint32_t type = OHOS::ResourceSchedule::ResType::RES_TYPE_THREAD_QOS_CHANGE;
382 OHOS::ResourceSchedule::ResSchedClient::GetInstance().ReportData(type, 0, mapPayLoad);
383 });
384 #endif // ACCESSIBILITY_WATCH_FEATURE
385 }
386
~AccessibilityInputEventConsumer()387 AccessibilityInputEventConsumer::~AccessibilityInputEventConsumer()
388 {
389 HILOG_DEBUG();
390
391 eventHandler_ = nullptr;
392 }
393
OnInputEvent(std::shared_ptr<MMI::KeyEvent> keyEvent) const394 void AccessibilityInputEventConsumer::OnInputEvent(std::shared_ptr<MMI::KeyEvent> keyEvent) const
395 {
396 HILOG_DEBUG();
397 if (!keyEvent) {
398 HILOG_WARN("keyEvent is null.");
399 return;
400 }
401
402 auto interceptor = AccessibilityInputInterceptor::GetInstance();
403 if (!interceptor) {
404 HILOG_ERROR("interceptor is null.");
405 return;
406 }
407
408 if (!eventHandler_) {
409 HILOG_ERROR("eventHandler is empty.");
410 return;
411 }
412
413 auto task = [keyEvent, interceptor] {interceptor->ProcessKeyEvent(keyEvent);};
414 eventHandler_->PostTask(task, "InputKeyEvent");
415 }
416
OnInputEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent) const417 void AccessibilityInputEventConsumer::OnInputEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent) const
418 {
419 if (!pointerEvent) {
420 HILOG_WARN("pointerEvent is null.");
421 return;
422 }
423
424 if (pointerEvent->GetPointerAction() != MMI::PointerEvent::POINTER_ACTION_MOVE) {
425 HILOG_INFO("PointerAction:%{public}d, SourceType:%{public}d, PointerId:%{public}d.",
426 pointerEvent->GetPointerAction(), pointerEvent->GetSourceType(), pointerEvent->GetPointerId());
427 } else {
428 HILOG_DEBUG("PointerAction:%{public}d, SourceType:%{public}d, PointerId:%{public}d.",
429 pointerEvent->GetPointerAction(), pointerEvent->GetSourceType(), pointerEvent->GetPointerId());
430 }
431
432 auto interceptor = AccessibilityInputInterceptor::GetInstance();
433 if (!interceptor) {
434 HILOG_ERROR("interceptor is null.");
435 return;
436 }
437
438 if (!eventHandler_) {
439 HILOG_ERROR("eventHandler is empty.");
440 return;
441 }
442 auto task = [pointerEvent, interceptor] {interceptor->ProcessPointerEvent(pointerEvent);};
443 eventHandler_->PostTask(task, "InputPointerEvent");
444 }
445 } // namespace Accessibility
446 } // namespace OHOS