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
25namespace OHOS {
26namespace MMI {
27namespace {
28constexpr int32_t TIME_WAIT_FOR_EVENT { 1000 };
29constexpr int32_t SEC_TO_NANOSEC { 1000000000 };
30} // namespace
31
32void 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
43void 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
60void 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
71void 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
81void 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
91void 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
101void 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
111void 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
121void 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
127void 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
133uint64_t WindowEventConsumer::GetConsumerThreadId()
134{
135    return threadId_;
136}
137
138EventUtilTest::EventUtilTest() {}
139EventUtilTest::~EventUtilTest() {}
140
141void 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
154std::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
172bool 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
190std::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
240std::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
264bool 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
279bool 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
294int64_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
301void 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