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