1 /*
2 * Copyright (c) 2023-2025 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_interceptor.h"
17
18 #include "cooperate_context.h"
19 #include "cooperate_hisysevent.h"
20 #include "devicestatus_define.h"
21 #include "display_manager.h"
22 #include "power_mgr_client.h"
23 #include "input_event_transmission/input_event_serialization.h"
24 #include "utility.h"
25 #include "kits/c/wifi_hid2d.h"
26
27 #include "res_sched_client.h"
28 #include "res_type.h"
29
30 #undef LOG_TAG
31 #define LOG_TAG "InputEventInterceptor"
32
33 namespace OHOS {
34 namespace Msdp {
35 namespace DeviceStatus {
36 namespace Cooperate {
37
38 namespace {
39 const std::string WIFI_INTERFACE_NAME { "chba0" };
40 const int32_t RESTORE_SCENE { 0 };
41 const int32_t FORBIDDEN_SCENE { 1 };
42 const int32_t UPPER_SCENE_FPS { 0 };
43 const int32_t UPPER_SCENE_BW { 0 };
44 const int32_t INTERVAL_MS { 2000 };
45 const int32_t REPEAT_MAX { 10000 };
46 const int32_t MODE_ENABLE { 0 };
47 const int32_t MODE_DISABLE { 1 };
48 const std::string LOW_LATENCY_KEY = "identity";
49 }
50
51 std::set<int32_t> InputEventInterceptor::filterKeys_ {
52 MMI::KeyEvent::KEYCODE_BACK,
53 MMI::KeyEvent::KEYCODE_POWER,
54 };
55
56 std::set<int32_t> InputEventInterceptor::filterPointers_ {
57 MMI::PointerEvent::POINTER_ACTION_ENTER_WINDOW,
58 MMI::PointerEvent::POINTER_ACTION_LEAVE_WINDOW,
59 MMI::PointerEvent::POINTER_ACTION_PULL_IN_WINDOW,
60 MMI::PointerEvent::POINTER_ACTION_PULL_OUT_WINDOW,
61 };
62
~InputEventInterceptor()63 InputEventInterceptor::~InputEventInterceptor()
64 {
65 Disable();
66 }
67
Enable(Context & context)68 int32_t InputEventInterceptor::Enable(Context &context)
69 {
70 CALL_INFO_TRACE;
71 CHKPR(env_, RET_ERR);
72 if (interceptorId_ > 0) {
73 return RET_OK;
74 }
75 auto cursorPos = context.CursorPosition();
76 FI_HILOGI("Cursor transite out at (%{private}d, %{private}d)", cursorPos.x, cursorPos.y);
77 remoteNetworkId_ = context.Peer();
78 sender_ = context.Sender();
79 inputEventSampler_.SetPointerEventHandler(
80 [this](std::shared_ptr<MMI::PointerEvent> pointerEvent) {
81 this->OnPointerEvent(pointerEvent);
82 }
83 );
84 interceptorId_ = env_->GetInput().AddInterceptor(
85 [this](std::shared_ptr<MMI::PointerEvent> pointerEvent) { inputEventSampler_.OnPointerEvent(pointerEvent); },
86 [this](std::shared_ptr<MMI::KeyEvent> keyEvent) { this->OnKeyEvent(keyEvent); });
87 if (interceptorId_ < 0) {
88 FI_HILOGE("Input::AddInterceptor fail");
89 CooperateRadarInfo radarInfo {
90 .funcName = __FUNCTION__,
91 .bizState = static_cast<int32_t> (BizState::STATE_END),
92 .bizStage = static_cast<int32_t> (BizCooperateStage::STAGE_ADD_MMI_EVENT_INTERCEPOR),
93 .stageRes = static_cast<int32_t> (BizCooperateStageRes::RES_FAIL),
94 .bizScene = static_cast<int32_t> (BizCooperateScene::SCENE_ACTIVE),
95 .errCode = static_cast<int32_t> (CooperateRadarErrCode::ADD_MMI_EVENT_INTERCEPOR_FAILED),
96 .hostName = "",
97 .localNetId = Utility::DFXRadarAnonymize(context.Local().c_str()),
98 .peerNetId = Utility::DFXRadarAnonymize(remoteNetworkId_.c_str())
99 };
100 CooperateRadar::ReportCooperateRadarInfo(radarInfo);
101 return RET_ERR;
102 }
103 TurnOffChannelScan();
104 HeartBeatSend();
105 ExecuteInner();
106 return RET_OK;
107 }
108
HeartBeatSend()109 void InputEventInterceptor::HeartBeatSend()
110 {
111 CALL_DEBUG_ENTER;
112 CHKPV(env_);
113 heartTimer_ = env_->GetTimerManager().AddTimerAsync(INTERVAL_MS, REPEAT_MAX, [this]() {
114 NetPacket packet(MessageId::DSOFTBUS_HEART_BEAT_PACKET);
115 if (InputEventSerialization::HeartBeatMarshalling(packet) != RET_OK) {
116 FI_HILOGE("Failed to serialize packet");
117 return;
118 }
119 env_->GetDSoftbus().SendPacket(remoteNetworkId_, packet);
120 });
121 }
122
Disable()123 void InputEventInterceptor::Disable()
124 {
125 CALL_INFO_TRACE;
126 CHKPV(env_);
127 TurnOnChannelScan();
128 if (interceptorId_ > 0) {
129 env_->GetInput().RemoveInterceptor(interceptorId_);
130 interceptorId_ = -1;
131 }
132 if ((pointerEventTimer_ >= 0)) {
133 env_->GetTimerManager().RemoveTimerAsync(pointerEventTimer_);
134 pointerEventTimer_ = -1;
135 }
136 if (heartTimer_ < 0) {
137 FI_HILOGE("Invalid heartTimer_");
138 return;
139 }
140 if (env_->GetTimerManager().RemoveTimerAsync(heartTimer_) != RET_OK) {
141 FI_HILOGE("Failed to RemoveTimer");
142 }
143 heartTimer_ = -1;
144 }
145
Update(Context & context)146 void InputEventInterceptor::Update(Context &context)
147 {
148 remoteNetworkId_ = context.Peer();
149 FI_HILOGI("Update peer to \'%{public}s\'", Utility::Anonymize(remoteNetworkId_).c_str());
150 }
151
OnPointerEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent)152 void InputEventInterceptor::OnPointerEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent)
153 {
154 CHKPV(pointerEvent);
155 int64_t interceptorTime = Utility::GetSysClockTime();
156 if (scanState_) {
157 TurnOffChannelScan();
158 }
159 RefreshActivity();
160 if ((pointerEventTimer_ >= 0)) {
161 env_->GetTimerManager().RemoveTimerAsync(pointerEventTimer_);
162 pointerEventTimer_ = -1;
163 }
164 if (auto pointerAction = pointerEvent->GetPointerAction();
165 filterPointers_.find(pointerAction) != filterPointers_.end()) {
166 FI_HILOGI("Current pointerAction:%{public}d, skip", static_cast<int32_t>(pointerAction));
167 return;
168 }
169 if (auto pointerAction = pointerEvent->GetPointerAction();
170 pointerAction == MMI::PointerEvent::POINTER_ACTION_CANCEL) {
171 auto originAction = pointerEvent->GetOriginPointerAction();
172 FI_HILOGI("Reset to origin action:%{public}d", static_cast<int32_t>(originAction));
173 pointerEvent->SetPointerAction(originAction);
174 }
175 OnNotifyCrossDrag(pointerEvent);
176 NetPacket packet(MessageId::DSOFTBUS_INPUT_POINTER_EVENT);
177
178 int32_t ret = InputEventSerialization::Marshalling(pointerEvent, packet, interceptorTime);
179 if (ret != RET_OK) {
180 FI_HILOGE("Failed to serialize pointer event");
181 return;
182 }
183 FI_HILOGD("PointerEvent(No:%{public}d,Source:%{public}s,Action:%{public}s)",
184 pointerEvent->GetId(), pointerEvent->DumpSourceType(), pointerEvent->DumpPointerAction());
185 env_->GetDSoftbus().SendPacket(remoteNetworkId_, packet);
186 pointerEventTimer_ = env_->GetTimerManager().AddTimerAsync(POINTER_EVENT_TIMEOUT, REPEAT_ONCE, [this]() {
187 TurnOnChannelScan();
188 pointerEventTimer_ = -1;
189 });
190 }
191
OnNotifyCrossDrag(std::shared_ptr<MMI::PointerEvent> pointerEvent)192 void InputEventInterceptor::OnNotifyCrossDrag(std::shared_ptr<MMI::PointerEvent> pointerEvent)
193 {
194 CHKPV(pointerEvent);
195 CHKPV(env_);
196 auto pointerAction = pointerEvent->GetPointerAction();
197 if (pointerAction == MMI::PointerEvent::POINTER_ACTION_PULL_IN_WINDOW ||
198 pointerAction == MMI::PointerEvent::POINTER_ACTION_PULL_OUT_WINDOW) {
199 FI_HILOGD("PointerAction:%{public}d, it's pressedButtons is empty, skip", pointerAction);
200 return;
201 }
202 auto pressedButtons = pointerEvent->GetPressedButtons();
203 bool isButtonDown = (pressedButtons.find(MMI::PointerEvent::MOUSE_BUTTON_LEFT) != pressedButtons.end());
204 FI_HILOGD("PointerAction:%{public}d, isPressed:%{public}s", pointerAction, isButtonDown ? "true" : "false");
205 CHKPV(env_);
206 env_->GetDragManager().NotifyCrossDrag(isButtonDown);
207 }
208
OnKeyEvent(std::shared_ptr<MMI::KeyEvent> keyEvent)209 void InputEventInterceptor::OnKeyEvent(std::shared_ptr<MMI::KeyEvent> keyEvent)
210 {
211 CHKPV(keyEvent);
212 CHKPV(env_);
213 RefreshActivity();
214 if (filterKeys_.find(keyEvent->GetKeyCode()) != filterKeys_.end()) {
215 keyEvent->AddFlag(MMI::AxisEvent::EVENT_FLAG_NO_INTERCEPT);
216 env_->GetInput().SimulateInputEvent(keyEvent);
217 return;
218 }
219 NetPacket packet(MessageId::DSOFTBUS_INPUT_KEY_EVENT);
220
221 int32_t ret = InputEventSerialization::KeyEventToNetPacket(keyEvent, packet);
222 if (ret != RET_OK) {
223 FI_HILOGE("Failed to serialize key event");
224 return;
225 }
226 FI_HILOGD("KeyEvent(No:%{public}d,Key:%{private}d,Action:%{public}d)",
227 keyEvent->GetId(), keyEvent->GetKeyCode(), keyEvent->GetKeyAction());
228 env_->GetDSoftbus().SendPacket(remoteNetworkId_, packet);
229 }
230
TurnOffChannelScan()231 void InputEventInterceptor::TurnOffChannelScan()
232 {
233 scanState_ = false;
234 if (SetWifiScene(FORBIDDEN_SCENE) != RET_OK) {
235 scanState_ = true;
236 FI_HILOGE("Forbidden scene failed");
237 }
238 }
239
ExecuteInner()240 void InputEventInterceptor::ExecuteInner()
241 {
242 CALL_DEBUG_ENTER;
243 // to enable low latency mode: value = 0
244 OHOS::ResourceSchedule::ResSchedClient::GetInstance().ReportData(
245 OHOS::ResourceSchedule::ResType::RES_TYPE_NETWORK_LATENCY_REQUEST, MODE_ENABLE,
246 {{LOW_LATENCY_KEY, FI_PKG_NAME}});
247 }
248
HandleStopTimer()249 void InputEventInterceptor::HandleStopTimer()
250 {
251 CALL_DEBUG_ENTER;
252 OHOS::ResourceSchedule::ResSchedClient::GetInstance().ReportData(
253 OHOS::ResourceSchedule::ResType::RES_TYPE_NETWORK_LATENCY_REQUEST, MODE_DISABLE,
254 {{LOW_LATENCY_KEY, FI_PKG_NAME}});
255 }
256
TurnOnChannelScan()257 void InputEventInterceptor::TurnOnChannelScan()
258 {
259 scanState_ = true;
260 if (SetWifiScene(RESTORE_SCENE) != RET_OK) {
261 scanState_ = false;
262 FI_HILOGE("Restore scene failed");
263 }
264 }
265
SetWifiScene(unsigned int scene)266 int32_t InputEventInterceptor::SetWifiScene(unsigned int scene)
267 {
268 CALL_DEBUG_ENTER;
269 Hid2dUpperScene upperScene;
270 upperScene.scene = scene;
271 upperScene.fps = UPPER_SCENE_FPS;
272 upperScene.bw = UPPER_SCENE_BW;
273 if (Hid2dSetUpperScene(WIFI_INTERFACE_NAME.c_str(), &upperScene) != RET_OK) {
274 FI_HILOGE("Set wifi scene failed");
275 return RET_ERR;
276 }
277 return RET_OK;
278 }
279
ReportPointerEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent)280 void InputEventInterceptor::ReportPointerEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent)
281 {
282 MMI::PointerEvent::PointerItem pointerItem;
283
284 if (!pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), pointerItem)) {
285 FI_HILOGE("Corrupted pointer event");
286 return;
287 }
288 auto ret = sender_.Send(CooperateEvent(
289 CooperateEventType::INPUT_POINTER_EVENT,
290 InputPointerEvent {
291 .deviceId = pointerEvent->GetDeviceId(),
292 .pointerAction = pointerEvent->GetPointerAction(),
293 .sourceType = pointerEvent->GetSourceType(),
294 .position = Coordinate {
295 .x = pointerItem.GetDisplayX(),
296 .y = pointerItem.GetDisplayY(),
297 }
298 }));
299 if (ret != Channel<CooperateEvent>::NO_ERROR) {
300 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
301 }
302 }
303
RefreshActivity()304 void InputEventInterceptor::RefreshActivity()
305 {
306 if (!PowerMgr::PowerMgrClient::GetInstance().RefreshActivity(
307 PowerMgr::UserActivityType::USER_ACTIVITY_TYPE_TOUCH)) {
308 FI_HILOGE("RefreshActivity Failed");
309 }
310 return;
311 }
312 } // namespace Cooperate
313 } // namespace DeviceStatus
314 } // namespace Msdp
315 } // namespace OHOS
316