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