• 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 } // 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 (%{private}d, %{private}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