• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 (%{private}d, %{private}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_HILOGD("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     keyEvent_->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