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 inFile.close();
131 return result;
132 }
133 result = recordTouchInput->PointerInput(xPosi, yPosi, MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN,
134 MMI::PointerEvent::POINTER_ACTION_UP);
135 usleep(interval * INTERVALTIME);
136 }
137 inFile.close();
138 }
139 return result;
140 }
141
142 class InputEventCallback : public MMI::IInputEventConsumer {
143 public:
OnInputEvent(std::shared_ptr<MMI::KeyEvent> keyEvent) const144 void OnInputEvent(std::shared_ptr<MMI::KeyEvent> keyEvent) const override
145 {
146 INFO_LOG_STR("keyCode: %d", keyEvent->GetKeyCode());
147 }
OnInputEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent) const148 void OnInputEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent) const override
149 {
150 MMI::PointerEvent::PointerItem item;
151 bool result = pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), item);
152 if (!result) {
153 ERROR_LOG("GetPointerItem Fail");
154 }
155 EventData data {};
156 int64_t currentTime = GetMillisTime();
157 if (g_timeTemp == -1) {
158 g_timeTemp = currentTime;
159 data.interval = INTERVALTIME;
160 } else {
161 data.interval = currentTime - g_timeTemp;
162 if (data.interval < OPERATIONINTERVAL) {
163 return;
164 }
165 g_timeTemp = currentTime;
166 }
167 data.xPosi = item.GetDisplayX();
168 data.yPosi = item.GetDisplayY();
169 WriteEventData(g_outFile, data);
170 INFO_LOG_STR("PointerEvent received. interval: %d xPosi: %d yPosi: %d", data.interval, data.xPosi, data.yPosi);
171 }
OnInputEvent(std::shared_ptr<MMI::AxisEvent> axisEvent) const172 void OnInputEvent(std::shared_ptr<MMI::AxisEvent> axisEvent) const override
173 {
174 }
175 static std::shared_ptr<InputEventCallback> GetPtr();
176 };
177
GetPtr()178 std::shared_ptr<InputEventCallback> InputEventCallback::GetPtr()
179 {
180 return std::make_shared<InputEventCallback>();
181 }
182 } // namespace
RecordInput()183 RecordInput::RecordInput() : InputAction()
184 {
185 }
186
~RecordInput()187 RecordInput::~RecordInput()
188 {
189 }
190
OrderInput(const std::shared_ptr<SpcialTestObject> & specialTestObject)191 ErrCode RecordInput::OrderInput(const std::shared_ptr<SpcialTestObject> &specialTestObject)
192 {
193 int result = ERR_OK;
194 auto recordPtr = std::static_pointer_cast<RecordParam>(specialTestObject);
195 if (recordPtr->recordStatus_) {
196 if (!InitEventRecordFile(g_outFile, recordPtr->recordName_)) {
197 ERROR_LOG("init file failed");
198 specialTestObject->isAllFinished_ = true;
199 return OHOS::ERR_INVALID_VALUE;
200 }
201 auto callBackPtr = InputEventCallback::GetPtr();
202 if (callBackPtr == nullptr) {
203 ERROR_LOG("input callback is nullptr");
204 specialTestObject->isAllFinished_ = true;
205 return OHOS::ERR_INVALID_VALUE;
206 }
207 int32_t id1 = MMI::InputManager::GetInstance()->AddMonitor(callBackPtr);
208 if (id1 == -1) {
209 ERROR_LOG("Startup Failed!");
210 specialTestObject->isAllFinished_ = true;
211 return OHOS::ERR_INVALID_VALUE;
212 }
213 INFO_LOG("Started Recording Successfully...");
214 int flag = getc(stdin);
215 specialTestObject->isAllFinished_ = true;
216 TRACK_LOG_STR("flag: %d", flag);
217 } else {
218 std::ifstream inFile(g_defaultDir + "/" + recordPtr->recordName_ + ".csv");
219 result = ReadEventLine(inFile);
220 if (result != ERR_OK) {
221 WARN_LOG("this input failed");
222 return result;
223 }
224 }
225 return result;
226 }
227 } // namespace WuKong
228 } // namespace OHOS
229