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