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 
36 namespace OHOS {
37 namespace Msdp {
38 namespace DeviceStatus {
39 namespace {
40 constexpr int32_t MAXIMUM_LEVEL_ALLOWED { 3 };
41 int32_t g_absMaxWidth { 720 };
42 int32_t g_absMaxHeight { 1280 };
43 constexpr int32_t ABS_PRESSURE_MAX { 100 };
44 constexpr int32_t ABS_MT_ORIENTATION_MIN { -90 };
45 constexpr int32_t ABS_MT_ORIENTATION_MAX { 90 };
46 constexpr int32_t ABS_MT_BLOB_ID_MAX { 10 };
47 constexpr int32_t ABS_MT_TRACKING_ID_MAX { 9 };
48 constexpr int32_t ABS_TOOL_TYPE_MAX { 15 };
49 constexpr int32_t SY_OFFSET { 1 };
50 constexpr int32_t TX_OFFSET { 2 };
51 constexpr int32_t TY_OFFSET { 3 };
52 constexpr uint32_t IO_FLAG_WIDTH { 6 };
53 constexpr int32_t DEFAULT_VALUE_MINUS_ONE { -1 };
54 constexpr int32_t DEFAULT_VALUE_ZERO { 0 };
55 } // namespace
56 
57 class PointerEventMonitor final : public MMI::IInputEventConsumer {
58 public:
59     PointerEventMonitor() = default;
60     ~PointerEventMonitor() = default;
61 
OnInputEvent(std::shared_ptr<MMI::KeyEvent> keyEvent) const62     void OnInputEvent(std::shared_ptr<MMI::KeyEvent> keyEvent) const override {};
63     void OnInputEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent) const override;
OnInputEvent(std::shared_ptr<MMI::AxisEvent> axisEvent) const64     void OnInputEvent(std::shared_ptr<MMI::AxisEvent> axisEvent) const override {};
65 };
66 
OnInputEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent) const67 void 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 
VirtualTouchScreenBuilder()82 VirtualTouchScreenBuilder::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 
GetDeviceName()117 std::string VirtualTouchScreenBuilder::GetDeviceName()
118 {
119     return std::string("Virtual TouchScreen");
120 }
121 
ShowUsage()122 void 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 
Mount()140 void 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 
Unmount()170 void VirtualTouchScreenBuilder::Unmount()
171 {
172     CALL_DEBUG_ENTER;
173     VirtualDeviceBuilder::Unmount("touchscreen", "T");
174 }
175 
Clone()176 void 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 
Monitor()217 void 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 
Act(int32_t argc,char * argv[])233 void 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 
ReadDownAction(int32_t argc,char * argv[])276 void 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 
ReadMoveAction(int32_t argc,char * argv[])297 void 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 
ReadUpAction()320 void 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 
ReadMoveToAction(int32_t argc,char * argv[])334 void 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 
ReadDragToAction(int32_t argc,char * argv[])355 void 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 
ReadActions(const char * path)384 void 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 
ReadModel(const nlohmann::json & model,int32_t level)396 void 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 
ReadAction(const nlohmann::json & model)411 void 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 
GetModelValue(const nlohmann::json & model,const std::string & targetName,int32_t defaultValue)434 int32_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 
HandleDown(const nlohmann::json & model)444 void 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 
HandleMove(const nlohmann::json & model)456 void 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 
HandleUp(const nlohmann::json & model)468 void 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 
HandleMoveTo(const nlohmann::json & model)476 void 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 
HandleWait(const nlohmann::json & model)488 void 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 
ReadRawInput(const char * path)498 void 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 
ReadRawModel(const nlohmann::json & model,int32_t level)510 void 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 
ReadRawData(const nlohmann::json & model)530 void 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