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 "event_util_test.h"
17
18 #include <iomanip>
19
20 #include "mmi_log.h"
21
22 namespace OHOS {
23 namespace MMI {
24 namespace {
25 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, MMI_LOG_DOMAIN, "EventUtilTest" };
26 constexpr int32_t TIME_WAIT_FOR_EVENT = 1000;
27 constexpr int32_t SEC_TO_NANOSEC = 1000000000;
28 } // namespace
29
OnInputEvent(std::shared_ptr<KeyEvent> keyEvent) const30 void InputEventConsumer::OnInputEvent(std::shared_ptr<KeyEvent> keyEvent) const
31 {
32 CALL_DEBUG_ENTER;
33 RECV_FLAG flag = TestUtil->GetRecvFlag();
34 if (flag == RECV_FLAG::RECV_FOCUS || flag == RECV_FLAG::RECV_MARK_CONSUMED) {
35 keyEvent->MarkProcessed();
36 ASSERT_TRUE(keyEvent != nullptr);
37 TestUtil->AddEventDump(TestUtil->DumpInputEvent(keyEvent));
38 }
39 }
40
OnInputEvent(std::shared_ptr<PointerEvent> pointerEvent) const41 void InputEventConsumer::OnInputEvent(std::shared_ptr<PointerEvent> pointerEvent) const
42 {
43 CALL_DEBUG_ENTER;
44 RECV_FLAG flag = TestUtil->GetRecvFlag();
45 if (flag == RECV_FLAG::RECV_FOCUS || flag == RECV_FLAG::RECV_MARK_CONSUMED) {
46 pointerEvent->MarkProcessed();
47 ASSERT_TRUE(pointerEvent != nullptr);
48 auto pointerAction = pointerEvent->GetPointerAction();
49 if (pointerAction != PointerEvent::POINTER_ACTION_ENTER_WINDOW &&
50 pointerAction != PointerEvent::POINTER_ACTION_LEAVE_WINDOW &&
51 pointerAction != PointerEvent::POINTER_ACTION_PULL_IN_WINDOW &&
52 pointerAction != PointerEvent::POINTER_ACTION_PULL_OUT_WINDOW) {
53 TestUtil->AddEventDump(TestUtil->DumpInputEvent(pointerEvent));
54 }
55 }
56 }
57
OnInputEvent(std::shared_ptr<PointerEvent> pointerEvent) const58 void InputEventCallback::OnInputEvent(std::shared_ptr<PointerEvent> pointerEvent) const
59 {
60 CALL_DEBUG_ENTER;
61 if (TestUtil->GetRecvFlag() != RECV_FLAG::RECV_MARK_CONSUMED) {
62 TestUtil->SetRecvFlag(RECV_FLAG::RECV_MONITOR);
63 ASSERT_TRUE(pointerEvent != nullptr);
64 TestUtil->AddEventDump(TestUtil->DumpInputEvent(pointerEvent));
65 lastPointerEventId_ = pointerEvent->GetId();
66 }
67 }
68
OnInputEvent(std::shared_ptr<KeyEvent> keyEvent) const69 void InputEventCallback::OnInputEvent(std::shared_ptr<KeyEvent> keyEvent) const
70 {
71 CALL_DEBUG_ENTER;
72 if (TestUtil->GetRecvFlag() != RECV_FLAG::RECV_MARK_CONSUMED) {
73 TestUtil->SetRecvFlag(RECV_FLAG::RECV_MONITOR);
74 ASSERT_TRUE(keyEvent != nullptr);
75 TestUtil->AddEventDump(TestUtil->DumpInputEvent(keyEvent));
76 }
77 }
78
OnInputEvent(std::shared_ptr<PointerEvent> pointerEvent) const79 void PriorityMiddleCallback::OnInputEvent(std::shared_ptr<PointerEvent> pointerEvent) const
80 {
81 CALL_DEBUG_ENTER;
82 if (TestUtil->GetRecvFlag() != RECV_FLAG::RECV_MARK_CONSUMED) {
83 TestUtil->SetRecvFlag(RECV_FLAG::RECV_INTERCEPT);
84 ASSERT_TRUE(pointerEvent != nullptr);
85 TestUtil->AddEventDump("Call middle interceptor");
86 }
87 }
88
OnInputEvent(std::shared_ptr<KeyEvent> keyEvent) const89 void PriorityMiddleCallback::OnInputEvent(std::shared_ptr<KeyEvent> keyEvent) const
90 {
91 CALL_DEBUG_ENTER;
92 if (TestUtil->GetRecvFlag() != RECV_FLAG::RECV_MARK_CONSUMED) {
93 TestUtil->SetRecvFlag(RECV_FLAG::RECV_INTERCEPT);
94 ASSERT_TRUE(keyEvent != nullptr);
95 TestUtil->AddEventDump("Call middle interceptor");
96 }
97 }
98
OnInputEvent(std::shared_ptr<PointerEvent> pointerEvent) const99 void PriorityHighCallback::OnInputEvent(std::shared_ptr<PointerEvent> pointerEvent) const
100 {
101 CALL_DEBUG_ENTER;
102 if (TestUtil->GetRecvFlag() != RECV_FLAG::RECV_MARK_CONSUMED) {
103 TestUtil->SetRecvFlag(RECV_FLAG::RECV_INTERCEPT);
104 ASSERT_TRUE(pointerEvent != nullptr);
105 TestUtil->AddEventDump("Call high interceptor");
106 }
107 }
108
OnInputEvent(std::shared_ptr<KeyEvent> keyEvent) const109 void PriorityHighCallback::OnInputEvent(std::shared_ptr<KeyEvent> keyEvent) const
110 {
111 CALL_DEBUG_ENTER;
112 if (TestUtil->GetRecvFlag() != RECV_FLAG::RECV_MARK_CONSUMED) {
113 TestUtil->SetRecvFlag(RECV_FLAG::RECV_INTERCEPT);
114 ASSERT_TRUE(keyEvent != nullptr);
115 TestUtil->AddEventDump("Call high interceptor");
116 }
117 }
118
OnInputEvent(std::shared_ptr<KeyEvent> keyEvent) const119 void WindowEventConsumer::OnInputEvent(std::shared_ptr<KeyEvent> keyEvent) const
120 {
121 threadId_ = GetThisThreadId();
122 MMI_HILOGD("Consumer callback keyEvent is threadId:%{public}" PRIu64, threadId_);
123 }
124
OnInputEvent(std::shared_ptr<PointerEvent> pointerEvent) const125 void WindowEventConsumer::OnInputEvent(std::shared_ptr<PointerEvent> pointerEvent) const
126 {
127 threadId_ = GetThisThreadId();
128 MMI_HILOGD("Consumer callback pointerEvent is threadId:%{public}" PRIu64, threadId_);
129 }
130
GetConsumerThreadId()131 uint64_t WindowEventConsumer::GetConsumerThreadId()
132 {
133 return threadId_;
134 }
135
EventUtilTest()136 EventUtilTest::EventUtilTest() {}
~EventUtilTest()137 EventUtilTest::~EventUtilTest() {}
138
AddEventDump(std::string eventDump)139 void EventUtilTest::AddEventDump(std::string eventDump)
140 {
141 CALL_DEBUG_ENTER;
142 std::lock_guard<std::mutex> lockGuard(mutex_);
143 if (eventDump.empty()) {
144 strEventDump_.clear();
145 return;
146 }
147 strEventDump_.push_back(eventDump);
148 MMI_HILOGD("Setting the Dump event, strEventDump_:%{public}s", eventDump.c_str());
149 conditionVariable_.notify_one();
150 }
151
GetEventDump()152 std::string EventUtilTest::GetEventDump()
153 {
154 CALL_DEBUG_ENTER;
155 std::unique_lock<std::mutex> uniqueLock(mutex_);
156 std::string str = "";
157 if (strEventDump_.empty()) {
158 MMI_HILOGD("Waiting for an event to fire");
159 if (conditionVariable_.wait_for(uniqueLock,
160 std::chrono::milliseconds(TIME_WAIT_FOR_EVENT)) == std::cv_status::timeout) {
161 MMI_HILOGD("Timeout");
162 return str;
163 }
164 }
165 str = strEventDump_.front();
166 strEventDump_.pop_front();
167 return str;
168 }
169
Init()170 bool EventUtilTest::Init()
171 {
172 CALL_DEBUG_ENTER;
173 if (!WindowUtilsTest::GetInstance()->DrawTestWindow()) {
174 return false;
175 }
176 sptr<Rosen::Window> window_ = WindowUtilsTest::GetInstance()->GetWindow();
177 CHKPF(window_);
178 auto listener_ = GetPtr<InputEventConsumer>();
179 CHKPF(listener_);
180 const std::string threadTest = "EventUtilTest";
181 auto runner = AppExecFwk::EventRunner::Create(threadTest);
182 CHKPF(runner);
183 auto eventHandler = std::make_shared<AppExecFwk::EventHandler>(runner);
184 MMI::InputManager::GetInstance()->SetWindowInputEventConsumer(listener_, eventHandler);
185 return true;
186 }
187
DumpInputEvent(const std::shared_ptr<PointerEvent> & pointerEvent)188 std::string EventUtilTest::DumpInputEvent(const std::shared_ptr<PointerEvent>& pointerEvent)
189 {
190 const int precision = 2;
191 std::ostringstream ostream;
192 std::vector<int32_t> pointerIds { pointerEvent->GetPointerIds() };
193 std::string str;
194 std::vector<uint8_t> buffer = pointerEvent->GetBuffer();
195 for (const auto& buff : buffer) {
196 str += std::to_string(buff);
197 }
198 ostream << "ClientMsgHandler: in OnPointerEvent"
199 << ",EventType:" << pointerEvent->GetEventType()
200 << ",ActionTime:" << pointerEvent->GetActionTime()
201 << ",Action:" << pointerEvent->GetAction()
202 << ",ActionStartTime:" << pointerEvent->GetActionStartTime()
203 << ",Flag:" << pointerEvent->GetFlag()
204 << ",PointerAction:" << pointerEvent->DumpPointerAction()
205 << ",SourceType:" << pointerEvent->DumpSourceType()
206 << ",ButtonId:" << pointerEvent->GetButtonId()
207 << ",DeviceId:" << pointerEvent->GetDeviceId()
208 << ",VerticalAxisValue:" << std::fixed << std::setprecision(precision)
209 << pointerEvent->GetAxisValue(PointerEvent::AXIS_TYPE_SCROLL_VERTICAL)
210 << ",HorizontalAxisValue:" << std::fixed << std::setprecision(precision)
211 << pointerEvent->GetAxisValue(PointerEvent::AXIS_TYPE_SCROLL_HORIZONTAL)
212 <<",BufferCount:" << buffer.size()
213 <<",Buffer:" << str.c_str();
214 for (const auto &pointerId : pointerIds) {
215 PointerEvent::PointerItem item;
216 if (!pointerEvent->GetPointerItem(pointerId, item)) {
217 MMI_HILOGE("Invalid pointer:%{public}d.", pointerId);
218 return ostream.str();
219 }
220 ostream << ",pointerId:" << pointerId << ",DownTime:" << item.GetDownTime()
221 << ",IsPressed:" << std::boolalpha << item.IsPressed()
222 << ",DisplayX:" << item.GetDisplayX() << ",DisplayY:" << item.GetDisplayY()
223 << ",Width:" << item.GetWidth() << ",Height:" << item.GetHeight()
224 << ",TiltX:" << std::fixed << std::setprecision(precision) << item.GetTiltX()
225 << ",TiltY:" << std::fixed << std::setprecision(precision) << item.GetTiltY()
226 << ",ToolDisplayX:" << item.GetToolDisplayX() << ",ToolDisplayY:" << item.GetToolDisplayY()
227 << ",ToolWindowX:" << item.GetToolWindowX() << ",ToolWindowY:" << item.GetToolWindowY()
228 << ",ToolWidth:" << item.GetToolWidth() << ",ToolHeight:" << item.GetToolHeight()
229 << ",Pressure:" << item.GetPressure() << ",ToolType:" << item.GetToolType()
230 << ",LongAxis:" << item.GetLongAxis() << ",ShortAxis:" << item.GetShortAxis()
231 << ",DeviceId:" << item.GetDeviceId() << ",RawDx:" << item.GetRawDx()
232 << ",RawDy:" << item.GetRawDy();
233 }
234
235 return ostream.str();
236 }
237
DumpInputEvent(const std::shared_ptr<KeyEvent> & keyEvent)238 std::string EventUtilTest::DumpInputEvent(const std::shared_ptr<KeyEvent>& keyEvent)
239 {
240 std::ostringstream strm;
241 strm << "InputManagerTest: in OnKeyEvent"
242 << ", KeyCode:" << keyEvent->GetKeyCode()
243 << ", ActionTime:" << keyEvent->GetActionTime()
244 << ", Action:" << keyEvent->GetAction()
245 << ", ActionStartTime:" << keyEvent->GetActionStartTime()
246 << ", EventType:" << keyEvent->GetEventType()
247 << ", KeyAction:" << keyEvent->GetKeyAction();
248 std::vector<int32_t> pressedKeys = keyEvent->GetPressedKeys();
249 for (const int32_t &key : pressedKeys) {
250 std::optional<KeyEvent::KeyItem> keyItem = keyEvent->GetKeyItem(key);
251 if (!keyItem) {
252 MMI_HILOGE("keyItem is nullopt");
253 return "";
254 }
255 strm << ", KeyCode:" << keyItem->GetKeyCode()
256 << ", DeviceId:" << keyItem->GetDeviceId()
257 << ", Unicode:" << keyItem->GetUnicode();
258 }
259 return strm.str();
260 }
261
CompareDump(const std::shared_ptr<PointerEvent> & pointerEvent)262 bool EventUtilTest::CompareDump(const std::shared_ptr<PointerEvent>& pointerEvent)
263 {
264 CALL_DEBUG_ENTER;
265 std::string before = DumpInputEvent(pointerEvent);
266 MMI_HILOGD("before:%{public}s", before.c_str());
267 InputManager::GetInstance()->SimulateInputEvent(pointerEvent);
268 std::string after = GetEventDump();
269 MMI_HILOGD("after:%{public}s", after.c_str());
270
271 return before == after;
272 }
273
CompareDump(const std::shared_ptr<KeyEvent> & keyEvent)274 bool EventUtilTest::CompareDump(const std::shared_ptr<KeyEvent>& keyEvent)
275 {
276 CALL_DEBUG_ENTER;
277 std::string before = DumpInputEvent(keyEvent);
278 MMI_HILOGD("before:%{public}s", before.c_str());
279 InputManager::GetInstance()->SimulateInputEvent(keyEvent);
280 std::string after = GetEventDump();
281 MMI_HILOGD("after:%{public}s", after.c_str());
282
283 return before == after;
284 }
285
GetNanoTime()286 int64_t GetNanoTime()
287 {
288 struct timespec time = { 0 };
289 clock_gettime(CLOCK_MONOTONIC, &time);
290 return static_cast<int64_t>(time.tv_sec) * SEC_TO_NANOSEC + time.tv_nsec;
291 }
292
DumpWindowData(const std::shared_ptr<PointerEvent> & pointerEvent)293 void DumpWindowData(const std::shared_ptr<PointerEvent>& pointerEvent)
294 {
295 CALL_DEBUG_ENTER;
296 pointerEvent->GetAxes();
297 pointerEvent->GetPressedKeys();
298 pointerEvent->GetPressedButtons();
299 PointerEvent::PointerItem item;
300 item.GetDisplayX();
301 item.GetDisplayY();
302 item.GetTargetWindowId();
303 }
304 } // namespace MMI
305 } // namespace OHOS