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/host/include/scb_system_session.h"
17 
18 #include <hisysevent.h>
19 #include "key_event.h"
20 #include "pointer_event.h"
21 #include <ui/rs_surface_node.h>
22 #include "window_manager_hilog.h"
23 
24 namespace OHOS::Rosen {
25 namespace {
26 constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, HILOG_DOMAIN_WINDOW, "SCBSystemSession" };
27 } // namespace
28 
SCBSystemSession(const SessionInfo & info,const sptr<SpecificSessionCallback> & specificCallback)29 SCBSystemSession::SCBSystemSession(const SessionInfo& info, const sptr<SpecificSessionCallback>& specificCallback)
30     : SceneSession(info, specificCallback)
31 {
32     auto name = sessionInfo_.bundleName_;
33     auto pos = name.find_last_of('.');
34     name = (pos == std::string::npos) ? name : name.substr(pos + 1); // skip '.'
35     if (sessionInfo_.isSystem_) {
36         RSSurfaceNodeConfig config;
37         config.SurfaceNodeName = name;
38         config.surfaceWindowType = SurfaceWindowType::SYSTEM_SCB_WINDOW;
39         surfaceNode_ = Rosen::RSSurfaceNode::Create(config, Rosen::RSSurfaceNodeType::APP_WINDOW_NODE);
40     }
41     WLOGFD("Create SCBSystemSession");
42 }
43 
~SCBSystemSession()44 SCBSystemSession::~SCBSystemSession()
45 {
46     WLOGD("~SCBSystemSession, id: %{public}d", GetPersistentId());
47 }
48 
RegisterBufferAvailableCallback(const SystemSessionBufferAvailableCallback & func)49 void SCBSystemSession::RegisterBufferAvailableCallback(const SystemSessionBufferAvailableCallback& func)
50 {
51     if (surfaceNode_) {
52         TLOGI(WmsLogTag::WMS_MULTI_USER, "Set buffer available callback");
53         surfaceNode_->SetBufferAvailableCallback(func);
54     } else {
55         TLOGE(WmsLogTag::WMS_MULTI_USER, "surfaceNode_ is null");
56     }
57 }
58 
ProcessPointDownSession(int32_t posX,int32_t posY)59 WSError SCBSystemSession::ProcessPointDownSession(int32_t posX, int32_t posY)
60 {
61     const auto& id = GetPersistentId();
62     const auto& type = GetWindowType();
63     WLOGFI("id: %{public}d, type: %{public}d", id, type);
64     PresentFocusIfPointDown();
65     return SceneSession::ProcessPointDownSession(posX, posY);
66 }
67 
NotifyClientToUpdateRect(const std::string & updateReason,std::shared_ptr<RSTransaction> rsTransaction)68 WSError SCBSystemSession::NotifyClientToUpdateRect(const std::string& updateReason,
69     std::shared_ptr<RSTransaction> rsTransaction)
70 {
71     auto task = [weakThis = wptr(this), rsTransaction, updateReason]() {
72         auto session = weakThis.promote();
73         if (!session) {
74             WLOGFE("session is null");
75             return WSError::WS_ERROR_DESTROYED_OBJECT;
76         }
77         WSError ret = session->NotifyClientToUpdateRectTask(updateReason, rsTransaction);
78         if (session->specificCallback_ != nullptr && session->specificCallback_->onUpdateAvoidArea_ != nullptr &&
79             session->specificCallback_->onClearDisplayStatusBarTemporarilyFlags_ != nullptr) {
80             if (Session::IsScbCoreEnabled()) {
81                 session->dirtyFlags_ |= static_cast<uint32_t>(SessionUIDirtyFlag::AVOID_AREA);
82             } else {
83                 session->specificCallback_->onUpdateAvoidArea_(session->GetPersistentId());
84             }
85             session->specificCallback_->onClearDisplayStatusBarTemporarilyFlags_();
86         }
87         if (session->GetWindowType() == WindowType::WINDOW_TYPE_KEYBOARD_PANEL &&
88             session->keyboardPanelRectUpdateCallback_ && session->isKeyboardPanelEnabled_) {
89             session->keyboardPanelRectUpdateCallback_();
90         }
91         return ret;
92     };
93     PostTask(task, "NotifyClientToUpdateRect");
94     return WSError::WS_OK;
95 }
96 
SetKeyboardPanelRectUpdateCallback(const KeyboardPanelRectUpdateCallback & func)97 void SCBSystemSession::SetKeyboardPanelRectUpdateCallback(const KeyboardPanelRectUpdateCallback& func)
98 {
99     keyboardPanelRectUpdateCallback_ = func;
100 }
101 
BindKeyboardSession(sptr<SceneSession> session)102 void SCBSystemSession::BindKeyboardSession(sptr<SceneSession> session)
103 {
104     if (session == nullptr) {
105         TLOGE(WmsLogTag::WMS_KEYBOARD, "session is nullptr");
106         return;
107     }
108     keyboardSession_ = session;
109     KeyboardPanelRectUpdateCallback onKeyboardPanelRectUpdate = [this]() {
110         if (this->keyboardSession_ != nullptr) {
111             this->keyboardSession_->OnKeyboardPanelUpdated();
112         }
113     };
114     SetKeyboardPanelRectUpdateCallback(onKeyboardPanelRectUpdate);
115     TLOGI(WmsLogTag::WMS_KEYBOARD, "Success, id: %{public}d", keyboardSession_->GetPersistentId());
116 }
117 
GetKeyboardSession() const118 sptr<SceneSession> SCBSystemSession::GetKeyboardSession() const
119 {
120     return keyboardSession_;
121 }
122 
PresentFocusIfPointDown()123 void SCBSystemSession::PresentFocusIfPointDown()
124 {
125     WLOGFI("PresentFocusIfPointDown, id: %{public}d, type: %{public}d", GetPersistentId(), GetWindowType());
126     if (!isFocused_ && GetFocusable()) {
127         FocusChangeReason reason = FocusChangeReason::CLICK;
128         NotifyRequestFocusStatusNotifyManager(true, false, reason);
129         NotifyClick();
130     }
131 }
132 
TransferKeyEvent(const std::shared_ptr<MMI::KeyEvent> & keyEvent)133 WSError SCBSystemSession::TransferKeyEvent(const std::shared_ptr<MMI::KeyEvent>& keyEvent)
134 {
135     if (keyEvent == nullptr) {
136         WLOGFE("KeyEvent is nullptr");
137         return WSError::WS_ERROR_NULLPTR;
138     }
139 
140     WSError ret = Session::TransferKeyEvent(keyEvent);
141     return ret;
142 }
143 
PresentFoucusIfNeed(int32_t pointerAction)144 void SCBSystemSession::PresentFoucusIfNeed(int32_t pointerAction)
145 {
146     WLOGFD("OnClick down, id: %{public}d", GetPersistentId());
147     if (pointerAction == MMI::PointerEvent::POINTER_ACTION_DOWN ||
148         pointerAction == MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN) {
149         if (!isFocused_ && GetFocusable()) {
150             FocusChangeReason reason = FocusChangeReason::CLICK;
151             NotifyRequestFocusStatusNotifyManager(true, false, reason);
152             NotifyClick();
153         }
154     }
155 }
156 
UpdateFocus(bool isFocused)157 WSError SCBSystemSession::UpdateFocus(bool isFocused)
158 {
159     if (isFocused_ == isFocused) {
160         TLOGD(WmsLogTag::WMS_FOCUS, "Session focus do not change");
161         return WSError::WS_DO_NOTHING;
162     }
163     isFocused_ = isFocused;
164     // notify scb arkui focus
165     if (isFocused) {
166         HiSysEventWrite(
167             OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER,
168             "FOCUS_WINDOW",
169             OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
170             "PID", getpid(),
171             "UID", getuid(),
172             "BUNDLE_NAME", sessionInfo_.bundleName_);
173         NotifyUIRequestFocus();
174     } else {
175         NotifyUILostFocus();
176     }
177     return WSError::WS_OK;
178 }
179 
UpdateWindowMode(WindowMode mode)180 WSError SCBSystemSession::UpdateWindowMode(WindowMode mode)
181 {
182     WLOGFD("session is system, id: %{public}d, mode: %{public}d, name: %{public}s, state: %{public}u",
183         GetPersistentId(), static_cast<int32_t>(mode), sessionInfo_.bundleName_.c_str(), GetSessionState());
184     return WSError::WS_ERROR_INVALID_SESSION;
185 }
186 
SetSystemSceneBlockingFocus(bool blocking)187 WSError SCBSystemSession::SetSystemSceneBlockingFocus(bool blocking)
188 {
189     TLOGD(WmsLogTag::WMS_FOCUS, "Session set blocking focus, id: %{public}d, mode: %{public}d",
190         GetPersistentId(), blocking);
191     blockingFocus_ = blocking;
192     return WSError::WS_OK;
193 }
194 
UpdatePointerArea(const WSRect & rect)195 void SCBSystemSession::UpdatePointerArea(const WSRect& rect)
196 {
197     // scb system session do nothing
198     return;
199 }
200 
SetSkipSelfWhenShowOnVirtualScreen(bool isSkip)201 void SCBSystemSession::SetSkipSelfWhenShowOnVirtualScreen(bool isSkip)
202 {
203     TLOGD(WmsLogTag::WMS_SCB, "Set Skip Self, isSkip: %{public}d", isSkip);
204     auto task = [weakThis = wptr(this), isSkip]() {
205         auto session = weakThis.promote();
206         if (!session) {
207             TLOGE(WmsLogTag::WMS_SCB, "session is null");
208             return WSError::WS_ERROR_DESTROYED_OBJECT;
209         }
210         std::shared_ptr<RSSurfaceNode> surfaceNode = session->GetSurfaceNode();
211         if (!surfaceNode) {
212             TLOGE(WmsLogTag::WMS_SCB, "surfaceNode_ is null");
213             return WSError::WS_OK;
214         }
215         if (session->specificCallback_ != nullptr
216             && session->specificCallback_->onSetSkipSelfWhenShowOnVirtualScreen_ != nullptr) {
217             session->specificCallback_->onSetSkipSelfWhenShowOnVirtualScreen_(surfaceNode->GetId(), isSkip);
218         }
219         return WSError::WS_OK;
220     };
221     PostTask(task, "SetSkipSelf");
222 }
223 
GetSurfaceNode()224 std::shared_ptr<RSSurfaceNode> SCBSystemSession::GetSurfaceNode()
225 {
226     if (!surfaceNode_) {
227         TLOGE(WmsLogTag::WMS_SCB, "surfaceNode_ is null");
228         return nullptr;
229     }
230     return surfaceNode_;
231 }
232 
IsVisibleForeground() const233 bool SCBSystemSession::IsVisibleForeground() const
234 {
235     return isVisible_;
236 }
237 
NotifyClientToUpdateAvoidArea()238 void SCBSystemSession::NotifyClientToUpdateAvoidArea()
239 {
240     SceneSession::NotifyClientToUpdateAvoidArea();
241     if (GetWindowType() == WindowType::WINDOW_TYPE_KEYBOARD_PANEL &&
242         keyboardPanelRectUpdateCallback_ && isKeyboardPanelEnabled_) {
243         keyboardPanelRectUpdateCallback_();
244     }
245 }
246 
SyncScenePanelGlobalPosition(bool needSync)247 void SCBSystemSession::SyncScenePanelGlobalPosition(bool needSync)
248 {
249     TLOGI(WmsLogTag::WMS_PIPELINE, "change isNeedSyncGlobalPos from %{public}d to %{public}d",
250         isNeedSyncGlobalPos_, needSync);
251     if (isNeedSyncGlobalPos_ != needSync) {
252         isNeedSyncGlobalPos_ = needSync;
253     }
254 }
255 } // namespace OHOS::Rosen
256