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