• 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 "cooperate_hisysevent.h"
22 #include "devicestatus_define.h"
23 #include "input_event_transmission/input_event_serialization.h"
24 #include "utility.h"
25 #include "kits/c/wifi_hid2d.h"
26 #include "res_sched_client.h"
27 #include "res_type.h"
28 
29 #undef LOG_TAG
30 #define LOG_TAG "InputEventBuilder"
31 
32 namespace OHOS {
33 namespace Msdp {
34 namespace DeviceStatus {
35 namespace Cooperate {
36 namespace {
37 constexpr size_t LOG_PERIOD { 10 };
38 constexpr int32_t DEFAULT_SCREEN_WIDTH { 512 };
39 constexpr double MIN_DAMPLING_COEFFICENT { 0.05 };
40 constexpr double MAX_DAMPLING_COEFFICENT { 1.5 };
41 constexpr double DEFAULT_DAMPLING_COEFFICIENT { 1.0 };
42 const std::string WIFI_INTERFACE_NAME { "chba0" };
43 const int32_t RESTORE_SCENE { 0 };
44 const int32_t FORBIDDEN_SCENE { 1 };
45 const int32_t UPPER_SCENE_FPS { 0 };
46 const int32_t UPPER_SCENE_BW { 0 };
47 const int32_t MODE_ENABLE { 0 };
48 const int32_t MODE_DISABLE { 1 };
49 const std::string LOW_LATENCY_KEY = "identity";
50 }
51 
InputEventBuilder(IContext * env)52 InputEventBuilder::InputEventBuilder(IContext *env)
53     : env_(env)
54 {
55     observer_ = std::make_shared<DSoftbusObserver>(*this);
56     pointerEvent_ = MMI::PointerEvent::Create();
57     keyEvent_ = MMI::KeyEvent::Create();
58 
59     for (size_t index = 0, cnt = damplingCoefficients_.size(); index < cnt; ++index) {
60         damplingCoefficients_[index] = DEFAULT_DAMPLING_COEFFICIENT;
61     }
62 }
63 
~InputEventBuilder()64 InputEventBuilder::~InputEventBuilder()
65 {
66     Disable();
67 }
68 
Enable(Context & context)69 void InputEventBuilder::Enable(Context &context)
70 {
71     CALL_INFO_TRACE;
72     if (enable_) {
73         return;
74     }
75     enable_ = true;
76     xDir_ = 0;
77     movement_ = 0;
78     freezing_ = (context.CooperateFlag() & COOPERATE_FLAG_FREEZE_CURSOR);
79     remoteNetworkId_ = context.Peer();
80     env_->GetDSoftbus().AddObserver(observer_);
81     Coordinate cursorPos = context.CursorPosition();
82     TurnOffChannelScan();
83     FI_HILOGI("Cursor transite in (%{private}d, %{private}d)", cursorPos.x, cursorPos.y);
84     if (!enable_) {
85         CooperateRadarInfo radarInfo {
86             .funcName =  __FUNCTION__,
87             .bizState = static_cast<int32_t> (BizState::STATE_END),
88             .bizStage = static_cast<int32_t> (BizCooperateStage::STATE_INPUT_EVENT_BUILDER_ENABLE),
89             .stageRes = static_cast<int32_t> (BizCooperateStageRes::RES_FAIL),
90             .bizScene = static_cast<int32_t> (BizCooperateScene::SCENE_PASSIVE),
91             .errCode = static_cast<int32_t> (CooperateRadarErrCode::INPUT_EVENT_BUILDER_ENABLE_FAILED),
92             .hostName = "",
93             .localNetId = Utility::DFXRadarAnonymize(context.Local().c_str()),
94             .peerNetId = Utility::DFXRadarAnonymize(remoteNetworkId_.c_str())
95         };
96         CooperateRadar::ReportCooperateRadarInfo(radarInfo);
97     }
98     ExecuteInner();
99 }
100 
Disable()101 void InputEventBuilder::Disable()
102 {
103     CALL_INFO_TRACE;
104     if (enable_) {
105         enable_ = false;
106         env_->GetDSoftbus().RemoveObserver(observer_);
107         TurnOnChannelScan();
108         ResetPressedEvents();
109     }
110     if ((pointerEventTimer_ >= 0)) {
111         env_->GetTimerManager().RemoveTimerAsync(pointerEventTimer_);
112         pointerEventTimer_ = -1;
113     }
114     HandleStopTimer();
115 }
116 
Update(Context & context)117 void InputEventBuilder::Update(Context &context)
118 {
119     remoteNetworkId_ = context.Peer();
120     FI_HILOGI("Update peer to \'%{public}s\'", Utility::Anonymize(remoteNetworkId_).c_str());
121 }
122 
Freeze()123 void InputEventBuilder::Freeze()
124 {
125     if (!enable_) {
126         return;
127     }
128     xDir_ = 0;
129     movement_ = 0;
130     freezing_ = true;
131     FI_HILOGI("Freeze remote input from '%{public}s'", Utility::Anonymize(remoteNetworkId_).c_str());
132 }
133 
Thaw()134 void InputEventBuilder::Thaw()
135 {
136     if (!enable_) {
137         return;
138     }
139     freezing_ = false;
140     FI_HILOGI("Thaw remote input from '%{public}s'", Utility::Anonymize(remoteNetworkId_).c_str());
141 }
142 
SetDamplingCoefficient(uint32_t direction,double coefficient)143 void InputEventBuilder::SetDamplingCoefficient(uint32_t direction, double coefficient)
144 {
145     coefficient = std::clamp(coefficient, MIN_DAMPLING_COEFFICENT, MAX_DAMPLING_COEFFICENT);
146     FI_HILOGI("SetDamplingCoefficient(0x%{public}x, %{public}.3f)", direction, coefficient);
147     if ((direction & COORDINATION_DAMPLING_UP) == COORDINATION_DAMPLING_UP) {
148         damplingCoefficients_[DamplingDirection::DAMPLING_DIRECTION_UP] = coefficient;
149     }
150     if ((direction & COORDINATION_DAMPLING_DOWN) == COORDINATION_DAMPLING_DOWN) {
151         damplingCoefficients_[DamplingDirection::DAMPLING_DIRECTION_DOWN] = coefficient;
152     }
153     if ((direction & COORDINATION_DAMPLING_LEFT) == COORDINATION_DAMPLING_LEFT) {
154         damplingCoefficients_[DamplingDirection::DAMPLING_DIRECTION_LEFT] = coefficient;
155     }
156     if ((direction & COORDINATION_DAMPLING_RIGHT) == COORDINATION_DAMPLING_RIGHT) {
157         damplingCoefficients_[DamplingDirection::DAMPLING_DIRECTION_RIGHT] = coefficient;
158     }
159 }
160 
UpdateVirtualDeviceIdMap(const std::unordered_map<int32_t,int32_t> & remote2VirtualIds)161 void InputEventBuilder::UpdateVirtualDeviceIdMap(const std::unordered_map<int32_t, int32_t> &remote2VirtualIds)
162 {
163     CALL_INFO_TRACE;
164     std::unique_lock<std::shared_mutex> lock(lock_);
165     remote2VirtualIds_ = remote2VirtualIds;
166     for (const auto &elem: remote2VirtualIds_) {
167         FI_HILOGI("Remote:%{public}d -> virtual:%{public}d", elem.first, elem.second);
168     }
169 }
170 
GetDamplingCoefficient(DamplingDirection direction) const171 double InputEventBuilder::GetDamplingCoefficient(DamplingDirection direction) const
172 {
173     if ((direction >= DamplingDirection::DAMPLING_DIRECTION_UP) &&
174         (direction < DamplingDirection::N_DAMPLING_DIRECTIONS)) {
175         return damplingCoefficients_[direction];
176     }
177     return DEFAULT_DAMPLING_COEFFICIENT;
178 }
179 
OnPacket(const std::string & networkId,Msdp::NetPacket & packet)180 bool InputEventBuilder::OnPacket(const std::string &networkId, Msdp::NetPacket &packet)
181 {
182     if (networkId != remoteNetworkId_) {
183         FI_HILOGW("Unexpected packet from \'%{public}s\'", Utility::Anonymize(networkId).c_str());
184         return false;
185     }
186     switch (packet.GetMsgId()) {
187         case MessageId::DSOFTBUS_INPUT_POINTER_EVENT: {
188             OnPointerEvent(packet);
189             break;
190         }
191         case MessageId::DSOFTBUS_INPUT_KEY_EVENT: {
192             OnKeyEvent(packet);
193             break;
194         }
195         case MessageId::DSOFTBUS_HEART_BEAT_PACKET: {
196             FI_HILOGD("Heart beat received");
197             break;
198         }
199         default: {
200             FI_HILOGW("Unexpected message(%{public}d) from \'%{public}s\'",
201                 static_cast<int32_t>(packet.GetMsgId()), Utility::Anonymize(networkId).c_str());
202             return false;
203         }
204     }
205     return true;
206 }
207 
OnPointerEvent(Msdp::NetPacket & packet)208 void InputEventBuilder::OnPointerEvent(Msdp::NetPacket &packet)
209 {
210     CHKPV(pointerEvent_);
211     if (scanState_) {
212         TurnOffChannelScan();
213     }
214     if ((pointerEventTimer_ >= 0)) {
215         env_->GetTimerManager().RemoveTimerAsync(pointerEventTimer_);
216         pointerEventTimer_ = -1;
217     }
218     pointerEvent_->Reset();
219     int32_t ret = InputEventSerialization::Unmarshalling(packet, pointerEvent_);
220     if (ret != RET_OK) {
221         FI_HILOGE("Failed to deserialize pointer event");
222         return;
223     }
224     if (!UpdatePointerEvent(pointerEvent_)) {
225         return;
226     }
227     TagRemoteEvent(pointerEvent_);
228     OnNotifyCrossDrag(pointerEvent_);
229     FI_HILOGD("PointerEvent(No:%{public}d, Source:%{public}s, Action:%{public}s)",
230         pointerEvent_->GetId(), pointerEvent_->DumpSourceType(), pointerEvent_->DumpPointerAction());
231     if (IsActive(pointerEvent_)) {
232         env_->GetInput().SimulateInputEvent(pointerEvent_);
233     }
234     pointerEventTimer_ = env_->GetTimerManager().AddTimerAsync(POINTER_EVENT_TIMEOUT, REPEAT_ONCE, [this]() {
235         TurnOnChannelScan();
236         pointerEventTimer_ = -1;
237     });
238 }
239 
OnNotifyCrossDrag(std::shared_ptr<MMI::PointerEvent> pointerEvent)240 void InputEventBuilder::OnNotifyCrossDrag(std::shared_ptr<MMI::PointerEvent> pointerEvent)
241 {
242     CHKPV(pointerEvent);
243     auto pointerAction = pointerEvent->GetPointerAction();
244     if (pointerAction == MMI::PointerEvent::POINTER_ACTION_PULL_IN_WINDOW ||
245         pointerAction == MMI::PointerEvent::POINTER_ACTION_PULL_OUT_WINDOW) {
246         FI_HILOGD("PointerAction:%{public}d, it's pressedButtons is empty, skip", pointerAction);
247         return;
248     }
249     auto pressedButtons = pointerEvent->GetPressedButtons();
250     bool isButtonDown = (pressedButtons.find(MMI::PointerEvent::MOUSE_BUTTON_LEFT) != pressedButtons.end());
251     FI_HILOGD("PointerAction:%{public}d, isPressed:%{public}s", pointerAction, isButtonDown ? "true" : "false");
252     CHKPV(env_);
253     env_->GetDragManager().NotifyCrossDrag(isButtonDown);
254 }
255 
OnKeyEvent(Msdp::NetPacket & packet)256 void InputEventBuilder::OnKeyEvent(Msdp::NetPacket &packet)
257 {
258     CHKPV(keyEvent_);
259     keyEvent_->Reset();
260     int32_t ret = InputEventSerialization::NetPacketToKeyEvent(packet, keyEvent_);
261     if (ret != RET_OK) {
262         FI_HILOGE("Failed to deserialize key event");
263         return;
264     }
265     FI_HILOGD("KeyEvent(No:%{public}d,Key:%{private}d,Action:%{public}d)",
266         keyEvent_->GetId(), keyEvent_->GetKeyCode(), keyEvent_->GetKeyAction());
267     keyEvent_->AddFlag(MMI::InputEvent::EVENT_FLAG_SIMULATE);
268     env_->GetInput().SimulateInputEvent(keyEvent_);
269 }
270 
TurnOffChannelScan()271 void InputEventBuilder::TurnOffChannelScan()
272 {
273     CALL_INFO_TRACE;
274     scanState_ = false;
275     if (SetWifiScene(FORBIDDEN_SCENE) != RET_OK) {
276         scanState_ = true;
277         FI_HILOGE("Forbidden scene failed");
278     }
279 }
280 
ExecuteInner()281 void InputEventBuilder::ExecuteInner()
282 {
283     CALL_DEBUG_ENTER;
284     // to enable low latency mode: value = 0
285     OHOS::ResourceSchedule::ResSchedClient::GetInstance().ReportData(
286         OHOS::ResourceSchedule::ResType::RES_TYPE_NETWORK_LATENCY_REQUEST, MODE_ENABLE,
287         {{LOW_LATENCY_KEY, FI_PKG_NAME}});
288 }
289 
HandleStopTimer()290 void InputEventBuilder::HandleStopTimer()
291 {
292     CALL_DEBUG_ENTER;
293     OHOS::ResourceSchedule::ResSchedClient::GetInstance().ReportData(
294         OHOS::ResourceSchedule::ResType::RES_TYPE_NETWORK_LATENCY_REQUEST, MODE_DISABLE,
295         {{LOW_LATENCY_KEY, FI_PKG_NAME}});
296 }
297 
TurnOnChannelScan()298 void InputEventBuilder::TurnOnChannelScan()
299 {
300     CALL_INFO_TRACE;
301     scanState_ = true;
302     if (SetWifiScene(RESTORE_SCENE) != RET_OK) {
303         scanState_ = false;
304         FI_HILOGE("Restore scene failed");
305     }
306 }
307 
SetWifiScene(unsigned int scene)308 int32_t InputEventBuilder::SetWifiScene(unsigned int scene)
309 {
310     CALL_DEBUG_ENTER;
311     Hid2dUpperScene upperScene;
312     upperScene.scene = scene;
313     upperScene.fps = UPPER_SCENE_FPS;
314     upperScene.bw = UPPER_SCENE_BW;
315     if (Hid2dSetUpperScene(WIFI_INTERFACE_NAME.c_str(), &upperScene) != RET_OK) {
316         FI_HILOGE("Set wifi scene failed");
317         return RET_ERR;
318     }
319     return RET_OK;
320 }
321 
UpdatePointerEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent)322 bool InputEventBuilder::UpdatePointerEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent)
323 {
324     if (pointerEvent->GetSourceType() != MMI::PointerEvent::SOURCE_TYPE_MOUSE) {
325         return true;
326     }
327     if (!DampPointerMotion(pointerEvent)) {
328         FI_HILOGE("DampPointerMotion fail");
329         return false;
330     }
331     pointerEvent->AddFlag(MMI::InputEvent::EVENT_FLAG_RAW_POINTER_MOVEMENT);
332     int64_t time = Utility::GetSysClockTime();
333     pointerEvent->SetActionTime(time);
334     pointerEvent->SetActionStartTime(time);
335     pointerEvent->SetTargetDisplayId(-1);
336     pointerEvent->SetTargetWindowId(-1);
337     pointerEvent->SetAgentWindowId(-1);
338     return true;
339 }
340 
DampPointerMotion(std::shared_ptr<MMI::PointerEvent> pointerEvent)341 bool InputEventBuilder::DampPointerMotion(std::shared_ptr<MMI::PointerEvent> pointerEvent)
342 {
343     MMI::PointerEvent::PointerItem item;
344     if (!pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), item)) {
345         FI_HILOGE("Corrupted pointer event");
346         return false;
347     }
348     // Dampling pointer movement.
349     // First transition will trigger special effect which would damp pointer movement. We want to
350     // damp pointer movement even further than that could be achieved by setting pointer speed.
351     // By scaling increment of pointer movement, we want to enlarge the range of pointer speed setting.
352     if (item.GetRawDx() > 0) {
353         double rawDxRight = rawDxRightRemainder_ + item.GetRawDx() * GetDamplingCoefficient(
354             DamplingDirection::DAMPLING_DIRECTION_RIGHT);
355         int32_t rawDxIntegerRight = static_cast<int32_t>(rawDxRight);
356         rawDxRightRemainder_ = rawDxRight - static_cast<double>(rawDxIntegerRight);
357         item.SetRawDx(rawDxIntegerRight);
358     } else if (item.GetRawDx() < 0) {
359         double rawDxLeft = rawDxLeftRemainder_ + item.GetRawDx() * GetDamplingCoefficient(
360             DamplingDirection::DAMPLING_DIRECTION_LEFT);
361         int32_t rawDxIntegerLeft = static_cast<int32_t>(rawDxLeft);
362         rawDxLeftRemainder_ = rawDxLeft - static_cast<double>(rawDxIntegerLeft);
363         item.SetRawDx(rawDxIntegerLeft);
364     }
365     if (item.GetRawDy() >= 0) {
366         item.SetRawDy(static_cast<int32_t>(
367             item.GetRawDy() * GetDamplingCoefficient(DamplingDirection::DAMPLING_DIRECTION_DOWN)));
368     } else {
369         item.SetRawDy(static_cast<int32_t>(
370             item.GetRawDy() * GetDamplingCoefficient(DamplingDirection::DAMPLING_DIRECTION_UP)));
371     }
372     pointerEvent->UpdatePointerItem(pointerEvent->GetPointerId(), item);
373     return true;
374 }
375 
TagRemoteEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent)376 void InputEventBuilder::TagRemoteEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent)
377 {
378     std::shared_lock<std::shared_mutex> lock(lock_);
379     if (auto deviceId = pointerEvent->GetDeviceId(); remote2VirtualIds_.find(deviceId) != remote2VirtualIds_.end()) {
380         pointerEvent->SetDeviceId(remote2VirtualIds_[deviceId]);
381     } else {
382         pointerEvent->SetDeviceId((deviceId >= 0) ? -(deviceId + 1) : deviceId);
383     }
384 }
385 
IsActive(std::shared_ptr<MMI::PointerEvent> pointerEvent)386 bool InputEventBuilder::IsActive(std::shared_ptr<MMI::PointerEvent> pointerEvent)
387 {
388     if (!freezing_) {
389         return true;
390     }
391     if ((pointerEvent->GetSourceType() != MMI::PointerEvent::SOURCE_TYPE_MOUSE) ||
392         ((pointerEvent->GetPointerAction() != MMI::PointerEvent::POINTER_ACTION_MOVE) &&
393          (pointerEvent->GetPointerAction() != MMI::PointerEvent::POINTER_ACTION_PULL_MOVE))) {
394         return true;
395     }
396     MMI::PointerEvent::PointerItem item;
397     if (!pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), item)) {
398         FI_HILOGE("Corrupted pointer event");
399         return false;
400     }
401     movement_ += item.GetRawDx();
402     movement_ = std::clamp(movement_, -DEFAULT_SCREEN_WIDTH, DEFAULT_SCREEN_WIDTH);
403     if (xDir_ == 0) {
404         xDir_ = movement_;
405     }
406     if (((xDir_ > 0) && (movement_ <= 0)) || ((xDir_ < 0) && (movement_ >= 0))) {
407         return true;
408     }
409     if ((nDropped_++ % LOG_PERIOD) == 0) {
410         FI_HILOGI("Remote input from '%{public}s' is freezing", Utility::Anonymize(remoteNetworkId_).c_str());
411     }
412     return false;
413 }
414 
ResetPressedEvents()415 void InputEventBuilder::ResetPressedEvents()
416 {
417     CHKPV(env_);
418     CHKPV(pointerEvent_);
419     if (auto pressedButtons = pointerEvent_->GetPressedButtons(); !pressedButtons.empty()) {
420         auto dragState = env_->GetDragManager().GetDragState();
421         for (auto buttonId : pressedButtons) {
422             if (dragState == DragState::START && buttonId == MMI::PointerEvent::MOUSE_BUTTON_LEFT) {
423                 FI_HILOGI("Dragging with mouse_button_left down, skip");
424                 continue;
425             }
426             pointerEvent_->SetButtonId(buttonId);
427             pointerEvent_->SetPointerAction(MMI::PointerEvent::POINTER_ACTION_BUTTON_UP);
428             env_->GetInput().SimulateInputEvent(pointerEvent_);
429             FI_HILOGI("Simulate button-up event, buttonId:%{public}d", buttonId);
430         }
431         pointerEvent_->Reset();
432     }
433 }
434 } // namespace Cooperate
435 } // namespace DeviceStatus
436 } // namespace Msdp
437 } // namespace OHOS
438