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 OPERATIONINTERVAL = 400;
34 const int NUMTWO = 2;
35 std::string g_defaultDir = "/data/local/tmp/wukong/record";
36 std::ofstream g_outFile;
37 int64_t g_timeTemp = -1;
38 struct EventData {
39 int xPosi;
40 int yPosi;
41 int interval = 1;
42 };
43
GetMillisTime()44 int64_t GetMillisTime()
45 {
46 auto timeNow = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now());
47 auto tmp = std::chrono::duration_cast<std::chrono::milliseconds>(timeNow.time_since_epoch());
48 return tmp.count();
49 }
50
split(const std::string & in,const std::string & delim)51 static std::vector<std::string> split(const std::string &in, const std::string &delim)
52 {
53 std::regex reg(delim);
54 std::vector<std::string> res = {std::sregex_token_iterator(in.begin(), in.end(), reg, -1),
55 std::sregex_token_iterator()};
56 return res;
57 }
58
WriteEventHead(std::ofstream & outFile)59 static void WriteEventHead(std::ofstream &outFile)
60 {
61 outFile << "x" << ',';
62 outFile << "y" << ',';
63 outFile << "interval" << std::endl;
64 }
65
WriteEventData(std::ofstream & outFile,const EventData & data)66 static void WriteEventData(std::ofstream &outFile, const EventData &data)
67 {
68 outFile << data.xPosi << ',';
69 outFile << data.yPosi << ',';
70 outFile << data.interval << std::endl;
71 }
72
InitReportFolder()73 bool InitReportFolder()
74 {
75 DIR *rootDir = nullptr;
76 if ((rootDir = opendir(g_defaultDir.c_str())) == nullptr) {
77 int ret = mkdir(g_defaultDir.c_str(), S_IROTH | S_IRWXU | S_IRWXG);
78 if (ret != 0) {
79 std::cerr << "failed to create dir: " << g_defaultDir << std::endl;
80 return false;
81 }
82 } else {
83 closedir(rootDir);
84 }
85 return true;
86 }
87
InitEventRecordFile(std::ofstream & outFile,const std::string & recordName)88 bool InitEventRecordFile(std::ofstream &outFile, const std::string &recordName)
89 {
90 if (!InitReportFolder()) {
91 ERROR_LOG("init folder failed");
92 return false;
93 }
94 std::string filePath = g_defaultDir + "/" + recordName + ".csv";
95 outFile.open(filePath, std::ios_base::out | std::ios_base::trunc);
96 if (!outFile) {
97 ERROR_LOG_STR("Failed to create csv file at: %s", filePath.c_str());
98 return false;
99 }
100 WriteEventHead(outFile);
101 INFO_LOG_STR("The result will be written in csv file at location: %s", filePath.c_str());
102 return true;
103 }
104
ReadEventLine(std::ifstream & inFile)105 ErrCode ReadEventLine(std::ifstream &inFile)
106 {
107 ErrCode result = OHOS::ERR_OK;
108 if (inFile.is_open()) {
109 int xPosi = -1;
110 int yPosi = -1;
111 int interval = -1;
112 bool jumpFlag = true;
113 std::string line;
114 while (std::getline(inFile, line)) {
115 if (jumpFlag) {
116 jumpFlag = !jumpFlag;
117 continue;
118 }
119 std::string delim = ",";
120 auto caseInfo = split(line, 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 inFile.close();
137 }
138 return result;
139 }
140
141 class InputEventCallback : public MMI::IInputEventConsumer {
142 public:
OnInputEvent(std::shared_ptr<MMI::KeyEvent> keyEvent) const143 void OnInputEvent(std::shared_ptr<MMI::KeyEvent> keyEvent) const override
144 {
145 INFO_LOG_STR("keyCode: %d", keyEvent->GetKeyCode());
146 }
OnInputEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent) const147 void OnInputEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent) const override
148 {
149 MMI::PointerEvent::PointerItem item;
150 bool result = pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), item);
151 if (!result) {
152 ERROR_LOG("GetPointerItem Fail");
153 }
154 EventData data {};
155 int64_t currentTime = GetMillisTime();
156 if (g_timeTemp == -1) {
157 g_timeTemp = currentTime;
158 data.interval = INTERVALTIME;
159 } else {
160 data.interval = currentTime - g_timeTemp;
161 if (data.interval < OPERATIONINTERVAL) {
162 return;
163 }
164 g_timeTemp = currentTime;
165 }
166 data.xPosi = item.GetDisplayX();
167 data.yPosi = item.GetDisplayY();
168 WriteEventData(g_outFile, data);
169 INFO_LOG_STR("PointerEvent received. interval: %d xPosi: %d yPosi: %d", data.interval, data.xPosi, data.yPosi);
170 }
OnInputEvent(std::shared_ptr<MMI::AxisEvent> axisEvent) const171 void OnInputEvent(std::shared_ptr<MMI::AxisEvent> axisEvent) const override
172 {
173 }
174 static std::shared_ptr<InputEventCallback> GetPtr();
175 };
176
GetPtr()177 std::shared_ptr<InputEventCallback> InputEventCallback::GetPtr()
178 {
179 return std::make_shared<InputEventCallback>();
180 }
181 } // namespace
RecordInput()182 RecordInput::RecordInput() : InputAction()
183 {
184 }
185
~RecordInput()186 RecordInput::~RecordInput()
187 {
188 }
189
OrderInput(const std::shared_ptr<SpcialTestObject> & specialTestObject)190 ErrCode RecordInput::OrderInput(const std::shared_ptr<SpcialTestObject> &specialTestObject)
191 {
192 int result = ERR_OK;
193 auto recordPtr = std::static_pointer_cast<RecordParam>(specialTestObject);
194 if (recordPtr->recordStatus_) {
195 if (!InitEventRecordFile(g_outFile, recordPtr->recordName_)) {
196 ERROR_LOG("init file failed");
197 specialTestObject->isAllFinished_ = true;
198 return OHOS::ERR_INVALID_VALUE;
199 }
200 auto callBackPtr = InputEventCallback::GetPtr();
201 if (callBackPtr == nullptr) {
202 ERROR_LOG("input callback is nullptr");
203 specialTestObject->isAllFinished_ = true;
204 return OHOS::ERR_INVALID_VALUE;
205 }
206 int32_t id1 = MMI::InputManager::GetInstance()->AddMonitor(callBackPtr);
207 if (id1 == -1) {
208 ERROR_LOG("Startup Failed!");
209 specialTestObject->isAllFinished_ = true;
210 return OHOS::ERR_INVALID_VALUE;
211 }
212 INFO_LOG("Started Recording Successfully...");
213 int flag = getc(stdin);
214 specialTestObject->isAllFinished_ = true;
215 TRACK_LOG_STR("flag: %d", flag);
216 } else {
217 std::ifstream inFile(g_defaultDir + "/" + recordPtr->recordName_ + ".csv");
218 result = ReadEventLine(inFile);
219 if (result != ERR_OK) {
220 WARN_LOG("this input failed");
221 return result;
222 }
223 }
224 return result;
225 }
226 } // namespace WuKong
227 } // namespace OHOS
228