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 "input_event_transmission/input_event_builder.h"
17
18 #include "display_info.h"
19
20 #include "cooperate_context.h"
21 #include "devicestatus_define.h"
22 #include "input_event_transmission/input_event_serialization.h"
23 #include "utility.h"
24
25 #undef LOG_TAG
26 #define LOG_TAG "InputEventBuilder"
27
28 namespace OHOS {
29 namespace Msdp {
30 namespace DeviceStatus {
31 namespace Cooperate {
32 namespace {
33 constexpr size_t LOG_PERIOD { 10 };
34 constexpr int32_t DEFAULT_SCREEN_WIDTH { 512 };
35 }
36
InputEventBuilder(IContext * env)37 InputEventBuilder::InputEventBuilder(IContext *env)
38 : env_(env)
39 {
40 observer_ = std::make_shared<DSoftbusObserver>(*this);
41 pointerEvent_ = MMI::PointerEvent::Create();
42 keyEvent_ = MMI::KeyEvent::Create();
43 }
44
~InputEventBuilder()45 InputEventBuilder::~InputEventBuilder()
46 {
47 Disable();
48 }
49
Enable(Context & context)50 void InputEventBuilder::Enable(Context &context)
51 {
52 CALL_INFO_TRACE;
53 if (enable_) {
54 return;
55 }
56 enable_ = true;
57 xDir_ = 0;
58 movement_ = 0;
59 freezing_ = (context.CooperateFlag() & COOPERATE_FLAG_FREEZE_CURSOR);
60 remoteNetworkId_ = context.Peer();
61 env_->GetDSoftbus().AddObserver(observer_);
62 Coordinate cursorPos = context.CursorPosition();
63 FI_HILOGI("Cursor transite in (%{public}d, %{public}d)", cursorPos.x, cursorPos.y);
64 }
65
Disable()66 void InputEventBuilder::Disable()
67 {
68 CALL_INFO_TRACE;
69 if (enable_) {
70 enable_ = false;
71 env_->GetDSoftbus().RemoveObserver(observer_);
72 ResetPressedEvents();
73 }
74 }
75
Update(Context & context)76 void InputEventBuilder::Update(Context &context)
77 {
78 remoteNetworkId_ = context.Peer();
79 FI_HILOGI("Update peer to \'%{public}s\'", Utility::Anonymize(remoteNetworkId_).c_str());
80 }
81
Freeze()82 void InputEventBuilder::Freeze()
83 {
84 if (!enable_) {
85 return;
86 }
87 xDir_ = 0;
88 movement_ = 0;
89 freezing_ = true;
90 FI_HILOGI("Freeze remote input from '%{public}s'", Utility::Anonymize(remoteNetworkId_).c_str());
91 }
92
Thaw()93 void InputEventBuilder::Thaw()
94 {
95 if (!enable_) {
96 return;
97 }
98 freezing_ = false;
99 FI_HILOGI("Thaw remote input from '%{public}s'", Utility::Anonymize(remoteNetworkId_).c_str());
100 }
101
OnPacket(const std::string & networkId,Msdp::NetPacket & packet)102 bool InputEventBuilder::OnPacket(const std::string &networkId, Msdp::NetPacket &packet)
103 {
104 if (networkId != remoteNetworkId_) {
105 FI_HILOGW("Unexpected packet from \'%{public}s\'", Utility::Anonymize(networkId).c_str());
106 return false;
107 }
108 switch (packet.GetMsgId()) {
109 case MessageId::DSOFTBUS_INPUT_POINTER_EVENT: {
110 OnPointerEvent(packet);
111 break;
112 }
113 case MessageId::DSOFTBUS_INPUT_KEY_EVENT: {
114 OnKeyEvent(packet);
115 break;
116 }
117 default: {
118 FI_HILOGW("Unexpected message(%{public}d) from \'%{public}s\'",
119 static_cast<int32_t>(packet.GetMsgId()), Utility::Anonymize(networkId).c_str());
120 return false;
121 }
122 }
123 return true;
124 }
125
OnPointerEvent(Msdp::NetPacket & packet)126 void InputEventBuilder::OnPointerEvent(Msdp::NetPacket &packet)
127 {
128 CHKPV(pointerEvent_);
129 pointerEvent_->Reset();
130 int32_t ret = InputEventSerialization::Unmarshalling(packet, pointerEvent_);
131 if (ret != RET_OK) {
132 FI_HILOGE("Failed to deserialize pointer event");
133 return;
134 }
135 if (!UpdatePointerEvent(pointerEvent_)) {
136 return;
137 }
138 TagRemoteEvent(pointerEvent_);
139 FI_HILOGI("PointerEvent(No:%{public}d,Source:%{public}s,Action:%{public}s)",
140 pointerEvent_->GetId(), pointerEvent_->DumpSourceType(), pointerEvent_->DumpPointerAction());
141 if (IsActive(pointerEvent_)) {
142 env_->GetInput().SimulateInputEvent(pointerEvent_);
143 }
144 }
145
OnKeyEvent(Msdp::NetPacket & packet)146 void InputEventBuilder::OnKeyEvent(Msdp::NetPacket &packet)
147 {
148 CHKPV(keyEvent_);
149 pointerEvent_->Reset();
150 int32_t ret = InputEventSerialization::NetPacketToKeyEvent(packet, keyEvent_);
151 if (ret != RET_OK) {
152 FI_HILOGE("Failed to deserialize key event");
153 return;
154 }
155 FI_HILOGD("KeyEvent(No:%{public}d,Key:%{private}d,Action:%{public}d)",
156 keyEvent_->GetId(), keyEvent_->GetKeyCode(), keyEvent_->GetKeyAction());
157 env_->GetInput().SimulateInputEvent(keyEvent_);
158 }
159
UpdatePointerEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent)160 bool InputEventBuilder::UpdatePointerEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent)
161 {
162 if (pointerEvent->GetSourceType() != MMI::PointerEvent::SOURCE_TYPE_MOUSE) {
163 return true;
164 }
165 MMI::PointerEvent::PointerItem item;
166 if (!pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), item)) {
167 FI_HILOGE("Corrupted pointer event");
168 return false;
169 }
170 pointerEvent->AddFlag(MMI::InputEvent::EVENT_FLAG_RAW_POINTER_MOVEMENT);
171 int64_t time = Utility::GetSysClockTime();
172 pointerEvent->SetActionTime(time);
173 pointerEvent->SetActionStartTime(time);
174 pointerEvent->SetTargetDisplayId(-1);
175 pointerEvent->SetTargetWindowId(-1);
176 pointerEvent->SetAgentWindowId(-1);
177 return true;
178 }
179
TagRemoteEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent)180 void InputEventBuilder::TagRemoteEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent)
181 {
182 pointerEvent->SetDeviceId(
183 (pointerEvent->GetDeviceId() >= 0) ?
184 -(pointerEvent->GetDeviceId() + 1) :
185 pointerEvent->GetDeviceId());
186 }
187
IsActive(std::shared_ptr<MMI::PointerEvent> pointerEvent)188 bool InputEventBuilder::IsActive(std::shared_ptr<MMI::PointerEvent> pointerEvent)
189 {
190 if (!freezing_) {
191 return true;
192 }
193 if ((pointerEvent->GetSourceType() != MMI::PointerEvent::SOURCE_TYPE_MOUSE) ||
194 ((pointerEvent->GetPointerAction() != MMI::PointerEvent::POINTER_ACTION_MOVE) &&
195 (pointerEvent->GetPointerAction() != MMI::PointerEvent::POINTER_ACTION_PULL_MOVE))) {
196 return true;
197 }
198 MMI::PointerEvent::PointerItem item;
199 if (!pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), item)) {
200 FI_HILOGE("Corrupted pointer event");
201 return false;
202 }
203 movement_ += item.GetRawDx();
204 movement_ = std::clamp(movement_, -DEFAULT_SCREEN_WIDTH, DEFAULT_SCREEN_WIDTH);
205 if (xDir_ == 0) {
206 xDir_ = movement_;
207 }
208 if (((xDir_ > 0) && (movement_ <= 0)) || ((xDir_ < 0) && (movement_ >= 0))) {
209 return true;
210 }
211 if ((nDropped_++ % LOG_PERIOD) == 0) {
212 FI_HILOGI("Remote input from '%{public}s' is freezing", Utility::Anonymize(remoteNetworkId_).c_str());
213 }
214 return false;
215 }
216
ResetPressedEvents()217 void InputEventBuilder::ResetPressedEvents()
218 {
219 CHKPV(env_);
220 CHKPV(pointerEvent_);
221 if (auto pressedButtons = pointerEvent_->GetPressedButtons(); !pressedButtons.empty()) {
222 auto dragState = env_->GetDragManager().GetDragState();
223 for (auto buttonId : pressedButtons) {
224 if (dragState == DragState::START && buttonId == MMI::PointerEvent::MOUSE_BUTTON_LEFT) {
225 FI_HILOGI("Dragging with mouse_button_left down, skip");
226 continue;
227 }
228 pointerEvent_->SetButtonId(buttonId);
229 pointerEvent_->SetPointerAction(MMI::PointerEvent::POINTER_ACTION_BUTTON_UP);
230 env_->GetInput().SimulateInputEvent(pointerEvent_);
231 FI_HILOGI("Simulate button-up event, buttonId:%{public}d", buttonId);
232 }
233 pointerEvent_->Reset();
234 }
235 }
236 } // namespace Cooperate
237 } // namespace DeviceStatus
238 } // namespace Msdp
239 } // namespace OHOS
240