1a3e0fd82Sopenharmony_ci/*
2a3e0fd82Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3a3e0fd82Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4a3e0fd82Sopenharmony_ci * you may not use this file except in compliance with the License.
5a3e0fd82Sopenharmony_ci * You may obtain a copy of the License at
6a3e0fd82Sopenharmony_ci *
7a3e0fd82Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8a3e0fd82Sopenharmony_ci *
9a3e0fd82Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10a3e0fd82Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11a3e0fd82Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12a3e0fd82Sopenharmony_ci * See the License for the specific language governing permissions and
13a3e0fd82Sopenharmony_ci * limitations under the License.
14a3e0fd82Sopenharmony_ci */
15a3e0fd82Sopenharmony_ci
16a3e0fd82Sopenharmony_ci#include "dfx/event_injector.h"
17a3e0fd82Sopenharmony_ci#if ENABLE_DEBUG
18a3e0fd82Sopenharmony_ci#include "common/input_device_manager.h"
19a3e0fd82Sopenharmony_ci#include "dfx/key_event_injector.h"
20a3e0fd82Sopenharmony_ci#include "dfx/point_event_injector.h"
21a3e0fd82Sopenharmony_ci#include "gfx_utils/graphic_log.h"
22a3e0fd82Sopenharmony_ci
23a3e0fd82Sopenharmony_cinamespace OHOS {
24a3e0fd82Sopenharmony_ciEventInjector::~EventInjector()
25a3e0fd82Sopenharmony_ci{
26a3e0fd82Sopenharmony_ci    InputDeviceManager* inputDeviceManager = InputDeviceManager::GetInstance();
27a3e0fd82Sopenharmony_ci    if (pointEventInjector_ != nullptr) {
28a3e0fd82Sopenharmony_ci        inputDeviceManager->Remove(pointEventInjector_);
29a3e0fd82Sopenharmony_ci        delete pointEventInjector_;
30a3e0fd82Sopenharmony_ci        pointEventInjector_ = nullptr;
31a3e0fd82Sopenharmony_ci    }
32a3e0fd82Sopenharmony_ci    if (keyEventInjector_ != nullptr) {
33a3e0fd82Sopenharmony_ci        inputDeviceManager->Remove(keyEventInjector_);
34a3e0fd82Sopenharmony_ci        delete keyEventInjector_;
35a3e0fd82Sopenharmony_ci        keyEventInjector_ = nullptr;
36a3e0fd82Sopenharmony_ci    }
37a3e0fd82Sopenharmony_ci}
38a3e0fd82Sopenharmony_ci
39a3e0fd82Sopenharmony_ciEventInjector* EventInjector::GetInstance()
40a3e0fd82Sopenharmony_ci{
41a3e0fd82Sopenharmony_ci    static EventInjector instance;
42a3e0fd82Sopenharmony_ci    return &instance;
43a3e0fd82Sopenharmony_ci}
44a3e0fd82Sopenharmony_ci
45a3e0fd82Sopenharmony_cibool EventInjector::RegisterEventInjector(EventDataType type)
46a3e0fd82Sopenharmony_ci{
47a3e0fd82Sopenharmony_ci    switch (type) {
48a3e0fd82Sopenharmony_ci        case EventDataType::POINT_TYPE:
49a3e0fd82Sopenharmony_ci            if (pointEventInjector_ == nullptr) {
50a3e0fd82Sopenharmony_ci                pointEventInjector_ = new PointEventInjector();
51a3e0fd82Sopenharmony_ci                if (pointEventInjector_ == nullptr) {
52a3e0fd82Sopenharmony_ci                    GRAPHIC_LOGE("EventInjector::RegisterEventInjector register pointEventInjector failed Err!\n");
53a3e0fd82Sopenharmony_ci                    return false;
54a3e0fd82Sopenharmony_ci                }
55a3e0fd82Sopenharmony_ci                InputDeviceManager::GetInstance()->Add(pointEventInjector_);
56a3e0fd82Sopenharmony_ci            }
57a3e0fd82Sopenharmony_ci            return true;
58a3e0fd82Sopenharmony_ci        case EventDataType::KEY_TYPE:
59a3e0fd82Sopenharmony_ci            if (keyEventInjector_ == nullptr) {
60a3e0fd82Sopenharmony_ci                keyEventInjector_ = new KeyEventInjector();
61a3e0fd82Sopenharmony_ci                if (keyEventInjector_ == nullptr) {
62a3e0fd82Sopenharmony_ci                    GRAPHIC_LOGE("EventInjector::RegisterEventInjector register keyEventInjector failed Err!\n");
63a3e0fd82Sopenharmony_ci                    return false;
64a3e0fd82Sopenharmony_ci                }
65a3e0fd82Sopenharmony_ci                InputDeviceManager::GetInstance()->Add(keyEventInjector_);
66a3e0fd82Sopenharmony_ci            }
67a3e0fd82Sopenharmony_ci            return true;
68a3e0fd82Sopenharmony_ci        default:
69a3e0fd82Sopenharmony_ci            break;
70a3e0fd82Sopenharmony_ci    }
71a3e0fd82Sopenharmony_ci    return false;
72a3e0fd82Sopenharmony_ci}
73a3e0fd82Sopenharmony_ci
74a3e0fd82Sopenharmony_civoid EventInjector::UnregisterEventInjector(EventDataType type)
75a3e0fd82Sopenharmony_ci{
76a3e0fd82Sopenharmony_ci    switch (type) {
77a3e0fd82Sopenharmony_ci        case EventDataType::POINT_TYPE:
78a3e0fd82Sopenharmony_ci            if (pointEventInjector_ != nullptr) {
79a3e0fd82Sopenharmony_ci                InputDeviceManager::GetInstance()->Remove(pointEventInjector_);
80a3e0fd82Sopenharmony_ci                delete pointEventInjector_;
81a3e0fd82Sopenharmony_ci                pointEventInjector_ = nullptr;
82a3e0fd82Sopenharmony_ci            }
83a3e0fd82Sopenharmony_ci            break;
84a3e0fd82Sopenharmony_ci        case EventDataType::KEY_TYPE:
85a3e0fd82Sopenharmony_ci            if (keyEventInjector_ != nullptr) {
86a3e0fd82Sopenharmony_ci                InputDeviceManager::GetInstance()->Remove(keyEventInjector_);
87a3e0fd82Sopenharmony_ci                delete keyEventInjector_;
88a3e0fd82Sopenharmony_ci                keyEventInjector_ = nullptr;
89a3e0fd82Sopenharmony_ci            }
90a3e0fd82Sopenharmony_ci            break;
91a3e0fd82Sopenharmony_ci        default:
92a3e0fd82Sopenharmony_ci            break;
93a3e0fd82Sopenharmony_ci    }
94a3e0fd82Sopenharmony_ci}
95a3e0fd82Sopenharmony_ci
96a3e0fd82Sopenharmony_cibool EventInjector::IsEventInjectorRegistered(EventDataType type) const
97a3e0fd82Sopenharmony_ci{
98a3e0fd82Sopenharmony_ci    switch (type) {
99a3e0fd82Sopenharmony_ci        case EventDataType::POINT_TYPE:
100a3e0fd82Sopenharmony_ci            if (pointEventInjector_ != nullptr) {
101a3e0fd82Sopenharmony_ci                return true;
102a3e0fd82Sopenharmony_ci            }
103a3e0fd82Sopenharmony_ci            break;
104a3e0fd82Sopenharmony_ci        case EventDataType::KEY_TYPE:
105a3e0fd82Sopenharmony_ci            if (keyEventInjector_ != nullptr) {
106a3e0fd82Sopenharmony_ci                return true;
107a3e0fd82Sopenharmony_ci            }
108a3e0fd82Sopenharmony_ci            break;
109a3e0fd82Sopenharmony_ci        default:
110a3e0fd82Sopenharmony_ci            break;
111a3e0fd82Sopenharmony_ci    }
112a3e0fd82Sopenharmony_ci    return false;
113a3e0fd82Sopenharmony_ci}
114a3e0fd82Sopenharmony_ci
115a3e0fd82Sopenharmony_cibool EventInjector::SetInjectEvent(const DeviceData* dataArray, uint16_t arrayLength, EventDataType type)
116a3e0fd82Sopenharmony_ci{
117a3e0fd82Sopenharmony_ci    if (dataArray == nullptr) {
118a3e0fd82Sopenharmony_ci        return false;
119a3e0fd82Sopenharmony_ci    }
120a3e0fd82Sopenharmony_ci    switch (type) {
121a3e0fd82Sopenharmony_ci        case EventDataType::POINT_TYPE:
122a3e0fd82Sopenharmony_ci            if (pointEventInjector_ == nullptr) {
123a3e0fd82Sopenharmony_ci                return false;
124a3e0fd82Sopenharmony_ci            }
125a3e0fd82Sopenharmony_ci            for (uint16_t i = 0; i < arrayLength; i++) {
126a3e0fd82Sopenharmony_ci                if (!pointEventInjector_->SetPointEvent(dataArray[i])) {
127a3e0fd82Sopenharmony_ci                    return false;
128a3e0fd82Sopenharmony_ci                }
129a3e0fd82Sopenharmony_ci            }
130a3e0fd82Sopenharmony_ci            break;
131a3e0fd82Sopenharmony_ci        case EventDataType::KEY_TYPE:
132a3e0fd82Sopenharmony_ci            if (keyEventInjector_ == nullptr) {
133a3e0fd82Sopenharmony_ci                return false;
134a3e0fd82Sopenharmony_ci            }
135a3e0fd82Sopenharmony_ci            for (uint16_t i = 0; i < arrayLength; i++) {
136a3e0fd82Sopenharmony_ci                if (!keyEventInjector_->SetKey(dataArray[i])) {
137a3e0fd82Sopenharmony_ci                    return false;
138a3e0fd82Sopenharmony_ci                }
139a3e0fd82Sopenharmony_ci            }
140a3e0fd82Sopenharmony_ci            break;
141a3e0fd82Sopenharmony_ci        default:
142a3e0fd82Sopenharmony_ci            return false;
143a3e0fd82Sopenharmony_ci    }
144a3e0fd82Sopenharmony_ci    return true;
145a3e0fd82Sopenharmony_ci}
146a3e0fd82Sopenharmony_ci
147a3e0fd82Sopenharmony_cibool EventInjector::SetClickEvent(const Point& clickPoint)
148a3e0fd82Sopenharmony_ci{
149a3e0fd82Sopenharmony_ci    uint16_t clickArrayLen = 2; /* 2:click event point */
150a3e0fd82Sopenharmony_ci    if (clickArrayLen > pointEventInjector_->GetLeftSize()) {
151a3e0fd82Sopenharmony_ci        GRAPHIC_LOGE("front points need to be read.(left size in pointer queue is not enough)");
152a3e0fd82Sopenharmony_ci        return false;
153a3e0fd82Sopenharmony_ci    }
154a3e0fd82Sopenharmony_ci    bool setResult = true;
155a3e0fd82Sopenharmony_ci    DeviceData* dataArray = new DeviceData[clickArrayLen];
156a3e0fd82Sopenharmony_ci    if (dataArray == nullptr) {
157a3e0fd82Sopenharmony_ci        return false;
158a3e0fd82Sopenharmony_ci    }
159a3e0fd82Sopenharmony_ci    dataArray[0].point = clickPoint;
160a3e0fd82Sopenharmony_ci    dataArray[0].state = InputDevice::STATE_PRESS;
161a3e0fd82Sopenharmony_ci    dataArray[1].point = clickPoint;
162a3e0fd82Sopenharmony_ci    dataArray[1].state = InputDevice::STATE_RELEASE;
163a3e0fd82Sopenharmony_ci    if (!SetInjectEvent(dataArray, clickArrayLen, EventDataType::POINT_TYPE)) {
164a3e0fd82Sopenharmony_ci        setResult = false;
165a3e0fd82Sopenharmony_ci    }
166a3e0fd82Sopenharmony_ci    delete[] dataArray;
167a3e0fd82Sopenharmony_ci    return setResult;
168a3e0fd82Sopenharmony_ci}
169a3e0fd82Sopenharmony_ci
170a3e0fd82Sopenharmony_cibool EventInjector::SetLongPressEvent(const Point& longPressPoint)
171a3e0fd82Sopenharmony_ci{
172a3e0fd82Sopenharmony_ci    uint16_t pointCount = INDEV_LONG_PRESS_TIME / INDEV_READ_PERIOD + 1;
173a3e0fd82Sopenharmony_ci    if (pointCount > pointEventInjector_->GetLeftSize()) {
174a3e0fd82Sopenharmony_ci        GRAPHIC_LOGE("front points need to be read.(left size in pointer queue is not enough)");
175a3e0fd82Sopenharmony_ci        return false;
176a3e0fd82Sopenharmony_ci    }
177a3e0fd82Sopenharmony_ci    bool setResult = true;
178a3e0fd82Sopenharmony_ci    DeviceData* dataArray = new DeviceData[pointCount];
179a3e0fd82Sopenharmony_ci    if (dataArray == nullptr) {
180a3e0fd82Sopenharmony_ci        return false;
181a3e0fd82Sopenharmony_ci    }
182a3e0fd82Sopenharmony_ci    for (uint16_t i = 0; i < pointCount; i++) {
183a3e0fd82Sopenharmony_ci        dataArray[i].point = longPressPoint;
184a3e0fd82Sopenharmony_ci        dataArray[i].state = InputDevice::STATE_PRESS;
185a3e0fd82Sopenharmony_ci    }
186a3e0fd82Sopenharmony_ci    dataArray[pointCount - 1].state = InputDevice::STATE_RELEASE;
187a3e0fd82Sopenharmony_ci    if (!SetInjectEvent(dataArray, pointCount, EventDataType::POINT_TYPE)) {
188a3e0fd82Sopenharmony_ci        setResult = false;
189a3e0fd82Sopenharmony_ci    }
190a3e0fd82Sopenharmony_ci    delete[] dataArray;
191a3e0fd82Sopenharmony_ci    return setResult;
192a3e0fd82Sopenharmony_ci}
193a3e0fd82Sopenharmony_ci
194a3e0fd82Sopenharmony_cibool EventInjector::SetDragEvent(const Point& startPoint, const Point& endPoint, uint32_t dragTime)
195a3e0fd82Sopenharmony_ci{
196a3e0fd82Sopenharmony_ci    uint16_t pointCount = (dragTime / INDEV_READ_PERIOD) + 1;
197a3e0fd82Sopenharmony_ci    /* 3: at least 3 points in drag event */
198a3e0fd82Sopenharmony_ci    if (pointCount < 3) {
199a3e0fd82Sopenharmony_ci        GRAPHIC_LOGE("dragTime is too short.(drag event needs at least 3 points)");
200a3e0fd82Sopenharmony_ci        return false;
201a3e0fd82Sopenharmony_ci    }
202a3e0fd82Sopenharmony_ci    if (pointCount > pointEventInjector_->GetLeftSize()) {
203a3e0fd82Sopenharmony_ci        GRAPHIC_LOGE("dragTime is too long or front points need to be read.(left size in pointer queue is not enough)");
204a3e0fd82Sopenharmony_ci        return false;
205a3e0fd82Sopenharmony_ci    }
206a3e0fd82Sopenharmony_ci    bool setResult = true;
207a3e0fd82Sopenharmony_ci    int16_t negativeFlag = 1; /* 1:represent the coordinate (x, y) of endPoint is larger than startPoint. */
208a3e0fd82Sopenharmony_ci    DeviceData* dataArray = new DeviceData[pointCount];
209a3e0fd82Sopenharmony_ci    if (dataArray == nullptr) {
210a3e0fd82Sopenharmony_ci        return false;
211a3e0fd82Sopenharmony_ci    }
212a3e0fd82Sopenharmony_ci    if (startPoint.x == endPoint.x) {
213a3e0fd82Sopenharmony_ci        float pointStep = static_cast<float>(MATH_ABS(endPoint.y - startPoint.y)) / (pointCount - 1);
214a3e0fd82Sopenharmony_ci        if (endPoint.y < startPoint.y) {
215a3e0fd82Sopenharmony_ci            negativeFlag = -1; /* -1:represent the coordinate y of endPoint is smaller than startPoint. */
216a3e0fd82Sopenharmony_ci        }
217a3e0fd82Sopenharmony_ci        for (uint16_t i = 0; i < pointCount; i++) {
218a3e0fd82Sopenharmony_ci            dataArray[i].point.x = startPoint.x;
219a3e0fd82Sopenharmony_ci            dataArray[i].point.y = startPoint.y + static_cast<int16_t>(i * negativeFlag * pointStep);
220a3e0fd82Sopenharmony_ci            dataArray[i].state = InputDevice::STATE_PRESS;
221a3e0fd82Sopenharmony_ci        }
222a3e0fd82Sopenharmony_ci    } else {
223a3e0fd82Sopenharmony_ci        float slope = static_cast<float>(endPoint.y - startPoint.y) / (endPoint.x - startPoint.x);
224a3e0fd82Sopenharmony_ci        int16_t constPara = startPoint.y - static_cast<int16_t>(slope * startPoint.x);
225a3e0fd82Sopenharmony_ci        float pointStep = static_cast<float>(MATH_ABS(endPoint.x - startPoint.x)) / (pointCount - 1);
226a3e0fd82Sopenharmony_ci        if (endPoint.x < startPoint.x) {
227a3e0fd82Sopenharmony_ci            negativeFlag = -1; /* -1:represent the coordinate x of endPoint is smaller than startPoint. */
228a3e0fd82Sopenharmony_ci        }
229a3e0fd82Sopenharmony_ci        for (uint16_t i = 0; i < pointCount; i++) {
230a3e0fd82Sopenharmony_ci            dataArray[i].point.x = startPoint.x + static_cast<int16_t>(i * negativeFlag * pointStep);
231a3e0fd82Sopenharmony_ci            dataArray[i].point.y = static_cast<int16_t>(slope * (dataArray[i].point.x)) + constPara;
232a3e0fd82Sopenharmony_ci            dataArray[i].state = InputDevice::STATE_PRESS;
233a3e0fd82Sopenharmony_ci        }
234a3e0fd82Sopenharmony_ci    }
235a3e0fd82Sopenharmony_ci    dataArray[pointCount - 1].point = endPoint;
236a3e0fd82Sopenharmony_ci    dataArray[pointCount - 1].state = InputDevice::STATE_RELEASE;
237a3e0fd82Sopenharmony_ci    if (!SetInjectEvent(dataArray, pointCount, EventDataType::POINT_TYPE)) {
238a3e0fd82Sopenharmony_ci        setResult = false;
239a3e0fd82Sopenharmony_ci    }
240a3e0fd82Sopenharmony_ci    delete[] dataArray;
241a3e0fd82Sopenharmony_ci    return setResult;
242a3e0fd82Sopenharmony_ci}
243a3e0fd82Sopenharmony_ci
244a3e0fd82Sopenharmony_cibool EventInjector::SetKeyEvent(uint16_t keyId, uint16_t state)
245a3e0fd82Sopenharmony_ci{
246a3e0fd82Sopenharmony_ci    uint16_t kevArrayLen = 1;
247a3e0fd82Sopenharmony_ci    if (kevArrayLen > keyEventInjector_->GetLeftSize()) {
248a3e0fd82Sopenharmony_ci        GRAPHIC_LOGE("front key event need to be read.(left size in key event queue is not enough)");
249a3e0fd82Sopenharmony_ci        return false;
250a3e0fd82Sopenharmony_ci    }
251a3e0fd82Sopenharmony_ci    bool setResult = true;
252a3e0fd82Sopenharmony_ci    DeviceData* dataArray = new DeviceData[kevArrayLen];
253a3e0fd82Sopenharmony_ci    if (dataArray == nullptr) {
254a3e0fd82Sopenharmony_ci        return false;
255a3e0fd82Sopenharmony_ci    }
256a3e0fd82Sopenharmony_ci    for (uint16_t i = 0; i < kevArrayLen; i++) {
257a3e0fd82Sopenharmony_ci        dataArray[i].keyId = keyId;
258a3e0fd82Sopenharmony_ci        dataArray[i].state = state;
259a3e0fd82Sopenharmony_ci    }
260a3e0fd82Sopenharmony_ci    if (!SetInjectEvent(dataArray, kevArrayLen, EventDataType::KEY_TYPE)) {
261a3e0fd82Sopenharmony_ci        setResult = false;
262a3e0fd82Sopenharmony_ci    }
263a3e0fd82Sopenharmony_ci    delete[] dataArray;
264a3e0fd82Sopenharmony_ci    return setResult;
265a3e0fd82Sopenharmony_ci}
266a3e0fd82Sopenharmony_ci
267a3e0fd82Sopenharmony_ci#if ENABLE_WINDOW
268a3e0fd82Sopenharmony_civoid EventInjector::SetWindowId(uint8_t windowId)
269a3e0fd82Sopenharmony_ci{
270a3e0fd82Sopenharmony_ci    if (pointEventInjector_ != nullptr) {
271a3e0fd82Sopenharmony_ci        pointEventInjector_->SetWindowId(windowId);
272a3e0fd82Sopenharmony_ci    }
273a3e0fd82Sopenharmony_ci}
274a3e0fd82Sopenharmony_ci#endif
275a3e0fd82Sopenharmony_ci} // namespace OHOS
276a3e0fd82Sopenharmony_ci#endif // ENABLE_DEBUG