1f857971dSopenharmony_ci/*
2f857971dSopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
3f857971dSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4f857971dSopenharmony_ci * you may not use this file except in compliance with the License.
5f857971dSopenharmony_ci * You may obtain a copy of the License at
6f857971dSopenharmony_ci *
7f857971dSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8f857971dSopenharmony_ci *
9f857971dSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10f857971dSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11f857971dSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12f857971dSopenharmony_ci * See the License for the specific language governing permissions and
13f857971dSopenharmony_ci * limitations under the License.
14f857971dSopenharmony_ci */
15f857971dSopenharmony_ci
16f857971dSopenharmony_ci#include "virtual_touchscreen_builder.h"
17f857971dSopenharmony_ci
18f857971dSopenharmony_ci#include <fstream>
19f857971dSopenharmony_ci#include <iostream>
20f857971dSopenharmony_ci#include <unordered_map>
21f857971dSopenharmony_ci
22f857971dSopenharmony_ci#include <getopt.h>
23f857971dSopenharmony_ci#include <linux/input.h>
24f857971dSopenharmony_ci
25f857971dSopenharmony_ci#include "input_manager.h"
26f857971dSopenharmony_ci
27f857971dSopenharmony_ci#include "devicestatus_define.h"
28f857971dSopenharmony_ci#include "display_manager.h"
29f857971dSopenharmony_ci#include "fi_log.h"
30f857971dSopenharmony_ci#include "utility.h"
31f857971dSopenharmony_ci#include "virtual_touchscreen.h"
32f857971dSopenharmony_ci
33f857971dSopenharmony_ci#undef LOG_TAG
34f857971dSopenharmony_ci#define LOG_TAG "VirtualTouchScreenBuilder"
35f857971dSopenharmony_ci
36f857971dSopenharmony_cinamespace OHOS {
37f857971dSopenharmony_cinamespace Msdp {
38f857971dSopenharmony_cinamespace DeviceStatus {
39f857971dSopenharmony_cinamespace {
40f857971dSopenharmony_ciconstexpr int32_t MAXIMUM_LEVEL_ALLOWED { 3 };
41f857971dSopenharmony_ciint32_t g_absMaxWidth { 720 };
42f857971dSopenharmony_ciint32_t g_absMaxHeight { 1280 };
43f857971dSopenharmony_ciconstexpr int32_t ABS_PRESSURE_MAX { 100 };
44f857971dSopenharmony_ciconstexpr int32_t ABS_MT_ORIENTATION_MIN { -90 };
45f857971dSopenharmony_ciconstexpr int32_t ABS_MT_ORIENTATION_MAX { 90 };
46f857971dSopenharmony_ciconstexpr int32_t ABS_MT_BLOB_ID_MAX { 10 };
47f857971dSopenharmony_ciconstexpr int32_t ABS_MT_TRACKING_ID_MAX { 9 };
48f857971dSopenharmony_ciconstexpr int32_t ABS_TOOL_TYPE_MAX { 15 };
49f857971dSopenharmony_ciconstexpr int32_t SY_OFFSET { 1 };
50f857971dSopenharmony_ciconstexpr int32_t TX_OFFSET { 2 };
51f857971dSopenharmony_ciconstexpr int32_t TY_OFFSET { 3 };
52f857971dSopenharmony_ciconstexpr uint32_t IO_FLAG_WIDTH { 6 };
53f857971dSopenharmony_ciconstexpr int32_t DEFAULT_VALUE_MINUS_ONE { -1 };
54f857971dSopenharmony_ciconstexpr int32_t DEFAULT_VALUE_ZERO { 0 };
55f857971dSopenharmony_ci} // namespace
56f857971dSopenharmony_ci
57f857971dSopenharmony_ciclass PointerEventMonitor final : public MMI::IInputEventConsumer {
58f857971dSopenharmony_cipublic:
59f857971dSopenharmony_ci    PointerEventMonitor() = default;
60f857971dSopenharmony_ci    ~PointerEventMonitor() = default;
61f857971dSopenharmony_ci
62f857971dSopenharmony_ci    void OnInputEvent(std::shared_ptr<MMI::KeyEvent> keyEvent) const override {};
63f857971dSopenharmony_ci    void OnInputEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent) const override;
64f857971dSopenharmony_ci    void OnInputEvent(std::shared_ptr<MMI::AxisEvent> axisEvent) const override {};
65f857971dSopenharmony_ci};
66f857971dSopenharmony_ci
67f857971dSopenharmony_civoid PointerEventMonitor::OnInputEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent) const
68f857971dSopenharmony_ci{
69f857971dSopenharmony_ci    CHKPV(pointerEvent);
70f857971dSopenharmony_ci    if (pointerEvent->GetSourceType() != MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN) {
71f857971dSopenharmony_ci        return;
72f857971dSopenharmony_ci    }
73f857971dSopenharmony_ci    MMI::PointerEvent::PointerItem pointerItem;
74f857971dSopenharmony_ci    if (!pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), pointerItem)) {
75f857971dSopenharmony_ci        return;
76f857971dSopenharmony_ci    }
77f857971dSopenharmony_ci    std::cout << "\rcurrent touch position - x: " << std::setw(IO_FLAG_WIDTH) << std::left
78f857971dSopenharmony_ci        << pointerItem.GetDisplayX() << "y: " << pointerItem.GetDisplayY() << "            ";
79f857971dSopenharmony_ci    std::cout.flush();
80f857971dSopenharmony_ci}
81f857971dSopenharmony_ci
82f857971dSopenharmony_ciVirtualTouchScreenBuilder::VirtualTouchScreenBuilder() : VirtualDeviceBuilder(GetDeviceName(), BUS_USB, 0x6006, 0x6006)
83f857971dSopenharmony_ci{
84f857971dSopenharmony_ci    sptr<Rosen::Display> display = Rosen::DisplayManager::GetInstance().GetDisplayById(0);
85f857971dSopenharmony_ci    CHKPV(display);
86f857971dSopenharmony_ci    g_absMaxWidth = display->GetWidth();
87f857971dSopenharmony_ci    g_absMaxHeight = display->GetHeight();
88f857971dSopenharmony_ci    AbsInfo absInfos[] { { ABS_X, 0, g_absMaxWidth, 0, 0 },
89f857971dSopenharmony_ci    { ABS_Y, 0, g_absMaxHeight, 0, 0 },
90f857971dSopenharmony_ci    { ABS_PRESSURE, 0, ABS_PRESSURE_MAX, 0, 0 },
91f857971dSopenharmony_ci    { ABS_MT_TOUCH_MAJOR, 0, 1, 0, 0 },
92f857971dSopenharmony_ci    { ABS_MT_TOUCH_MINOR, 0, 1, 0, 0 },
93f857971dSopenharmony_ci    { ABS_MT_ORIENTATION, ABS_MT_ORIENTATION_MIN, ABS_MT_ORIENTATION_MAX, 0, 0 },
94f857971dSopenharmony_ci    { ABS_MT_POSITION_X, 0, g_absMaxWidth, 0, 0 },
95f857971dSopenharmony_ci    { ABS_MT_POSITION_Y, 0, g_absMaxHeight, 0, 0 },
96f857971dSopenharmony_ci    { ABS_MT_BLOB_ID, 0, ABS_MT_BLOB_ID_MAX, 0, 0 },
97f857971dSopenharmony_ci    { ABS_MT_TRACKING_ID, 0, ABS_MT_TRACKING_ID_MAX, 0, 0 },
98f857971dSopenharmony_ci    { ABS_MT_PRESSURE, 0, ABS_PRESSURE_MAX, 0, 0 },
99f857971dSopenharmony_ci    { ABS_MT_TOOL_TYPE, 0, ABS_TOOL_TYPE_MAX, 0, 0 },
100f857971dSopenharmony_ci    { ABS_MT_WIDTH_MAJOR, 0, 1, 0, 0 },
101f857971dSopenharmony_ci    { ABS_MT_WIDTH_MINOR, 0, 1, 0, 0 },
102f857971dSopenharmony_ci    { ABS_MT_TOOL_X, 0, g_absMaxWidth, 0, 0 },
103f857971dSopenharmony_ci    { ABS_MT_TOOL_Y, 0, 1, 0, 0 } };
104f857971dSopenharmony_ci
105f857971dSopenharmony_ci    eventTypes_ = { EV_ABS, EV_KEY };
106f857971dSopenharmony_ci    properties_ = { INPUT_PROP_DIRECT };
107f857971dSopenharmony_ci    keys_ = { BTN_TOUCH, BTN_TOOL_RUBBER, BTN_TOOL_BRUSH, BTN_TOOL_PENCIL, BTN_TOOL_AIRBRUSH,
108f857971dSopenharmony_ci            BTN_TOOL_FINGER, BTN_TOOL_MOUSE, BTN_TOOL_LENS };
109f857971dSopenharmony_ci    abs_ = { ABS_X, ABS_Y, ABS_PRESSURE, ABS_MT_TOUCH_MAJOR, ABS_MT_TOUCH_MINOR, ABS_MT_ORIENTATION,
110f857971dSopenharmony_ci            ABS_MT_POSITION_X, ABS_MT_POSITION_Y, ABS_MT_BLOB_ID, ABS_MT_TRACKING_ID, ABS_MT_PRESSURE,
111f857971dSopenharmony_ci            ABS_MT_WIDTH_MAJOR, ABS_MT_WIDTH_MINOR, ABS_MT_TOOL_X, ABS_MT_TOOL_Y, ABS_MT_TOOL_TYPE };
112f857971dSopenharmony_ci    for (const auto &item : absInfos) {
113f857971dSopenharmony_ci        SetAbsValue(item);
114f857971dSopenharmony_ci    }
115f857971dSopenharmony_ci}
116f857971dSopenharmony_ci
117f857971dSopenharmony_cistd::string VirtualTouchScreenBuilder::GetDeviceName()
118f857971dSopenharmony_ci{
119f857971dSopenharmony_ci    return std::string("Virtual TouchScreen");
120f857971dSopenharmony_ci}
121f857971dSopenharmony_ci
122f857971dSopenharmony_civoid VirtualTouchScreenBuilder::ShowUsage()
123f857971dSopenharmony_ci{
124f857971dSopenharmony_ci    std::cout << "Usage: vdevadm act -t T [-d<SLOT>  <x> <y>] [-u<SLOT>] [-m<SLOT> <dx> [<dy>]]" << std::endl;
125f857971dSopenharmony_ci    std::cout << "                        [-M<SLOT> <x> <y>] [-w <ms>] [-f <FILE>] [-r <FILE>] [-c]" << std::endl;
126f857971dSopenharmony_ci    std::cout << "      -d <SLOT> <x> <y>" << std::endl;
127f857971dSopenharmony_ci    std::cout << "                  Press donw on touch screen." << std::endl;
128f857971dSopenharmony_ci    std::cout << "                  The <SLOT> identify one touch and is in the range [0-9]." << std::endl;
129f857971dSopenharmony_ci    std::cout << "      -u <SLOT>   Lift up the touch <SLOT>." << std::endl;
130f857971dSopenharmony_ci    std::cout << "      -m <SLOT> <dx> [<dy>]" << std::endl;
131f857971dSopenharmony_ci    std::cout << "                  Move the touch <SLOT> along (dx, dy) for one step." << std::endl;
132f857971dSopenharmony_ci    std::cout << "      -M <SLOT> <x> <y>" << std::endl;
133f857971dSopenharmony_ci    std::cout << "                  Move the touch <SLOT> to (x, y)." << std::endl;
134f857971dSopenharmony_ci    std::cout << "      -D <SLOT> <sx> <sy> <tx> <ty> Drag the touch <SLOT> to (tx, ty)" << std::endl;
135f857971dSopenharmony_ci    std::cout << "      -w <ms>     Wait for <ms> milliseconds." << std::endl;
136f857971dSopenharmony_ci    std::cout << "      -f <FILE>   Read actions from <FILE>." << std::endl;
137f857971dSopenharmony_ci    std::cout << "      -r <FILE>   Read raw input data from <FILE>." << std::endl;
138f857971dSopenharmony_ci}
139f857971dSopenharmony_ci
140f857971dSopenharmony_civoid VirtualTouchScreenBuilder::Mount()
141f857971dSopenharmony_ci{
142f857971dSopenharmony_ci    CALL_DEBUG_ENTER;
143f857971dSopenharmony_ci    std::cout << "Start to mount virtual touchscreen." << std::endl;
144f857971dSopenharmony_ci    if (VirtualTouchScreen::GetDevice() != nullptr) {
145f857971dSopenharmony_ci        std::cout << "Virtual touchscreen has been mounted." << std::endl;
146f857971dSopenharmony_ci        return;
147f857971dSopenharmony_ci    }
148f857971dSopenharmony_ci    VirtualTouchScreenBuilder vTouch;
149f857971dSopenharmony_ci    if (!vTouch.SetUp()) {
150f857971dSopenharmony_ci        std::cout << "Failed to mount virtual touchscreen." << std::endl;
151f857971dSopenharmony_ci        return;
152f857971dSopenharmony_ci    }
153f857971dSopenharmony_ci
154f857971dSopenharmony_ci    int32_t nTries = 3;
155f857971dSopenharmony_ci    do {
156f857971dSopenharmony_ci        std::this_thread::sleep_for(std::chrono::seconds(1));
157f857971dSopenharmony_ci    } while ((nTries-- > 0) && (VirtualTouchScreen::GetDevice() == nullptr));
158f857971dSopenharmony_ci    if (VirtualTouchScreen::GetDevice() == nullptr) {
159f857971dSopenharmony_ci        std::cout << "Failed to mount virtual touchscreen." << std::endl;
160f857971dSopenharmony_ci        return;
161f857971dSopenharmony_ci    }
162f857971dSopenharmony_ci
163f857971dSopenharmony_ci    std::cout << "Mount virtual touchscreen successfully." << std::endl;
164f857971dSopenharmony_ci    VirtualDeviceBuilder::Daemonize();
165f857971dSopenharmony_ci    for (;;) {
166f857971dSopenharmony_ci        std::this_thread::sleep_for(std::chrono::minutes(1));
167f857971dSopenharmony_ci    }
168f857971dSopenharmony_ci}
169f857971dSopenharmony_ci
170f857971dSopenharmony_civoid VirtualTouchScreenBuilder::Unmount()
171f857971dSopenharmony_ci{
172f857971dSopenharmony_ci    CALL_DEBUG_ENTER;
173f857971dSopenharmony_ci    VirtualDeviceBuilder::Unmount("touchscreen", "T");
174f857971dSopenharmony_ci}
175f857971dSopenharmony_ci
176f857971dSopenharmony_civoid VirtualTouchScreenBuilder::Clone()
177f857971dSopenharmony_ci{
178f857971dSopenharmony_ci    CALL_DEBUG_ENTER;
179f857971dSopenharmony_ci    if (VirtualTouchScreen::GetDevice() != nullptr) {
180f857971dSopenharmony_ci        std::cout << "Virtual touchscreen has been mounted" << std::endl;
181f857971dSopenharmony_ci        return;
182f857971dSopenharmony_ci    }
183f857971dSopenharmony_ci
184f857971dSopenharmony_ci    std::vector<std::shared_ptr<VirtualDevice>> vDevs;
185f857971dSopenharmony_ci    int32_t ret = VirtualDeviceBuilder::ScanFor(
186f857971dSopenharmony_ci        [](std::shared_ptr<VirtualDevice> vDev) { return ((vDev != nullptr) && vDev->IsTouchscreen()); }, vDevs);
187f857971dSopenharmony_ci    if (ret != RET_OK) {
188f857971dSopenharmony_ci        std::cout << "Failed while scanning for touchscreen" << std::endl;
189f857971dSopenharmony_ci        return;
190f857971dSopenharmony_ci    }
191f857971dSopenharmony_ci    auto vDev = VirtualDeviceBuilder::Select(vDevs, "touchscreen");
192f857971dSopenharmony_ci    CHKPV(vDev);
193f857971dSopenharmony_ci
194f857971dSopenharmony_ci    std::cout << "Cloning \'" << vDev->GetName() << "\'." << std::endl;
195f857971dSopenharmony_ci    VirtualDeviceBuilder vBuilder(GetDeviceName(), vDev);
196f857971dSopenharmony_ci    if (!vBuilder.SetUp()) {
197f857971dSopenharmony_ci        std::cout << "Failed to clone \' " << vDev->GetName() << " \'." << std::endl;
198f857971dSopenharmony_ci        return;
199f857971dSopenharmony_ci    }
200f857971dSopenharmony_ci
201f857971dSopenharmony_ci    int32_t nTries = 3;
202f857971dSopenharmony_ci    do {
203f857971dSopenharmony_ci        std::this_thread::sleep_for(std::chrono::seconds(1));
204f857971dSopenharmony_ci    } while ((nTries-- > 0) && (VirtualTouchScreen::GetDevice() == nullptr));
205f857971dSopenharmony_ci    if (VirtualTouchScreen::GetDevice() == nullptr) {
206f857971dSopenharmony_ci        std::cout << "Clone \' " << vDev->GetName() << " \' is unsuccessful." << std::endl;
207f857971dSopenharmony_ci        return;
208f857971dSopenharmony_ci    }
209f857971dSopenharmony_ci
210f857971dSopenharmony_ci    std::cout << "Clone \'" << vDev->GetName() << "\' successfully" << std::endl;
211f857971dSopenharmony_ci    VirtualDeviceBuilder::Daemonize();
212f857971dSopenharmony_ci    for (;;) {
213f857971dSopenharmony_ci        std::this_thread::sleep_for(std::chrono::minutes(1));
214f857971dSopenharmony_ci    }
215f857971dSopenharmony_ci}
216f857971dSopenharmony_ci
217f857971dSopenharmony_civoid VirtualTouchScreenBuilder::Monitor()
218f857971dSopenharmony_ci{
219f857971dSopenharmony_ci    CALL_DEBUG_ENTER;
220f857971dSopenharmony_ci    MMI::InputManager* inputMgr = MMI::InputManager::GetInstance();
221f857971dSopenharmony_ci    CHKPV(inputMgr);
222f857971dSopenharmony_ci    auto monitor = std::make_shared<PointerEventMonitor>();
223f857971dSopenharmony_ci    int32_t monitorId = inputMgr->AddMonitor(monitor);
224f857971dSopenharmony_ci    if (monitorId < 0) {
225f857971dSopenharmony_ci        std::cout << "Failed to add monitor." << std::endl;
226f857971dSopenharmony_ci        return;
227f857971dSopenharmony_ci    }
228f857971dSopenharmony_ci    for (;;) {
229f857971dSopenharmony_ci        std::this_thread::sleep_for(std::chrono::minutes(1));
230f857971dSopenharmony_ci    }
231f857971dSopenharmony_ci}
232f857971dSopenharmony_ci
233f857971dSopenharmony_civoid VirtualTouchScreenBuilder::Act(int32_t argc, char *argv[])
234f857971dSopenharmony_ci{
235f857971dSopenharmony_ci    CALL_DEBUG_ENTER;
236f857971dSopenharmony_ci    int32_t opt = getopt(argc, argv, "d:u:m:M:f:r:w:D:");
237f857971dSopenharmony_ci    if (opt < 0) {
238f857971dSopenharmony_ci        std::cout << "Vdevadm act: required option is missing" << std::endl;
239f857971dSopenharmony_ci        ShowUsage();
240f857971dSopenharmony_ci        return;
241f857971dSopenharmony_ci    }
242f857971dSopenharmony_ci    if (VirtualTouchScreen::GetDevice() == nullptr) {
243f857971dSopenharmony_ci        std::cout << "No virtual touchscreen." << std::endl;
244f857971dSopenharmony_ci        return;
245f857971dSopenharmony_ci    }
246f857971dSopenharmony_ci    do {
247f857971dSopenharmony_ci        {
248f857971dSopenharmony_ci            auto action = ruleTscrnActions_.find(opt);
249f857971dSopenharmony_ci            if (action != ruleTscrnActions_.end()) {
250f857971dSopenharmony_ci                action->second();
251f857971dSopenharmony_ci                continue;
252f857971dSopenharmony_ci            }
253f857971dSopenharmony_ci        }
254f857971dSopenharmony_ci        {
255f857971dSopenharmony_ci            auto action = readTscrnActions_.find(opt);
256f857971dSopenharmony_ci            if (action != readTscrnActions_.end()) {
257f857971dSopenharmony_ci                action->second(optarg);
258f857971dSopenharmony_ci                continue;
259f857971dSopenharmony_ci            }
260f857971dSopenharmony_ci        }
261f857971dSopenharmony_ci        {
262f857971dSopenharmony_ci            auto action = moveTscrnActions_.find(opt);
263f857971dSopenharmony_ci            if (action != moveTscrnActions_.end()) {
264f857971dSopenharmony_ci                action->second(argc, argv);
265f857971dSopenharmony_ci                continue;
266f857971dSopenharmony_ci            }
267f857971dSopenharmony_ci        }
268f857971dSopenharmony_ci        if (opt == 'w') {
269f857971dSopenharmony_ci            VirtualDeviceBuilder::WaitFor(optarg, "touchscreen");
270f857971dSopenharmony_ci        } else {
271f857971dSopenharmony_ci            ShowUsage();
272f857971dSopenharmony_ci        }
273f857971dSopenharmony_ci    } while ((opt = getopt(argc, argv, "d:u:m:M:f:r:w:D:")) >= 0);
274f857971dSopenharmony_ci}
275f857971dSopenharmony_ci
276f857971dSopenharmony_civoid VirtualTouchScreenBuilder::ReadDownAction(int32_t argc, char *argv[])
277f857971dSopenharmony_ci{
278f857971dSopenharmony_ci    CALL_DEBUG_ENTER;
279f857971dSopenharmony_ci    CHKPV(optarg);
280f857971dSopenharmony_ci
281f857971dSopenharmony_ci    if (!Utility::IsInteger(optarg) || (optind < 0) || (optind + 1 >= argc) ||
282f857971dSopenharmony_ci        !Utility::IsInteger(argv[optind]) || !Utility::IsInteger(argv[optind + 1])) {
283f857971dSopenharmony_ci        std::cout << "Require arguments for Option \'-d\'." << std::endl;
284f857971dSopenharmony_ci        ShowUsage();
285f857971dSopenharmony_ci        return;
286f857971dSopenharmony_ci    }
287f857971dSopenharmony_ci    int32_t slot = std::atoi(optarg);
288f857971dSopenharmony_ci    int32_t x = std::atoi(argv[optind]);
289f857971dSopenharmony_ci    int32_t y = std::atoi(argv[optind + 1]);
290f857971dSopenharmony_ci    std::cout << "[touchscreen] down: [" << slot << ", (" << x << "," << y << ")]" << std::endl;
291f857971dSopenharmony_ci    VirtualTouchScreen::GetDevice()->DownButton(slot, x, y);
292f857971dSopenharmony_ci    while ((optind < argc) && Utility::IsInteger(argv[optind])) {
293f857971dSopenharmony_ci        optind++;
294f857971dSopenharmony_ci    }
295f857971dSopenharmony_ci}
296f857971dSopenharmony_ci
297f857971dSopenharmony_civoid VirtualTouchScreenBuilder::ReadMoveAction(int32_t argc, char *argv[])
298f857971dSopenharmony_ci{
299f857971dSopenharmony_ci    CALL_DEBUG_ENTER;
300f857971dSopenharmony_ci    CHKPV(optarg);
301f857971dSopenharmony_ci
302f857971dSopenharmony_ci    if (!Utility::IsInteger(optarg) || (optind < 0) || (optind + 1 >= argc) || !Utility::IsInteger(argv[optind])) {
303f857971dSopenharmony_ci        std::cout << "Invalid arguments for Option \'-m\'." << std::endl;
304f857971dSopenharmony_ci        ShowUsage();
305f857971dSopenharmony_ci        return;
306f857971dSopenharmony_ci    }
307f857971dSopenharmony_ci    int32_t slot = std::atoi(optarg);
308f857971dSopenharmony_ci    int32_t dx = std::atoi(argv[optind]);
309f857971dSopenharmony_ci    int32_t dy = 0;
310f857971dSopenharmony_ci    if ((optind + 1 < argc) && Utility::IsInteger(argv[optind + 1])) {
311f857971dSopenharmony_ci        dy = std::atoi(argv[optind + 1]);
312f857971dSopenharmony_ci    }
313f857971dSopenharmony_ci    std::cout << "[touchscreen] move: [" << slot << ", (" << dx << "," << dy << ")]" << std::endl;
314f857971dSopenharmony_ci    VirtualTouchScreen::GetDevice()->Move(slot, dx, dy);
315f857971dSopenharmony_ci    while ((optind < argc) && Utility::IsInteger(argv[optind])) {
316f857971dSopenharmony_ci        optind++;
317f857971dSopenharmony_ci    }
318f857971dSopenharmony_ci}
319f857971dSopenharmony_ci
320f857971dSopenharmony_civoid VirtualTouchScreenBuilder::ReadUpAction()
321f857971dSopenharmony_ci{
322f857971dSopenharmony_ci    CALL_DEBUG_ENTER;
323f857971dSopenharmony_ci    CHKPV(optarg);
324f857971dSopenharmony_ci    if (!Utility::IsInteger(optarg)) {
325f857971dSopenharmony_ci        std::cout << "Invalid arguments for Option \'-u\'." << std::endl;
326f857971dSopenharmony_ci        ShowUsage();
327f857971dSopenharmony_ci        return;
328f857971dSopenharmony_ci    }
329f857971dSopenharmony_ci    int32_t slot = std::atoi(optarg);
330f857971dSopenharmony_ci    std::cout << "[touchscreen] release: [" << slot << "]" << std::endl;
331f857971dSopenharmony_ci    VirtualTouchScreen::GetDevice()->UpButton(slot);
332f857971dSopenharmony_ci}
333f857971dSopenharmony_ci
334f857971dSopenharmony_civoid VirtualTouchScreenBuilder::ReadMoveToAction(int32_t argc, char *argv[])
335f857971dSopenharmony_ci{
336f857971dSopenharmony_ci    CALL_DEBUG_ENTER;
337f857971dSopenharmony_ci    CHKPV(optarg);
338f857971dSopenharmony_ci
339f857971dSopenharmony_ci    if (!Utility::IsInteger(optarg) || (optind < 0) || (optind + 1 >= argc) || !Utility::IsInteger(argv[optind]) ||
340f857971dSopenharmony_ci        !Utility::IsInteger(argv[optind + 1])) {
341f857971dSopenharmony_ci        std::cout << "Invalid arguments for Option \'-M\'." << std::endl;
342f857971dSopenharmony_ci        ShowUsage();
343f857971dSopenharmony_ci        return;
344f857971dSopenharmony_ci    }
345f857971dSopenharmony_ci    int32_t slot = std::atoi(optarg);
346f857971dSopenharmony_ci    int32_t x = std::atoi(argv[optind]);
347f857971dSopenharmony_ci    int32_t y = std::atoi(argv[optind + 1]);
348f857971dSopenharmony_ci    std::cout << "[touchscreen] move-to: [" << slot << ", (" << x << "," << y << ")]" << std::endl;
349f857971dSopenharmony_ci    VirtualTouchScreen::GetDevice()->MoveTo(slot, x, y);
350f857971dSopenharmony_ci    while ((optind < argc) && Utility::IsInteger(argv[optind])) {
351f857971dSopenharmony_ci        optind++;
352f857971dSopenharmony_ci    }
353f857971dSopenharmony_ci}
354f857971dSopenharmony_ci
355f857971dSopenharmony_civoid VirtualTouchScreenBuilder::ReadDragToAction(int32_t argc, char *argv[])
356f857971dSopenharmony_ci{
357f857971dSopenharmony_ci    CALL_DEBUG_ENTER;
358f857971dSopenharmony_ci    CHKPV(optarg);
359f857971dSopenharmony_ci    if (!Utility::IsInteger(optarg) || (optind < 0) || (optind + TY_OFFSET >= argc) ||
360f857971dSopenharmony_ci        !Utility::IsInteger(argv[optind]) || !Utility::IsInteger(argv[optind + SY_OFFSET]) ||
361f857971dSopenharmony_ci        !Utility::IsInteger(argv[optind + TX_OFFSET]) || !Utility::IsInteger(argv[optind + TY_OFFSET])) {
362f857971dSopenharmony_ci        std::cout << "Invalid arguments for Option \'-D\'." << std::endl;
363f857971dSopenharmony_ci        ShowUsage();
364f857971dSopenharmony_ci        return;
365f857971dSopenharmony_ci    }
366f857971dSopenharmony_ci
367f857971dSopenharmony_ci    int32_t slot = std::atoi(optarg);
368f857971dSopenharmony_ci    int32_t sx = std::atoi(argv[optind]);
369f857971dSopenharmony_ci    int32_t sy = std::atoi(argv[optind + SY_OFFSET]);
370f857971dSopenharmony_ci    int32_t tx = std::atoi(argv[optind + TX_OFFSET]);
371f857971dSopenharmony_ci    int32_t ty = std::atoi(argv[optind + TY_OFFSET]);
372f857971dSopenharmony_ci
373f857971dSopenharmony_ci    std::cout << "[touchscreen] drag-to: [" << slot << ", (" << tx << "," << ty << ")]" << std::endl;
374f857971dSopenharmony_ci    auto vTouch = VirtualTouchScreen::GetDevice();
375f857971dSopenharmony_ci    vTouch->DownButton(slot, sx, sy);
376f857971dSopenharmony_ci    VirtualDeviceBuilder::WaitFor("touchscreen", SLEEP_TIME);
377f857971dSopenharmony_ci    vTouch->MoveTo(slot, tx, ty);
378f857971dSopenharmony_ci    vTouch->UpButton(slot);
379f857971dSopenharmony_ci    while ((optind < argc) && Utility::IsInteger(argv[optind])) {
380f857971dSopenharmony_ci        optind++;
381f857971dSopenharmony_ci    }
382f857971dSopenharmony_ci}
383f857971dSopenharmony_ci
384f857971dSopenharmony_civoid VirtualTouchScreenBuilder::ReadActions(const char *path)
385f857971dSopenharmony_ci{
386f857971dSopenharmony_ci    CALL_DEBUG_ENTER;
387f857971dSopenharmony_ci    json model;
388f857971dSopenharmony_ci    int32_t ret = VirtualDeviceBuilder::ReadFile(path, model);
389f857971dSopenharmony_ci    if (ret == RET_ERR) {
390f857971dSopenharmony_ci        FI_HILOGE("Failed to read touchscreen data from the files");
391f857971dSopenharmony_ci        return;
392f857971dSopenharmony_ci    }
393f857971dSopenharmony_ci    ReadModel(model, MAXIMUM_LEVEL_ALLOWED);
394f857971dSopenharmony_ci}
395f857971dSopenharmony_ci
396f857971dSopenharmony_civoid VirtualTouchScreenBuilder::ReadModel(const nlohmann::json &model, int32_t level)
397f857971dSopenharmony_ci{
398f857971dSopenharmony_ci    CALL_DEBUG_ENTER;
399f857971dSopenharmony_ci    if (model.is_object()) {
400f857971dSopenharmony_ci        auto it = model.find("actions");
401f857971dSopenharmony_ci        if (it != model.cend() && it->is_array()) {
402f857971dSopenharmony_ci            std::for_each(it->cbegin(), it->cend(), [](const auto &item) { ReadAction(item); });
403f857971dSopenharmony_ci        }
404f857971dSopenharmony_ci    } else if (model.is_array() && level > 0) {
405f857971dSopenharmony_ci        for (const auto &m : model) {
406f857971dSopenharmony_ci            ReadModel(m, level - 1);
407f857971dSopenharmony_ci        }
408f857971dSopenharmony_ci    }
409f857971dSopenharmony_ci}
410f857971dSopenharmony_ci
411f857971dSopenharmony_civoid VirtualTouchScreenBuilder::ReadAction(const nlohmann::json &model)
412f857971dSopenharmony_ci{
413f857971dSopenharmony_ci    CALL_DEBUG_ENTER;
414f857971dSopenharmony_ci    if (!model.is_object()) {
415f857971dSopenharmony_ci        FI_HILOGD("Not an object");
416f857971dSopenharmony_ci        return;
417f857971dSopenharmony_ci    }
418f857971dSopenharmony_ci    auto it = model.find("action");
419f857971dSopenharmony_ci    if (it != model.cend()) {
420f857971dSopenharmony_ci        static const std::unordered_map<std::string, std::function<void(const nlohmann::json &model)>> actions {
421f857971dSopenharmony_ci            { "down", &HandleDown },
422f857971dSopenharmony_ci            { "move", &HandleMove },
423f857971dSopenharmony_ci            { "up", &HandleUp },
424f857971dSopenharmony_ci            { "move-to", &HandleMoveTo },
425f857971dSopenharmony_ci            { "wait", &HandleWait }
426f857971dSopenharmony_ci        };
427f857971dSopenharmony_ci        auto actionItr = actions.find(it.value());
428f857971dSopenharmony_ci        if (actionItr != actions.cend()) {
429f857971dSopenharmony_ci            actionItr->second(model);
430f857971dSopenharmony_ci        }
431f857971dSopenharmony_ci    }
432f857971dSopenharmony_ci}
433f857971dSopenharmony_ci
434f857971dSopenharmony_ciint32_t VirtualTouchScreenBuilder::GetModelValue(const nlohmann::json &model, const std::string &targetName,
435f857971dSopenharmony_ci    int32_t defaultValue)
436f857971dSopenharmony_ci{
437f857971dSopenharmony_ci    auto it = model.find(targetName);
438f857971dSopenharmony_ci    if (it != model.cend() && it->is_number_integer()) {
439f857971dSopenharmony_ci        return it.value();
440f857971dSopenharmony_ci    }
441f857971dSopenharmony_ci    return defaultValue;
442f857971dSopenharmony_ci}
443f857971dSopenharmony_ci
444f857971dSopenharmony_civoid VirtualTouchScreenBuilder::HandleDown(const nlohmann::json &model)
445f857971dSopenharmony_ci{
446f857971dSopenharmony_ci    int32_t slot = VirtualTouchScreenBuilder::GetModelValue(model, "slot", DEFAULT_VALUE_MINUS_ONE);
447f857971dSopenharmony_ci
448f857971dSopenharmony_ci    int32_t x = VirtualTouchScreenBuilder::GetModelValue(model, "x", DEFAULT_VALUE_MINUS_ONE);
449f857971dSopenharmony_ci
450f857971dSopenharmony_ci    int32_t y = VirtualTouchScreenBuilder::GetModelValue(model, "y", DEFAULT_VALUE_MINUS_ONE);
451f857971dSopenharmony_ci
452f857971dSopenharmony_ci    std::cout << "[touchscreen] down: [" << slot << ", (" << x << "," << y << ")]" << std::endl;
453f857971dSopenharmony_ci    VirtualTouchScreen::GetDevice()->DownButton(slot, x, y);
454f857971dSopenharmony_ci}
455f857971dSopenharmony_ci
456f857971dSopenharmony_civoid VirtualTouchScreenBuilder::HandleMove(const nlohmann::json &model)
457f857971dSopenharmony_ci{
458f857971dSopenharmony_ci    int32_t slot = VirtualTouchScreenBuilder::GetModelValue(model, "slot", DEFAULT_VALUE_MINUS_ONE);
459f857971dSopenharmony_ci
460f857971dSopenharmony_ci    int32_t dx = VirtualTouchScreenBuilder::GetModelValue(model, "dx", DEFAULT_VALUE_ZERO);
461f857971dSopenharmony_ci
462f857971dSopenharmony_ci    int32_t dy = VirtualTouchScreenBuilder::GetModelValue(model, "dy", DEFAULT_VALUE_ZERO);
463f857971dSopenharmony_ci
464f857971dSopenharmony_ci    std::cout << "[touchscreen] move: [" << slot << ", (" << dx << "," << dy << ")]" << std::endl;
465f857971dSopenharmony_ci    VirtualTouchScreen::GetDevice()->Move(slot, dx, dy);
466f857971dSopenharmony_ci}
467f857971dSopenharmony_ci
468f857971dSopenharmony_civoid VirtualTouchScreenBuilder::HandleUp(const nlohmann::json &model)
469f857971dSopenharmony_ci{
470f857971dSopenharmony_ci    int32_t slot = VirtualTouchScreenBuilder::GetModelValue(model, "slot", DEFAULT_VALUE_MINUS_ONE);
471f857971dSopenharmony_ci
472f857971dSopenharmony_ci    std::cout << "[touchscreen] release: [" << slot << "]" << std::endl;
473f857971dSopenharmony_ci    VirtualTouchScreen::GetDevice()->UpButton(slot);
474f857971dSopenharmony_ci}
475f857971dSopenharmony_ci
476f857971dSopenharmony_civoid VirtualTouchScreenBuilder::HandleMoveTo(const nlohmann::json &model)
477f857971dSopenharmony_ci{
478f857971dSopenharmony_ci    int32_t slot = VirtualTouchScreenBuilder::GetModelValue(model, "slot", DEFAULT_VALUE_MINUS_ONE);
479f857971dSopenharmony_ci
480f857971dSopenharmony_ci    int32_t x = VirtualTouchScreenBuilder::GetModelValue(model, "x", DEFAULT_VALUE_MINUS_ONE);
481f857971dSopenharmony_ci
482f857971dSopenharmony_ci    int32_t y = VirtualTouchScreenBuilder::GetModelValue(model, "y", DEFAULT_VALUE_MINUS_ONE);
483f857971dSopenharmony_ci
484f857971dSopenharmony_ci    std::cout << "[touchscreen] move-to: [" << slot << ", (" << x << "," << y << ")]" << std::endl;
485f857971dSopenharmony_ci    VirtualTouchScreen::GetDevice()->MoveTo(slot, x, y);
486f857971dSopenharmony_ci}
487f857971dSopenharmony_ci
488f857971dSopenharmony_civoid VirtualTouchScreenBuilder::HandleWait(const nlohmann::json &model)
489f857971dSopenharmony_ci{
490f857971dSopenharmony_ci    CALL_DEBUG_ENTER;
491f857971dSopenharmony_ci    auto it = model.find("duration");
492f857971dSopenharmony_ci    if (it != model.cend() && it->is_number_integer()) {
493f857971dSopenharmony_ci        int32_t waitTime = it.value();
494f857971dSopenharmony_ci        VirtualDeviceBuilder::WaitFor("touchscreen", waitTime);
495f857971dSopenharmony_ci    }
496f857971dSopenharmony_ci}
497f857971dSopenharmony_ci
498f857971dSopenharmony_civoid VirtualTouchScreenBuilder::ReadRawInput(const char *path)
499f857971dSopenharmony_ci{
500f857971dSopenharmony_ci    CALL_DEBUG_ENTER;
501f857971dSopenharmony_ci    json model;
502f857971dSopenharmony_ci    int32_t ret = VirtualDeviceBuilder::ReadFile(path, model);
503f857971dSopenharmony_ci    if (ret == RET_ERR) {
504f857971dSopenharmony_ci        FI_HILOGE("Failed to read the raw touchscreen data");
505f857971dSopenharmony_ci        return;
506f857971dSopenharmony_ci    }
507f857971dSopenharmony_ci    ReadRawModel(model, MAXIMUM_LEVEL_ALLOWED);
508f857971dSopenharmony_ci}
509f857971dSopenharmony_ci
510f857971dSopenharmony_civoid VirtualTouchScreenBuilder::ReadRawModel(const nlohmann::json &model, int32_t level)
511f857971dSopenharmony_ci{
512f857971dSopenharmony_ci    CALL_DEBUG_ENTER;
513f857971dSopenharmony_ci    if (model.is_object()) {
514f857971dSopenharmony_ci        auto it = model.find("type");
515f857971dSopenharmony_ci        if (it == model.cend() || !it->is_string() || (std::string(it.value()).compare("raw") != 0)) {
516f857971dSopenharmony_ci            std::cout << "Expect raw input data." << std::endl;
517f857971dSopenharmony_ci            return;
518f857971dSopenharmony_ci        }
519f857971dSopenharmony_ci        it = model.find("actions");
520f857971dSopenharmony_ci        if (it != model.cend() && it->is_array()) {
521f857971dSopenharmony_ci            std::for_each(it->cbegin(), it->cend(), [](const auto &item) { ReadRawData(item); });
522f857971dSopenharmony_ci        }
523f857971dSopenharmony_ci    } else if (model.is_array() && level > 0) {
524f857971dSopenharmony_ci        for (const auto &m : model) {
525f857971dSopenharmony_ci            ReadRawModel(m, level - 1);
526f857971dSopenharmony_ci        }
527f857971dSopenharmony_ci    }
528f857971dSopenharmony_ci}
529f857971dSopenharmony_ci
530f857971dSopenharmony_civoid VirtualTouchScreenBuilder::ReadRawData(const nlohmann::json &model)
531f857971dSopenharmony_ci{
532f857971dSopenharmony_ci    CALL_DEBUG_ENTER;
533f857971dSopenharmony_ci    if (!model.is_object()) {
534f857971dSopenharmony_ci        FI_HILOGD("Not an object");
535f857971dSopenharmony_ci        return;
536f857971dSopenharmony_ci    }
537f857971dSopenharmony_ci    auto typeIter = model.find("type");
538f857971dSopenharmony_ci    if (typeIter == model.cend() || !typeIter->is_number_integer()) {
539f857971dSopenharmony_ci        return;
540f857971dSopenharmony_ci    }
541f857971dSopenharmony_ci    auto codeIter = model.find("code");
542f857971dSopenharmony_ci    if (codeIter == model.cend() || !codeIter->is_number_integer()) {
543f857971dSopenharmony_ci        return;
544f857971dSopenharmony_ci    }
545f857971dSopenharmony_ci    auto valueIter = model.find("value");
546f857971dSopenharmony_ci    if (valueIter == model.cend() || !valueIter->is_number_integer()) {
547f857971dSopenharmony_ci        return;
548f857971dSopenharmony_ci    }
549f857971dSopenharmony_ci    std::cout << "[touchscreen] raw input: [" << typeIter.value() << ", " << codeIter.value() << ", " <<
550f857971dSopenharmony_ci        valueIter.value() << "]" << std::endl;
551f857971dSopenharmony_ci    VirtualTouchScreen::GetDevice()->SendEvent(typeIter.value(), codeIter.value(), valueIter.value());
552f857971dSopenharmony_ci}
553f857971dSopenharmony_ci} // namespace DeviceStatus
554f857971dSopenharmony_ci} // namespace Msdp
555f857971dSopenharmony_ci} // namespace OHOS