1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "record_input.h"
17
18 #include <ctime>
19 #include <dirent.h>
20 #include <fstream>
21 #include <iostream>
22 #include <regex>
23 #include <sys/stat.h>
24 #include <typeinfo>
25
26 #include "ability_manager_client.h"
27 #include "multimode_manager.h"
28
29 namespace OHOS {
30 namespace WuKong {
31 namespace {
32 const int INTERVALTIME = 1000;
33 const int NUMTWO = 2;
34 std::string g_defaultDir = "/data/local/tmp/wukong/record";
35 std::ofstream g_outFile;
36 int64_t g_timeTemp = -1;
37 struct EventData {
38 int xPosi;
39 int yPosi;
40 int interval = 1;
41 };
42
GetMillisTime()43 int64_t GetMillisTime()
44 {
45 auto timeNow = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now());
46 auto tmp = std::chrono::duration_cast<std::chrono::milliseconds>(timeNow.time_since_epoch());
47 return tmp.count();
48 }
49
split(const std::string & in,const std::string & delim)50 static std::vector<std::string> split(const std::string &in, const std::string &delim)
51 {
52 std::regex reg(delim);
53 std::vector<std::string> res = {std::sregex_token_iterator(in.begin(), in.end(), reg, -1),
54 std::sregex_token_iterator()};
55 return res;
56 }
57
WriteEventHead(std::ofstream & outFile)58 static void WriteEventHead(std::ofstream &outFile)
59 {
60 outFile << "x" << ',';
61 outFile << "y" << ',';
62 outFile << "interval" << std::endl;
63 }
64
WriteEventData(std::ofstream & outFile,const EventData & data)65 static void WriteEventData(std::ofstream &outFile, const EventData &data)
66 {
67 outFile << data.xPosi << ',';
68 outFile << data.yPosi << ',';
69 outFile << data.interval << std::endl;
70 }
71
InitReportFolder()72 bool InitReportFolder()
73 {
74 DIR *rootDir = nullptr;
75 if ((rootDir = opendir(g_defaultDir.c_str())) == nullptr) {
76 int ret = mkdir(g_defaultDir.c_str(), S_IROTH | S_IRWXU | S_IRWXG);
77 if (ret != 0) {
78 std::cerr << "failed to create dir: " << g_defaultDir << std::endl;
79 return false;
80 }
81 } else {
82 closedir(rootDir);
83 }
84 return true;
85 }
86
InitEventRecordFile(std::ofstream & outFile,const std::string & recordName)87 bool InitEventRecordFile(std::ofstream &outFile, const std::string &recordName)
88 {
89 if (!InitReportFolder()) {
90 ERROR_LOG("init folder failed");
91 return false;
92 }
93 std::string filePath = g_defaultDir + "/" + recordName + ".csv";
94 outFile.open(filePath, std::ios_base::out | std::ios_base::trunc);
95 if (!outFile) {
96 ERROR_LOG_STR("Failed to create csv file at: %s", filePath.c_str());
97 return false;
98 }
99 WriteEventHead(outFile);
100 INFO_LOG_STR("The result will be written in csv file at location: %s", filePath.c_str());
101 return true;
102 }
103
ReadEventLine(std::ifstream & inFile)104 ErrCode ReadEventLine(std::ifstream &inFile)
105 {
106 ErrCode result = OHOS::ERR_OK;
107 char buffer[50];
108 int xPosi = -1;
109 int yPosi = -1;
110 int interval = -1;
111 bool jumpFlag = true;
112 while (!inFile.eof()) {
113 inFile >> buffer;
114 if (jumpFlag) {
115 jumpFlag = !jumpFlag;
116 continue;
117 }
118 jumpFlag = !jumpFlag;
119 std::string delim = ",";
120 auto caseInfo = split(buffer, delim);
121 xPosi = std::stoi(caseInfo[0]);
122 yPosi = std::stoi(caseInfo[1]);
123 interval = std::stoi(caseInfo[NUMTWO]);
124 INFO_LOG_STR("Position: (%d,%d) interval: %d", xPosi, yPosi, interval);
125 auto recordTouchInput = MultimodeManager::GetInstance();
126 result = recordTouchInput->PointerInput(xPosi, yPosi, MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN,
127 MMI::PointerEvent::POINTER_ACTION_DOWN);
128 if (result != OHOS::ERR_OK) {
129 ERROR_LOG("input failed");
130 return result;
131 }
132 result = recordTouchInput->PointerInput(xPosi, yPosi, MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN,
133 MMI::PointerEvent::POINTER_ACTION_UP);
134 usleep(interval * INTERVALTIME);
135 }
136 return result;
137 }
138
139 class InputEventCallback : public MMI::IInputEventConsumer {
140 public:
OnInputEvent(std::shared_ptr<MMI::KeyEvent> keyEvent) const141 void OnInputEvent(std::shared_ptr<MMI::KeyEvent> keyEvent) const override
142 {
143 INFO_LOG_STR("keyCode: %d", keyEvent->GetKeyCode());
144 }
OnInputEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent) const145 void OnInputEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent) const override
146 {
147 MMI::PointerEvent::PointerItem item;
148 bool result = pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), item);
149 if (!result) {
150 ERROR_LOG("GetPointerItem Fail");
151 }
152 EventData data {};
153 int64_t currentTime = GetMillisTime();
154 if (g_timeTemp == -1) {
155 g_timeTemp = currentTime;
156 data.interval = INTERVALTIME;
157 } else {
158 data.interval = currentTime - g_timeTemp;
159 g_timeTemp = currentTime;
160 }
161 data.xPosi = item.GetDisplayX();
162 data.yPosi = item.GetDisplayY();
163 WriteEventData(g_outFile, data);
164 INFO_LOG_STR("PointerEvent received. interval: %d xPosi: %d yPosi: %d", data.interval, data.xPosi, data.yPosi);
165 }
OnInputEvent(std::shared_ptr<MMI::AxisEvent> axisEvent) const166 void OnInputEvent(std::shared_ptr<MMI::AxisEvent> axisEvent) const override
167 {
168 }
169 static std::shared_ptr<InputEventCallback> GetPtr();
170 };
171
GetPtr()172 std::shared_ptr<InputEventCallback> InputEventCallback::GetPtr()
173 {
174 return std::make_shared<InputEventCallback>();
175 }
176 } // namespace
RecordInput()177 RecordInput::RecordInput() : InputAction()
178 {
179 }
180
~RecordInput()181 RecordInput::~RecordInput()
182 {
183 }
184
OrderInput(const std::shared_ptr<SpcialTestObject> & specialTestObject)185 ErrCode RecordInput::OrderInput(const std::shared_ptr<SpcialTestObject> &specialTestObject)
186 {
187 int result = ERR_OK;
188 auto recordPtr = std::static_pointer_cast<RecordParam>(specialTestObject);
189 if (recordPtr->recordStatus_) {
190 if (!InitEventRecordFile(g_outFile, recordPtr->recordName_)) {
191 ERROR_LOG("init file failed");
192 specialTestObject->isAllFinished_ = true;
193 return OHOS::ERR_INVALID_VALUE;
194 }
195 auto callBackPtr = InputEventCallback::GetPtr();
196 if (callBackPtr == nullptr) {
197 ERROR_LOG("input callback is nullptr");
198 specialTestObject->isAllFinished_ = true;
199 return OHOS::ERR_INVALID_VALUE;
200 }
201 int32_t id1 = MMI::InputManager::GetInstance()->AddMonitor(callBackPtr);
202 if (id1 == -1) {
203 ERROR_LOG("Startup Failed!");
204 specialTestObject->isAllFinished_ = true;
205 return OHOS::ERR_INVALID_VALUE;
206 }
207 INFO_LOG("Started Recording Successfully...");
208 int flag = getc(stdin);
209 specialTestObject->isAllFinished_ = true;
210 TRACK_LOG_STR("flag: %d", flag);
211 } else {
212 std::ifstream inFile(g_defaultDir + "/" + recordPtr->recordName_ + ".csv");
213 result = ReadEventLine(inFile);
214 if (result != ERR_OK) {
215 WARN_LOG("this input failed");
216 return result;
217 }
218 specialTestObject->isAllFinished_ = true;
219 }
220 return result;
221 }
222 } // namespace WuKong
223 } // namespace OHOS
224