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