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