1 /*
2 * Copyright (c) 2023-2024 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 "touchpad_event_fragment_mgr.h"
17
18 #include <linux/input.h>
19
20 #include "dinput_log.h"
21 #include "dinput_utils_tool.h"
22
23 namespace OHOS {
24 namespace DistributedHardware {
25 namespace DistributedInput {
IsPositionEvent(const RawEvent & event)26 bool TouchPadEventFragmentMgr::IsPositionEvent(const RawEvent &event)
27 {
28 if (event.type == EV_ABS && (event.code == ABS_MT_POSITION_X || event.code == ABS_MT_POSITION_Y ||
29 event.code == ABS_X || event.code == ABS_Y)) {
30 return true;
31 }
32
33 return false;
34 }
35
IsSynEvent(const RawEvent & event)36 bool TouchPadEventFragmentMgr::IsSynEvent(const RawEvent &event)
37 {
38 return event.type == EV_SYN && event.code == SYN_REPORT;
39 }
40
IsWholeTouchFragments(const std::vector<TouchPadEventFragment> & events)41 bool TouchPadEventFragmentMgr::IsWholeTouchFragments(const std::vector<TouchPadEventFragment> &events)
42 {
43 return events.front().IsTouchPadOptStart() && events.back().IsTouchPadOptFinish();
44 }
45
PushEvent(const std::string & dhId,const RawEvent & event)46 std::pair<bool, std::vector<RawEvent>> TouchPadEventFragmentMgr::PushEvent(const std::string &dhId,
47 const RawEvent &event)
48 {
49 if (IsPositionEvent(event)) {
50 return {false, {}};
51 }
52 std::lock_guard<std::mutex> lock(fragmentsMtx_);
53 if (fragments_.find(dhId) == fragments_.end()) {
54 fragments_[dhId] = {{}};
55 }
56
57 fragments_[dhId].back().PushEvent(event);
58 if (IsSynEvent(event)) {
59 return DealSynEvent(dhId);
60 }
61 return {false, {}};
62 }
63
DealSynEvent(const std::string & dhId)64 std::pair<bool, std::vector<RawEvent>> TouchPadEventFragmentMgr::DealSynEvent(const std::string &dhId)
65 {
66 if (fragments_[dhId].back().IsTouchPadOptFinish()) {
67 bool needSim = false;
68 std::vector<RawEvent> allEvents = {};
69 if (!IsWholeTouchFragments(fragments_[dhId])) {
70 // If not whole touch events, this means the down event occurs on the other device,
71 // so we need simulate the up actions to the other side to reset the touchpad states.
72 for (auto &frag : fragments_[dhId]) {
73 std::vector<RawEvent> fragEvents = frag.GetEvents();
74 allEvents.insert(allEvents.end(), fragEvents.begin(), fragEvents.end());
75 }
76 needSim = true;
77 DHLOGI("Find NOT Whole touchpad events need send back, dhId: %{public}s", GetAnonyString(dhId).c_str());
78 }
79 fragments_[dhId].clear();
80 fragments_[dhId].push_back({});
81 return {needSim, allEvents};
82 }
83
84 if (fragments_[dhId].back().IsShouldDrop()) {
85 fragments_[dhId].pop_back();
86 }
87 fragments_[dhId].push_back({});
88 return {false, {}};
89 }
90
Clear(const std::string & dhId)91 void TouchPadEventFragmentMgr::Clear(const std::string &dhId)
92 {
93 std::lock_guard<std::mutex> lock(fragmentsMtx_);
94 fragments_.erase(dhId);
95 }
96
GetAndClearEvents(const std::string & dhId)97 std::vector<RawEvent> TouchPadEventFragmentMgr::GetAndClearEvents(const std::string &dhId)
98 {
99 std::lock_guard<std::mutex> lock(fragmentsMtx_);
100 std::vector<RawEvent> allEvents;
101 if (fragments_.find(dhId) == fragments_.end()) {
102 return {};
103 }
104
105 for (auto &frag : fragments_[dhId]) {
106 std::vector<RawEvent> fragEvents = frag.GetEvents();
107 allEvents.insert(allEvents.end(), fragEvents.begin(), fragEvents.end());
108 }
109
110 fragments_.erase(dhId);
111 return allEvents;
112 }
113 } // namespace DistributedInput
114 } // namespace DistributedHardware
115 } // namespace OHOS