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/system_session.h"
17
18 #include "common/include/session_permission.h"
19 #include "key_event.h"
20 #include "session/host/include/session.h"
21 #include "window_helper.h"
22 #include "window_manager_hilog.h"
23 #include "parameters.h"
24 #include "pointer_event.h"
25 namespace OHOS::Rosen {
26 namespace {
27 constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, HILOG_DOMAIN_WINDOW, "SystemSession" };
28 } // namespace
29
30 constexpr uint32_t MIN_SYSTEM_WINDOW_WIDTH = 5;
31 constexpr uint32_t MIN_SYSTEM_WINDOW_HEIGHT = 5;
32
SystemSession(const SessionInfo & info,const sptr<SpecificSessionCallback> & specificCallback)33 SystemSession::SystemSession(const SessionInfo& info, const sptr<SpecificSessionCallback>& specificCallback)
34 : SceneSession(info, specificCallback)
35 {
36 TLOGD(WmsLogTag::WMS_LIFE, "Create SystemSession");
37 moveDragController_ = new (std::nothrow) MoveDragController(GetPersistentId());
38 if (moveDragController_ != nullptr && specificCallback != nullptr &&
39 specificCallback->onWindowInputPidChangeCallback_ != nullptr) {
40 moveDragController_->SetNotifyWindowPidChangeCallback(specificCallback_->onWindowInputPidChangeCallback_);
41 }
42 SetMoveDragCallback();
43 }
44
~SystemSession()45 SystemSession::~SystemSession()
46 {
47 TLOGD(WmsLogTag::WMS_LIFE, "~SystemSession, id: %{public}d", GetPersistentId());
48 }
49
UpdateCameraWindowStatus(bool isShowing)50 void SystemSession::UpdateCameraWindowStatus(bool isShowing)
51 {
52 if (specificCallback_ == nullptr) {
53 return;
54 }
55 if (GetWindowType() == WindowType::WINDOW_TYPE_FLOAT_CAMERA) {
56 if (!specificCallback_->onCameraFloatSessionChange_) {
57 return;
58 }
59 TLOGI(WmsLogTag::WMS_SYSTEM, "CameraFloat status: %{public}d, id: %{public}d", isShowing, GetPersistentId());
60 specificCallback_->onCameraFloatSessionChange_(GetSessionProperty()->GetAccessTokenId(), isShowing);
61 } else if (GetWindowType() == WindowType::WINDOW_TYPE_PIP && GetWindowMode() == WindowMode::WINDOW_MODE_PIP) {
62 if (!specificCallback_->onCameraSessionChange_) {
63 return;
64 }
65 auto pipType = GetPiPTemplateInfo().pipTemplateType;
66 if (pipType == static_cast<uint32_t>(PiPTemplateType::VIDEO_CALL) ||
67 pipType == static_cast<uint32_t>(PiPTemplateType::VIDEO_MEETING)) {
68 TLOGI(WmsLogTag::WMS_SYSTEM, "PiPWindow status: %{public}d, id: %{public}d", isShowing, GetPersistentId());
69 specificCallback_->onCameraSessionChange_(GetSessionProperty()->GetAccessTokenId(), isShowing);
70 }
71 } else {
72 TLOGI(WmsLogTag::WMS_SYSTEM, "Skip window type, isShowing: %{public}d", isShowing);
73 }
74 }
75
Show(sptr<WindowSessionProperty> property)76 WSError SystemSession::Show(sptr<WindowSessionProperty> property)
77 {
78 if (!CheckPermissionWithPropertyAnimation(property)) {
79 return WSError::WS_ERROR_NOT_SYSTEM_APP;
80 }
81 auto type = GetWindowType();
82 if (((type == WindowType::WINDOW_TYPE_TOAST) || (type == WindowType::WINDOW_TYPE_FLOAT)) &&
83 !SessionPermission::IsSystemCalling()) {
84 auto parentSession = GetParentSession();
85 if (parentSession == nullptr) {
86 WLOGFW("parent session is null");
87 return WSError::WS_ERROR_INVALID_PARENT;
88 }
89 if (!parentSession->IsSessionForeground()) {
90 WLOGFW("parent session is not in foreground");
91 return WSError::WS_ERROR_INVALID_OPERATION;
92 }
93 }
94 auto task = [weakThis = wptr(this), property]() {
95 auto session = weakThis.promote();
96 if (!session) {
97 WLOGFE("session is null");
98 return WSError::WS_ERROR_DESTROYED_OBJECT;
99 }
100 TLOGI(WmsLogTag::WMS_LIFE, "Show session, id: %{public}d", session->GetPersistentId());
101 // use property from client
102 if (property && property->GetAnimationFlag() == static_cast<uint32_t>(WindowAnimation::CUSTOM)) {
103 session->GetSessionProperty()->SetAnimationFlag(static_cast<uint32_t>(WindowAnimation::CUSTOM));
104 session->NotifyIsCustomAnimationPlaying(true);
105 }
106 session->UpdateCameraWindowStatus(true);
107 session->UpdatePiPWindowStateChanged(true);
108 auto ret = session->SceneSession::Foreground(property);
109 return ret;
110 };
111 PostTask(task, "Show");
112 return WSError::WS_OK;
113 }
114
Hide()115 WSError SystemSession::Hide()
116 {
117 if (!CheckPermissionWithPropertyAnimation(GetSessionProperty())) {
118 return WSError::WS_ERROR_NOT_SYSTEM_APP;
119 }
120 auto type = GetWindowType();
121 if (NeedSystemPermission(type)) {
122 // Do not need to verify the permission to hide the input method status bar.
123 if (!SessionPermission::IsSystemCalling() && type != WindowType::WINDOW_TYPE_INPUT_METHOD_STATUS_BAR) {
124 TLOGE(WmsLogTag::WMS_LIFE, "Hide permission denied id: %{public}d type:%{public}u",
125 GetPersistentId(), type);
126 return WSError::WS_ERROR_INVALID_PERMISSION;
127 }
128 }
129 auto task = [weakThis = wptr(this)]() {
130 auto session = weakThis.promote();
131 if (!session) {
132 TLOGE(WmsLogTag::WMS_LIFE, "session is null");
133 return WSError::WS_ERROR_DESTROYED_OBJECT;
134 }
135 TLOGI(WmsLogTag::WMS_LIFE, "Hide session, id: %{public}d", session->GetPersistentId());
136 auto ret = session->SetActive(false);
137 if (ret != WSError::WS_OK) {
138 return ret;
139 }
140 // background will remove surfaceNode, custom not execute
141 // not animation playing when already background; inactive may be animation playing
142 auto sessionProperty = session->GetSessionProperty();
143 if (sessionProperty &&
144 sessionProperty->GetAnimationFlag() == static_cast<uint32_t>(WindowAnimation::CUSTOM)) {
145 session->NotifyIsCustomAnimationPlaying(true);
146 return WSError::WS_OK;
147 }
148 session->UpdateCameraWindowStatus(false);
149 session->UpdatePiPWindowStateChanged(false);
150 ret = session->SceneSession::Background();
151 return ret;
152 };
153 PostTask(task, "Hide");
154 return WSError::WS_OK;
155 }
156
Disconnect(bool isFromClient,const std::string & identityToken)157 WSError SystemSession::Disconnect(bool isFromClient, const std::string& identityToken)
158 {
159 auto task = [weakThis = wptr(this), isFromClient]() {
160 auto session = weakThis.promote();
161 if (!session) {
162 TLOGE(WmsLogTag::WMS_LIFE, "session is null");
163 return WSError::WS_ERROR_DESTROYED_OBJECT;
164 }
165 TLOGI(WmsLogTag::WMS_LIFE, "Disconnect session, id: %{public}d", session->GetPersistentId());
166 session->SceneSession::Disconnect(isFromClient);
167 session->UpdateCameraWindowStatus(false);
168 session->UpdatePiPWindowStateChanged(false);
169 return WSError::WS_OK;
170 };
171 PostTask(task, "Disconnect");
172 return WSError::WS_OK;
173 }
174
ProcessPointDownSession(int32_t posX,int32_t posY)175 WSError SystemSession::ProcessPointDownSession(int32_t posX, int32_t posY)
176 {
177 const auto& id = GetPersistentId();
178 const auto& type = GetWindowType();
179 auto parentSession = GetParentSession();
180 if (parentSession && parentSession->CheckDialogOnForeground()) {
181 WLOGFI("Parent has dialog foreground, id: %{public}d, type: %{public}d", id, type);
182 parentSession->HandlePointDownDialog();
183 if (!IsTopDialog()) {
184 return WSError::WS_OK;
185 }
186 }
187 auto sessionProperty = GetSessionProperty();
188 if (type == WindowType::WINDOW_TYPE_DIALOG && sessionProperty && sessionProperty->GetRaiseEnabled()) {
189 RaiseToAppTopForPointDown();
190 }
191 TLOGI(WmsLogTag::WMS_LIFE, "id: %{public}d, type: %{public}d", id, type);
192 PresentFocusIfPointDown();
193 return SceneSession::ProcessPointDownSession(posX, posY);
194 }
195
GetMissionId() const196 int32_t SystemSession::GetMissionId() const
197 {
198 auto parentSession = GetParentSession();
199 return parentSession != nullptr ? parentSession->GetPersistentId() : SceneSession::GetMissionId();
200 }
201
TransferKeyEvent(const std::shared_ptr<MMI::KeyEvent> & keyEvent)202 WSError SystemSession::TransferKeyEvent(const std::shared_ptr<MMI::KeyEvent>& keyEvent)
203 {
204 if (!IsSessionValid()) {
205 return WSError::WS_ERROR_INVALID_SESSION;
206 }
207 if (keyEvent == nullptr) {
208 WLOGFE("KeyEvent is nullptr");
209 return WSError::WS_ERROR_NULLPTR;
210 }
211 if (GetWindowType() == WindowType::WINDOW_TYPE_DIALOG) {
212 if (keyEvent->GetKeyCode() == MMI::KeyEvent::KEYCODE_BACK) {
213 return WSError::WS_ERROR_INVALID_PERMISSION;
214 }
215 auto parentSession = GetParentSession();
216 if (parentSession && parentSession->CheckDialogOnForeground() &&
217 !IsTopDialog()) {
218 return WSError::WS_ERROR_INVALID_PERMISSION;
219 }
220 if (!CheckKeyEventDispatch(keyEvent)) {
221 WLOGFW("Do not dispatch the key event.");
222 return WSError::WS_DO_NOTHING;
223 }
224 }
225
226 WSError ret = Session::TransferKeyEvent(keyEvent);
227 return ret;
228 }
229
ProcessBackEvent()230 WSError SystemSession::ProcessBackEvent()
231 {
232 if (!IsSessionValid()) {
233 TLOGD(WmsLogTag::WMS_EVENT, "Session is invalid, id: %{public}d state: %{public}u",
234 GetPersistentId(), GetSessionState());
235 return WSError::WS_ERROR_INVALID_SESSION;
236 }
237 if (GetWindowType() == WindowType::WINDOW_TYPE_DIALOG && !dialogSessionBackGestureEnabled_) {
238 TLOGI(WmsLogTag::WMS_DIALOG, "this is dialog, id: %{public}d", GetPersistentId());
239 return WSError::WS_OK;
240 }
241 if (sessionStage_ == nullptr) {
242 TLOGE(WmsLogTag::WMS_EVENT, "sessionStage_ is nullptr, id = %{public}d.",
243 GetPersistentId());
244 return WSError::WS_ERROR_NULLPTR;
245 }
246 return sessionStage_->HandleBackEvent();
247 }
248
NotifyClientToUpdateRect(const std::string & updateReason,std::shared_ptr<RSTransaction> rsTransaction)249 WSError SystemSession::NotifyClientToUpdateRect(const std::string& updateReason,
250 std::shared_ptr<RSTransaction> rsTransaction)
251 {
252 auto task = [weakThis = wptr(this), rsTransaction, updateReason]() {
253 auto session = weakThis.promote();
254 if (!session) {
255 WLOGFE("session is null");
256 return WSError::WS_ERROR_DESTROYED_OBJECT;
257 }
258 WSError ret = session->NotifyClientToUpdateRectTask(updateReason, rsTransaction);
259 if (ret != WSError::WS_OK) {
260 return ret;
261 }
262 if (session->specificCallback_ != nullptr && session->specificCallback_->onUpdateAvoidArea_ != nullptr) {
263 if (Session::IsScbCoreEnabled()) {
264 session->dirtyFlags_ |= static_cast<uint32_t>(SessionUIDirtyFlag::AVOID_AREA);
265 } else {
266 session->specificCallback_->onUpdateAvoidArea_(session->GetPersistentId());
267 }
268 }
269 return ret;
270 };
271 PostTask(task, "NotifyClientToUpdateRect");
272 return WSError::WS_OK;
273 }
274
CheckKeyEventDispatch(const std::shared_ptr<MMI::KeyEvent> & keyEvent) const275 bool SystemSession::CheckKeyEventDispatch(const std::shared_ptr<MMI::KeyEvent>& keyEvent) const
276 {
277 auto currentRect = winRect_;
278 if (!GetRSVisible() || currentRect.width_ == 0 || currentRect.height_ == 0) {
279 WLOGE("Error size: [width: %{public}d, height: %{public}d], isRSVisible_: %{public}d,"
280 " persistentId: %{public}d",
281 currentRect.width_, currentRect.height_, GetRSVisible(), GetPersistentId());
282 return false;
283 }
284
285 auto parentSession = GetParentSession();
286 if (parentSession == nullptr) {
287 WLOGFW("Dialog parent is null");
288 return false;
289 }
290 auto parentSessionState = parentSession->GetSessionState();
291 if ((parentSessionState != SessionState::STATE_FOREGROUND &&
292 parentSessionState != SessionState::STATE_ACTIVE) ||
293 (state_ != SessionState::STATE_FOREGROUND &&
294 state_ != SessionState::STATE_ACTIVE)) {
295 TLOGE(WmsLogTag::WMS_DIALOG, "Dialog's parent info : [persistentId: %{publicd}d, state:%{public}d];"
296 "Dialog info:[persistentId: %{publicd}d, state:%{public}d]",
297 parentSession->GetPersistentId(), parentSessionState, GetPersistentId(), GetSessionState());
298 return false;
299 }
300 return true;
301 }
302
NeedSystemPermission(WindowType type)303 bool SystemSession::NeedSystemPermission(WindowType type)
304 {
305 return !(type == WindowType::WINDOW_TYPE_SCENE_BOARD || type == WindowType::WINDOW_TYPE_SYSTEM_FLOAT ||
306 type == WindowType::WINDOW_TYPE_SYSTEM_SUB_WINDOW || type == WindowType::WINDOW_TYPE_TOAST ||
307 type == WindowType::WINDOW_TYPE_DRAGGING_EFFECT || type == WindowType::WINDOW_TYPE_APP_LAUNCHING ||
308 type == WindowType::WINDOW_TYPE_PIP);
309 }
310
CheckPointerEventDispatch(const std::shared_ptr<MMI::PointerEvent> & pointerEvent) const311 bool SystemSession::CheckPointerEventDispatch(const std::shared_ptr<MMI::PointerEvent>& pointerEvent) const
312 {
313 auto sessionState = GetSessionState();
314 int32_t action = pointerEvent->GetPointerAction();
315 auto isPC = systemConfig_.uiType_ == UI_TYPE_PC;
316 bool isDialog = WindowHelper::IsDialogWindow(GetWindowType());
317 if (isPC && isDialog && sessionState != SessionState::STATE_FOREGROUND &&
318 sessionState != SessionState::STATE_ACTIVE &&
319 action != MMI::PointerEvent::POINTER_ACTION_LEAVE_WINDOW) {
320 WLOGFW("CheckPointerEventDispatch false, Current Session Info: [persistentId: %{public}d, "
321 "state: %{public}d, action:%{public}d]", GetPersistentId(), GetSessionState(), action);
322 return false;
323 }
324 return true;
325 }
326
UpdatePointerArea(const WSRect & rect)327 void SystemSession::UpdatePointerArea(const WSRect& rect)
328 {
329 auto property = GetSessionProperty();
330 if (!(property->IsDecorEnable() && GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING)) {
331 return;
332 }
333 Session::UpdatePointerArea(rect);
334 }
335
RectCheck(uint32_t curWidth,uint32_t curHeight)336 void SystemSession::RectCheck(uint32_t curWidth, uint32_t curHeight)
337 {
338 uint32_t minWidth = MIN_SYSTEM_WINDOW_WIDTH;
339 uint32_t minHeight = MIN_SYSTEM_WINDOW_HEIGHT;
340 uint32_t maxFloatingWindowSize = GetSystemConfig().maxFloatingWindowSize_;
341 RectSizeCheckProcess(curWidth, curHeight, minWidth, minHeight, maxFloatingWindowSize);
342 }
343
SetDialogSessionBackGestureEnabled(bool isEnabled)344 WSError SystemSession::SetDialogSessionBackGestureEnabled(bool isEnabled)
345 {
346 return PostSyncTask([weakThis = wptr(this), isEnabled]() {
347 auto session = weakThis.promote();
348 if (!session) {
349 WLOGFE("session is null");
350 return WSError::WS_ERROR_DESTROYED_OBJECT;
351 }
352 WindowType windowType = session->GetWindowType();
353 if (windowType != WindowType::WINDOW_TYPE_DIALOG) {
354 TLOGE(WmsLogTag::WMS_DIALOG, "windowType not support. WinId:%{public}u, WindowType:%{public}u",
355 session->GetWindowId(), static_cast<uint32_t>(windowType));
356 return WSError::WS_ERROR_INVALID_CALLING;
357 }
358 session->dialogSessionBackGestureEnabled_ = isEnabled;
359 return WSError::WS_OK;
360 });
361 }
362
IsVisibleForeground() const363 bool SystemSession::IsVisibleForeground() const
364 {
365 if (GetWindowType() == WindowType::WINDOW_TYPE_DIALOG &&
366 parentSession_ && WindowHelper::IsMainWindow(parentSession_->GetWindowType())) {
367 return parentSession_->IsVisibleForeground() && Session::IsVisibleForeground();
368 }
369 return Session::IsVisibleForeground();
370 }
371
UpdatePiPWindowStateChanged(bool isForeground)372 void SystemSession::UpdatePiPWindowStateChanged(bool isForeground)
373 {
374 if (specificCallback_ == nullptr || !specificCallback_->onPiPStateChange_) {
375 return;
376 }
377 if (GetWindowType() == WindowType::WINDOW_TYPE_PIP) {
378 TLOGI(WmsLogTag::WMS_PIP, "pip state changed, bundleName:%{public}s, state:%{public}d",
379 GetSessionInfo().bundleName_.c_str(), isForeground);
380 specificCallback_->onPiPStateChange_(GetSessionInfo().bundleName_, isForeground);
381 } else {
382 TLOGD(WmsLogTag::WMS_PIP, "skip type");
383 }
384 }
385 } // namespace OHOS::Rosen
386