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 "session/container/include/window_event_channel.h"
17 #include "scene_board_judgement.h"
18
19 #include <functional>
20 #include <utility>
21
22 #include <axis_event.h>
23 #include <key_event.h>
24 #include <pointer_event.h>
25
26 #include "anr_handler.h"
27 #include "window_manager_hilog.h"
28 #include "session_permission.h"
29
30 namespace OHOS::Rosen {
31 namespace {
32 constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowEventChannel" };
33 const std::set<int32_t> VALID_KEYCODE_FOR_CONSTRAINED_EMBEDDED_UIEXTENSION({ MMI::KeyEvent::KEYCODE_HOME,
34 MMI::KeyEvent::KEYCODE_TAB, MMI::KeyEvent::KEYCODE_ESCAPE, MMI::KeyEvent::KEYCODE_DPAD_UP,
35 MMI::KeyEvent::KEYCODE_DPAD_DOWN, MMI::KeyEvent::KEYCODE_DPAD_LEFT, MMI::KeyEvent::KEYCODE_DPAD_RIGHT,
36 MMI::KeyEvent::KEYCODE_MOVE_HOME, MMI::KeyEvent::KEYCODE_MOVE_END });
37 constexpr int32_t SIZE_TWO = 2;
38 }
39
OnTransferKeyEventForConsumed(int32_t keyEventId,bool isPreImeEvent,bool isConsumed,WSError retCode)40 void WindowEventChannelListenerProxy::OnTransferKeyEventForConsumed(int32_t keyEventId, bool isPreImeEvent,
41 bool isConsumed, WSError retCode)
42 {
43 MessageParcel data;
44 MessageParcel reply;
45 MessageOption option(MessageOption::TF_ASYNC);
46 if (!data.WriteInterfaceToken(GetDescriptor())) {
47 TLOGE(WmsLogTag::WMS_EVENT, "WriteInterfaceToken failed");
48 return;
49 }
50 if (!data.WriteInt32(keyEventId)) {
51 TLOGE(WmsLogTag::WMS_EVENT, "keyEventId write failed.");
52 return;
53 }
54 if (!data.WriteBool(isPreImeEvent)) {
55 TLOGE(WmsLogTag::WMS_EVENT, "isPreImeEvent write failed.");
56 return;
57 }
58 if (!data.WriteBool(isConsumed)) {
59 TLOGE(WmsLogTag::WMS_EVENT, "isConsumed write failed.");
60 return;
61 }
62 if (!data.WriteInt32(static_cast<int32_t>(retCode))) {
63 TLOGE(WmsLogTag::WMS_EVENT, "retCode write failed.");
64 return;
65 }
66 sptr<IRemoteObject> remote = Remote();
67 if (remote == nullptr) {
68 TLOGE(WmsLogTag::WMS_EVENT, "remote is null");
69 return;
70 }
71 if (remote->SendRequest(static_cast<uint32_t>(
72 WindowEventChannelListenerMessage::TRANS_ID_ON_TRANSFER_KEY_EVENT_FOR_CONSUMED_ASYNC),
73 data, reply, option) != ERR_NONE) {
74 TLOGE(WmsLogTag::WMS_EVENT, "SendRequest failed");
75 }
76 }
77
SetIsUIExtension(bool isUIExtension)78 void WindowEventChannel::SetIsUIExtension(bool isUIExtension)
79 {
80 isUIExtension_ = isUIExtension;
81 }
82
SetUIExtensionUsage(UIExtensionUsage uiExtensionUsage)83 void WindowEventChannel::SetUIExtensionUsage(UIExtensionUsage uiExtensionUsage)
84 {
85 uiExtensionUsage_ = uiExtensionUsage;
86 }
87
TransferKeyEvent(const std::shared_ptr<MMI::KeyEvent> & keyEvent)88 WSError WindowEventChannel::TransferKeyEvent(const std::shared_ptr<MMI::KeyEvent>& keyEvent)
89 {
90 WLOGFD("WindowEventChannel receive key event");
91 PrintKeyEvent(keyEvent);
92 bool isConsumed = false;
93 return TransferKeyEventForConsumed(keyEvent, isConsumed);
94 }
95
TransferPointerEvent(const std::shared_ptr<MMI::PointerEvent> & pointerEvent)96 WSError WindowEventChannel::TransferPointerEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent)
97 {
98 WLOGFD("WindowEventChannel receive pointer event");
99 PrintPointerEvent(pointerEvent);
100 if (SceneBoardJudgement::IsSceneBoardEnabled() && isUIExtension_ &&
101 (uiExtensionUsage_ == UIExtensionUsage::MODAL ||
102 uiExtensionUsage_ == UIExtensionUsage::CONSTRAINED_EMBEDDED)) {
103 if (!SessionPermission::IsSystemCalling()) {
104 TLOGE(WmsLogTag::WMS_EVENT, "Point event blocked because of modal/constrained UIExtension:%{public}u",
105 uiExtensionUsage_);
106 return WSError::WS_ERROR_INVALID_PERMISSION;
107 } else {
108 TLOGW(WmsLogTag::WMS_EVENT, "SystemCalling UIExtension:%{public}u", uiExtensionUsage_);
109 }
110 }
111 if (!sessionStage_) {
112 WLOGFE("session stage is null!");
113 return WSError::WS_ERROR_NULLPTR;
114 }
115 if (pointerEvent == nullptr) {
116 WLOGFE("PointerEvent is null!");
117 return WSError::WS_ERROR_NULLPTR;
118 }
119 auto pointerAction = pointerEvent->GetPointerAction();
120 if (pointerAction == MMI::PointerEvent::POINTER_ACTION_ENTER_WINDOW ||
121 pointerAction == MMI::PointerEvent::POINTER_ACTION_LEAVE_WINDOW ||
122 pointerAction == MMI::PointerEvent::POINTER_ACTION_PULL_IN_WINDOW ||
123 pointerAction == MMI::PointerEvent::POINTER_ACTION_PULL_OUT_WINDOW) {
124 WLOGFI("InputTracking id:%{public}d, Dispatch by skipping receipt, action:%{public}s,"
125 " persistentId:%{public}d", pointerEvent->GetId(),
126 pointerEvent->DumpPointerAction(), sessionStage_->GetPersistentId());
127 }
128 sessionStage_->NotifyPointerEvent(pointerEvent);
129 return WSError::WS_OK;
130 }
131
TransferBackpressedEventForConsumed(bool & isConsumed)132 WSError WindowEventChannel::TransferBackpressedEventForConsumed(bool& isConsumed)
133 {
134 WLOGFD("WindowEventChannel receive backpressed event");
135 if (!sessionStage_) {
136 WLOGFE("session stage is null!");
137 return WSError::WS_ERROR_NULLPTR;
138 }
139 sessionStage_->NotifyBackpressedEvent(isConsumed);
140 return WSError::WS_OK;
141 }
142
TransferKeyEventForConsumed(const std::shared_ptr<MMI::KeyEvent> & keyEvent,bool & isConsumed,bool isPreImeEvent)143 WSError WindowEventChannel::TransferKeyEventForConsumed(
144 const std::shared_ptr<MMI::KeyEvent>& keyEvent, bool& isConsumed, bool isPreImeEvent)
145 {
146 WLOGFD("WindowEventChannel receive key event");
147 if (!sessionStage_) {
148 WLOGFE("session stage is null!");
149 return WSError::WS_ERROR_NULLPTR;
150 }
151 if (keyEvent == nullptr) {
152 WLOGFE("keyEvent is nullptr");
153 return WSError::WS_ERROR_NULLPTR;
154 }
155 if (SceneBoardJudgement::IsSceneBoardEnabled() && isUIExtension_ && IsUIExtensionKeyEventBlocked(keyEvent)) {
156 return WSError::WS_ERROR_INVALID_PERMISSION;
157 }
158 if (isPreImeEvent) {
159 isConsumed = sessionStage_->NotifyOnKeyPreImeEvent(keyEvent);
160 TLOGI(WmsLogTag::WMS_EVENT, "NotifyOnKeyPreImeEvent id:%{public}d isConsumed:%{public}d",
161 keyEvent->GetId(), static_cast<int>(isConsumed));
162 return WSError::WS_OK;
163 }
164 sessionStage_->NotifyKeyEvent(keyEvent, isConsumed);
165 keyEvent->MarkProcessed();
166 return WSError::WS_OK;
167 }
168
IsUIExtensionKeyEventBlocked(const std::shared_ptr<MMI::KeyEvent> & keyEvent)169 bool WindowEventChannel::IsUIExtensionKeyEventBlocked(const std::shared_ptr<MMI::KeyEvent>& keyEvent)
170 {
171 if (uiExtensionUsage_ == UIExtensionUsage::MODAL) {
172 if (!SessionPermission::IsSystemCalling()) {
173 TLOGE(WmsLogTag::WMS_EVENT, "Unsupported keyCode due to Modal UIExtension.");
174 return true;
175 } else {
176 TLOGW(WmsLogTag::WMS_EVENT, "SystemCalling UIExtension.");
177 return false;
178 }
179 }
180 if (uiExtensionUsage_ == UIExtensionUsage::CONSTRAINED_EMBEDDED) {
181 auto keyCode = keyEvent->GetKeyCode();
182 if (VALID_KEYCODE_FOR_CONSTRAINED_EMBEDDED_UIEXTENSION.find(keyCode) ==
183 VALID_KEYCODE_FOR_CONSTRAINED_EMBEDDED_UIEXTENSION.end()) {
184 TLOGE(WmsLogTag::WMS_EVENT, "Unsupported keyCode due to Constrained embedded UIExtension.");
185 return true;
186 }
187 auto pressedKeys = keyEvent->GetPressedKeys();
188 if (pressedKeys.size() == SIZE_TWO && keyCode == MMI::KeyEvent::KEYCODE_TAB &&
189 (pressedKeys[0] == MMI::KeyEvent::KEYCODE_SHIFT_LEFT ||
190 pressedKeys[0] == MMI::KeyEvent::KEYCODE_SHIFT_RIGHT)) {
191 // only allows combined keys SHIFT+TAB
192 return false;
193 } else if (pressedKeys.size() >= SIZE_TWO) {
194 TLOGE(WmsLogTag::WMS_EVENT, "Invalid size of PressedKeys due to Constrained embedded UIExtension.");
195 return true;
196 }
197 }
198 return false;
199 }
200
TransferKeyEventForConsumedAsync(const std::shared_ptr<MMI::KeyEvent> & keyEvent,bool isPreImeEvent,const sptr<IRemoteObject> & listener)201 WSError WindowEventChannel::TransferKeyEventForConsumedAsync(
202 const std::shared_ptr<MMI::KeyEvent>& keyEvent, bool isPreImeEvent, const sptr<IRemoteObject>& listener)
203 {
204 bool isConsumed = false;
205 auto ret = TransferKeyEventForConsumed(keyEvent, isConsumed, isPreImeEvent);
206 auto channelListener = iface_cast<IWindowEventChannelListener>(listener);
207 if (channelListener == nullptr) {
208 TLOGE(WmsLogTag::WMS_EVENT, "listener is null.");
209 return ret;
210 }
211
212 auto keyEventId = keyEvent->GetId();
213 TLOGD(WmsLogTag::WMS_EVENT, "finished with isConsumed:%{public}d ret:%{public}d at PreIme:%{public}d id:%{public}d",
214 isConsumed, ret, isPreImeEvent, keyEventId);
215 channelListener->OnTransferKeyEventForConsumed(keyEventId, isPreImeEvent, isConsumed, ret);
216 return ret;
217 }
218
TransferFocusActiveEvent(bool isFocusActive)219 WSError WindowEventChannel::TransferFocusActiveEvent(bool isFocusActive)
220 {
221 WLOGFD("WindowEventChannel receive focus active event");
222 if (!sessionStage_) {
223 WLOGFE("session stage is null!");
224 return WSError::WS_ERROR_NULLPTR;
225 }
226 sessionStage_->NotifyFocusActiveEvent(isFocusActive);
227 return WSError::WS_OK;
228 }
229
PrintKeyEvent(const std::shared_ptr<MMI::KeyEvent> & event)230 void WindowEventChannel::PrintKeyEvent(const std::shared_ptr<MMI::KeyEvent>& event)
231 {
232 if (event == nullptr) {
233 WLOGFE("event is nullptr");
234 return;
235 }
236 std::vector<MMI::KeyEvent::KeyItem> eventItems = event->GetKeyItems();
237 WLOGFD("KeyCode:%{public}d,KeyAction:%{public}s,keyItemsCount:%{public}zu", event->GetKeyCode(),
238 MMI::KeyEvent::ActionToString(event->GetKeyAction()), eventItems.size());
239 for (const auto &item : eventItems) {
240 WLOGFD("KeyCode:%{public}d,IsPressed:%{public}d,GetUnicode:%{public}d",
241 item.GetKeyCode(), item.IsPressed(), item.GetUnicode());
242 }
243 }
244
PrintPointerEvent(const std::shared_ptr<MMI::PointerEvent> & event)245 void WindowEventChannel::PrintPointerEvent(const std::shared_ptr<MMI::PointerEvent>& event)
246 {
247 if (event == nullptr) {
248 WLOGFE("event is nullptr");
249 return;
250 }
251 std::vector<int32_t> pointerIds = event->GetPointerIds();
252 std::string str;
253 std::vector<uint8_t> buffer = event->GetBuffer();
254 for (const auto &buff : buffer) {
255 str += std::to_string(buff);
256 }
257 auto pointerAction = event->GetPointerAction();
258 if (pointerAction == MMI::PointerEvent::POINTER_ACTION_MOVE ||
259 pointerAction == MMI::PointerEvent::POINTER_ACTION_PULL_MOVE) {
260 WLOGFD("PointerAction:%{public}s,SourceType:%{public}s,ButtonId:%{public}d,"
261 "VerticalAxisValue:%{public}.2f,HorizontalAxisValue:%{public}.2f,"
262 "PointerId:%{public}d,PointerCount:%{public}zu,EventNumber:%{public}d,"
263 "BufferCount:%{public}zu,Buffer:%{public}s",
264 event->DumpPointerAction(), event->DumpSourceType(), event->GetButtonId(),
265 event->GetAxisValue(MMI::PointerEvent::AXIS_TYPE_SCROLL_VERTICAL),
266 event->GetAxisValue(MMI::PointerEvent::AXIS_TYPE_SCROLL_HORIZONTAL),
267 event->GetPointerId(), pointerIds.size(), event->GetId(), buffer.size(), str.c_str());
268
269 for (const auto &pointerId : pointerIds) {
270 MMI::PointerEvent::PointerItem item;
271 if (!event->GetPointerItem(pointerId, item)) {
272 WLOGFE("Invalid pointer: %{public}d.", pointerId);
273 return;
274 }
275 TLOGD(WmsLogTag::WMS_EVENT, "pointerId:%{public}d,DownTime:%{public}" PRId64 ",IsPressed:%{public}d,"
276 "DisplayX:%{private}d,DisplayY:%{private}d,WindowX:%{private}d,WindowY:%{private}d",
277 pointerId, item.GetDownTime(), item.IsPressed(), item.GetDisplayX(), item.GetDisplayY(),
278 item.GetWindowX(), item.GetWindowY());
279 }
280 } else {
281 PrintInfoPointerEvent(event);
282 }
283 }
284
PrintInfoPointerEvent(const std::shared_ptr<MMI::PointerEvent> & event)285 void WindowEventChannel::PrintInfoPointerEvent(const std::shared_ptr<MMI::PointerEvent>& event)
286 {
287 if (event == nullptr) {
288 WLOGFE("event is nullptr");
289 return;
290 }
291 std::vector<int32_t> pointerIds = event->GetPointerIds();
292 std::string str;
293 std::vector<uint8_t> buffer = event->GetBuffer();
294 for (const auto &buff : buffer) {
295 str += std::to_string(buff);
296 }
297 WLOGFI("PointerAction:%{public}s,SourceType:%{public}s,ButtonId:%{public}d,"
298 "VerticalAxisValue:%{public}.2f,HorizontalAxisValue:%{public}.2f,"
299 "PointerId:%{public}d,PointerCount:%{public}zu,EventNumber:%{public}d,"
300 "BufferCount:%{public}zu,Buffer:%{public}s",
301 event->DumpPointerAction(), event->DumpSourceType(), event->GetButtonId(),
302 event->GetAxisValue(MMI::PointerEvent::AXIS_TYPE_SCROLL_VERTICAL),
303 event->GetAxisValue(MMI::PointerEvent::AXIS_TYPE_SCROLL_HORIZONTAL),
304 event->GetPointerId(), pointerIds.size(), event->GetId(), buffer.size(), str.c_str());
305
306 for (const auto &pointerId : pointerIds) {
307 MMI::PointerEvent::PointerItem item;
308 if (!event->GetPointerItem(pointerId, item)) {
309 WLOGFE("Invalid pointer: %{public}d.", pointerId);
310 return;
311 }
312 WLOGFI("pointerId:%{public}d,DownTime:%{public}" PRId64 ",IsPressed:%{public}d",
313 pointerId, item.GetDownTime(), item.IsPressed());
314 }
315 }
316
TransferFocusState(bool focusState)317 WSError WindowEventChannel::TransferFocusState(bool focusState)
318 {
319 WLOGFD("WindowEventChannel receive focus state event: %{public}d", static_cast<int>(focusState));
320 if (!sessionStage_) {
321 WLOGFE("session stage is null!");
322 return WSError::WS_ERROR_NULLPTR;
323 }
324 sessionStage_->NotifyFocusStateEvent(focusState);
325 return WSError::WS_OK;
326 }
327
TransferAccessibilityHoverEvent(float pointX,float pointY,int32_t sourceType,int32_t eventType,int64_t timeMs)328 WSError WindowEventChannel::TransferAccessibilityHoverEvent(float pointX, float pointY, int32_t sourceType,
329 int32_t eventType, int64_t timeMs)
330 {
331 if (!sessionStage_) {
332 TLOGE(WmsLogTag::WMS_UIEXT, "session stage is null.");
333 return WSError::WS_ERROR_NULLPTR;
334 }
335 return sessionStage_->NotifyAccessibilityHoverEvent(pointX, pointY, sourceType, eventType, timeMs);
336 }
337
TransferAccessibilityChildTreeRegister(uint32_t windowId,int32_t treeId,int64_t accessibilityId)338 WSError WindowEventChannel::TransferAccessibilityChildTreeRegister(
339 uint32_t windowId, int32_t treeId, int64_t accessibilityId)
340 {
341 if (!sessionStage_) {
342 TLOGE(WmsLogTag::WMS_UIEXT, "session stage is null.");
343 return WSError::WS_ERROR_NULLPTR;
344 }
345 return sessionStage_->NotifyAccessibilityChildTreeRegister(windowId, treeId, accessibilityId);
346 }
347
TransferAccessibilityChildTreeUnregister()348 WSError WindowEventChannel::TransferAccessibilityChildTreeUnregister()
349 {
350 if (!sessionStage_) {
351 TLOGE(WmsLogTag::WMS_UIEXT, "session stage is null.");
352 return WSError::WS_ERROR_NULLPTR;
353 }
354 return sessionStage_->NotifyAccessibilityChildTreeUnregister();
355 }
356
TransferAccessibilityDumpChildInfo(const std::vector<std::string> & params,std::vector<std::string> & info)357 WSError WindowEventChannel::TransferAccessibilityDumpChildInfo(
358 const std::vector<std::string>& params, std::vector<std::string>& info)
359 {
360 if (!sessionStage_) {
361 TLOGE(WmsLogTag::WMS_UIEXT, "session stage is null.");
362 return WSError::WS_ERROR_NULLPTR;
363 }
364 #ifdef ACCESSIBILITY_DUMP_FOR_TEST
365 return sessionStage_->NotifyAccessibilityDumpChildInfo(params, info);
366 #else
367 info.emplace_back("not support in user build variant");
368 return WSError::WS_OK;
369 #endif
370 }
371 } // namespace OHOS::Rosen
372