/* * Copyright (c) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "session/host/include/scene_session.h" #include #include #include #ifdef IMF_ENABLE #include #endif // IMF_ENABLE #include #include #include #include #include "../../proxy/include/window_info.h" #include "common/include/session_permission.h" #include "interfaces/include/ws_common.h" #include "pixel_map.h" #include "pip_util.h" #include "session/host/include/scene_persistent_storage.h" #include "session/host/include/session_utils.h" #include "display_manager.h" #include "session_helper.h" #include "window_helper.h" #include "window_manager_hilog.h" #include "wm_math.h" #include #include "singleton_container.h" #include "pip_report.h" namespace OHOS::Rosen { namespace { constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, HILOG_DOMAIN_WINDOW, "SceneSession" }; const std::string DLP_INDEX = "ohos.dlp.params.index"; } // namespace MaximizeMode SceneSession::maximizeMode_ = MaximizeMode::MODE_RECOVER; wptr SceneSession::enterSession_ = nullptr; std::mutex SceneSession::enterSessionMutex_; std::map SceneSession::windowDragHotAreaMap_; static bool g_enableForceUIFirst = system::GetParameter("window.forceUIFirst.enabled", "1") == "1"; SceneSession::SceneSession(const SessionInfo& info, const sptr& specificCallback) : Session(info) { GeneratePersistentId(false, info.persistentId_); specificCallback_ = specificCallback; SetCollaboratorType(info.collaboratorType_); WLOGFI("[WMSLife] Create session, id: %{public}d", GetPersistentId()); } SceneSession::~SceneSession() { WLOGI("[WMSLife] ~SceneSession, id: %{public}d", GetPersistentId()); } WSError SceneSession::Connect(const sptr& sessionStage, const sptr& eventChannel, const std::shared_ptr& surfaceNode, SystemSessionConfig& systemConfig, sptr property, sptr token, int32_t pid, int32_t uid) { // Get pid and uid before posting task. pid = pid == -1 ? IPCSkeleton::GetCallingRealPid() : pid; uid = uid == -1 ? IPCSkeleton::GetCallingUid() : uid; auto task = [weakThis = wptr(this), sessionStage, eventChannel, surfaceNode, &systemConfig, property, token, pid, uid]() { auto session = weakThis.promote(); if (!session) { WLOGFE("[WMSLife] session is null"); return WSError::WS_ERROR_DESTROYED_OBJECT; } auto ret = session->Session::Connect( sessionStage, eventChannel, surfaceNode, systemConfig, property, token, pid, uid); if (ret != WSError::WS_OK) { return ret; } session->NotifyPropertyWhenConnect(); return ret; }; return PostSyncTask(task, "Connect"); } WSError SceneSession::Reconnect(const sptr& sessionStage, const sptr& eventChannel, const std::shared_ptr& surfaceNode, sptr property, sptr token, int32_t pid, int32_t uid) { return PostSyncTask([weakThis = wptr(this), sessionStage, eventChannel, surfaceNode, property, token, pid, uid]() { auto session = weakThis.promote(); if (!session) { WLOGFE("session is null"); return WSError::WS_ERROR_DESTROYED_OBJECT; } return session->Session::Reconnect(sessionStage, eventChannel, surfaceNode, property, token, pid, uid); }); } WSError SceneSession::Foreground(sptr property) { // return when screen is locked and show without ShowWhenLocked flag if (GetWindowType() == WindowType::WINDOW_TYPE_APP_MAIN_WINDOW && GetStateFromManager(ManagerState::MANAGER_STATE_SCREEN_LOCKED) && !IsShowWhenLocked() && sessionInfo_.bundleName_.find("startupguide") == std::string::npos && sessionInfo_.bundleName_.find("samplemanagement") == std::string::npos) { WLOGFW("[WMSLife] Foreground failed: Screen is locked, session %{public}d show without ShowWhenLocked flag", GetPersistentId()); return WSError::WS_ERROR_INVALID_SESSION; } auto task = [weakThis = wptr(this), property]() { auto session = weakThis.promote(); if (!session) { WLOGFE("[WMSLife] session or property is null"); return WSError::WS_ERROR_DESTROYED_OBJECT; } if (property && session->GetSessionProperty()) { session->GetSessionProperty()->SetWindowMode(property->GetWindowMode()); session->GetSessionProperty()->SetDecorEnable(property->IsDecorEnable()); } if (property) { weakThis->SetTextFieldAvoidInfo(property->GetTextFieldPositionY(), property->GetTextFieldHeight()); } auto ret = session->Session::Foreground(property); if (ret != WSError::WS_OK) { return ret; } auto sessionProperty = session->GetSessionProperty(); if (session->leashWinSurfaceNode_ && sessionProperty) { bool lastPrivacyMode = sessionProperty->GetPrivacyMode() || sessionProperty->GetSystemPrivacyMode(); session->leashWinSurfaceNode_->SetSecurityLayer(lastPrivacyMode); } if (session->specificCallback_ != nullptr) { session->specificCallback_->onUpdateAvoidArea_(session->GetPersistentId()); session->specificCallback_->onWindowInfoUpdate_( session->GetPersistentId(), WindowUpdateType::WINDOW_UPDATE_ADDED); } return WSError::WS_OK; }; PostTask(task, "Foreground"); return WSError::WS_OK; } WSError SceneSession::Background() { auto task = [weakThis = wptr(this)]() { auto session = weakThis.promote(); if (!session) { WLOGFE("[WMSLife] session is null"); return WSError::WS_ERROR_DESTROYED_OBJECT; } auto ret = session->Session::Background(); if (ret != WSError::WS_OK) { return ret; } if (WindowHelper::IsMainWindow(session->GetWindowType())) { session->snapshot_ = session->Snapshot(); if (session->scenePersistence_ && session->snapshot_) { const std::function func = std::bind(&Session::ResetSnapshot, session); session->scenePersistence_->SaveSnapshot(session->snapshot_, func); } } session->snapshot_.reset(); if (session->specificCallback_ != nullptr) { session->specificCallback_->onUpdateAvoidArea_(session->GetPersistentId()); session->specificCallback_->onWindowInfoUpdate_( session->GetPersistentId(), WindowUpdateType::WINDOW_UPDATE_REMOVED); } return WSError::WS_OK; }; PostTask(task, "Background"); return WSError::WS_OK; } void SceneSession::ClearSpecificSessionCbMap() { auto task = [weakThis = wptr(this)]() { auto session = weakThis.promote(); if (!session) { WLOGFE("[WMSSystem] session is null"); return; } if (session->sessionChangeCallback_ && session->sessionChangeCallback_->clearCallbackFunc_) { session->sessionChangeCallback_->clearCallbackFunc_(true, session->GetPersistentId()); WLOGFD("[WMSSystem] ClearCallbackMap, id: %{public}d", session->GetPersistentId()); } else { WLOGFE("[WMSSystem] get callback failed, id: %{public}d", session->GetPersistentId()); } }; PostTask(task, "ClearSpecificSessionCbMap"); } WSError SceneSession::Disconnect(bool isFromClient) { PostTask([weakThis = wptr(this), isFromClient]() { auto session = weakThis.promote(); if (!session) { WLOGFE("[WMSLife] session is null"); return WSError::WS_ERROR_DESTROYED_OBJECT; } if (isFromClient) { WLOGFI("[WMSLife] Client need notify destroy session, id: %{public}d", session->GetPersistentId()); session->SetSessionState(SessionState::STATE_DISCONNECT); return WSError::WS_OK; } auto state = session->GetSessionState(); auto isMainWindow = SessionHelper::IsMainWindow(session->GetWindowType()); if (session->needSnapshot_ || (state == SessionState::STATE_ACTIVE && isMainWindow)) { session->snapshot_ = session->Snapshot(); if (session->scenePersistence_ && session->snapshot_) { const std::function func = std::bind(&Session::ResetSnapshot, session); session->scenePersistence_->SaveSnapshot(session->snapshot_, func); } } if (WindowHelper::IsPipWindow(session->GetWindowType()) && session->GetWindowMode() == WindowMode::WINDOW_MODE_PIP) { session->SavePiPRectInfo(); } session->Session::Disconnect(isFromClient); session->snapshot_.reset(); session->isTerminating = false; return WSError::WS_OK; }, "Disconnect"); return WSError::WS_OK; } WSError SceneSession::UpdateActiveStatus(bool isActive) { auto task = [weakThis = wptr(this), isActive]() { auto session = weakThis.promote(); if (!session) { WLOGFE("[WMSCom] session is null"); return WSError::WS_ERROR_DESTROYED_OBJECT; } if (!session->IsSessionValid()) { return WSError::WS_ERROR_INVALID_SESSION; } if (isActive == session->isActive_) { WLOGFD("[WMSCom] Session active do not change: %{public}d", isActive); return WSError::WS_DO_NOTHING; } WSError ret = WSError::WS_DO_NOTHING; if (isActive && session->GetSessionState() == SessionState::STATE_FOREGROUND) { session->UpdateSessionState(SessionState::STATE_ACTIVE); session->isActive_ = isActive; ret = WSError::WS_OK; } if (!isActive && session->GetSessionState() == SessionState::STATE_ACTIVE) { session->UpdateSessionState(SessionState::STATE_INACTIVE); session->isActive_ = isActive; ret = WSError::WS_OK; } WLOGFI("[WMSCom] UpdateActiveStatus, isActive: %{public}d, state: %{public}u", session->isActive_, session->GetSessionState()); return ret; }; PostTask(task, "UpdateActiveStatus:" + std::to_string(isActive)); return WSError::WS_OK; } WSError SceneSession::OnSessionEvent(SessionEvent event) { auto task = [weakThis = wptr(this), event]() { auto session = weakThis.promote(); if (!session) { WLOGFE("[WMSCom] session is null"); return WSError::WS_ERROR_DESTROYED_OBJECT; } WLOGFI("[WMSCom] SceneSession OnSessionEvent event: %{public}d", static_cast(event)); if (event == SessionEvent::EVENT_START_MOVE && session->moveDragController_ && !session->moveDragController_->GetStartDragFlag()) { HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "SceneSession::StartMove"); session->moveDragController_->InitMoveDragProperty(); session->moveDragController_->SetStartMoveFlag(true); session->moveDragController_->ClacFirstMoveTargetRect(session->winRect_); } if (session->sessionChangeCallback_ && session->sessionChangeCallback_->OnSessionEvent_) { session->sessionChangeCallback_->OnSessionEvent_(static_cast(event)); } return WSError::WS_OK; }; PostTask(task, "OnSessionEvent:" + std::to_string(static_cast(event))); return WSError::WS_OK; } void SceneSession::RegisterSessionChangeCallback(const sptr& sessionChangeCallback) { std::lock_guard guard(sessionChangeCbMutex_); sessionChangeCallback_ = sessionChangeCallback; } WSError SceneSession::SetGlobalMaximizeMode(MaximizeMode mode) { auto task = [weakThis = wptr(this), mode]() { auto session = weakThis.promote(); if (!session) { WLOGFE("[WMSCom] session is null"); return WSError::WS_ERROR_DESTROYED_OBJECT; } WLOGFD("[WMSCom] mode: %{public}u", static_cast(mode)); session->maximizeMode_ = mode; ScenePersistentStorage::Insert("maximize_state", static_cast(session->maximizeMode_), ScenePersistentStorageType::MAXIMIZE_STATE); return WSError::WS_OK; }; return PostSyncTask(task, "SetGlobalMaximizeMode"); } WSError SceneSession::GetGlobalMaximizeMode(MaximizeMode &mode) { auto task = [weakThis = wptr(this), &mode]() { auto session = weakThis.promote(); if (!session) { WLOGFE("[WMSCom] session is null"); return WSError::WS_ERROR_DESTROYED_OBJECT; } mode = maximizeMode_; WLOGFD("[WMSCom] mode: %{public}u", static_cast(mode)); return WSError::WS_OK; }; return PostSyncTask(task, "GetGlobalMaximizeMode"); } WSError SceneSession::SetAspectRatio(float ratio) { auto task = [weakThis = wptr(this), ratio]() { auto session = weakThis.promote(); if (!session) { WLOGFE("[WMSCom] session is null"); return WSError::WS_ERROR_DESTROYED_OBJECT; } if (!session->GetSessionProperty()) { WLOGE("[WMSCom] SetAspectRatio failed because property is null"); return WSError::WS_ERROR_NULLPTR; } WLOGFI("[WMSCom] ratio: %{public}f", ratio); float vpr = 1.5f; // 1.5f: default virtual pixel ratio auto display = DisplayManager::GetInstance().GetDefaultDisplay(); if (display) { vpr = display->GetVirtualPixelRatio(); WLOGD("vpr = %{public}f", vpr); } if (!MathHelper::NearZero(ratio)) { auto limits = session->GetSessionProperty()->GetWindowLimits(); if (session->IsDecorEnable()) { if (limits.minWidth_ && limits.maxHeight_ && MathHelper::LessNotEqual(ratio, SessionUtils::ToLayoutWidth(limits.minWidth_, vpr) / SessionUtils::ToLayoutHeight(limits.maxHeight_, vpr))) { WLOGE("Failed, because aspectRatio is smaller than minWidth/maxHeight"); return WSError::WS_ERROR_INVALID_PARAM; } else if (limits.minHeight_ && limits.maxWidth_ && MathHelper::GreatNotEqual(ratio, SessionUtils::ToLayoutWidth(limits.maxWidth_, vpr) / SessionUtils::ToLayoutHeight(limits.minHeight_, vpr))) { WLOGE("Failed, because aspectRatio is bigger than maxWidth/minHeight"); return WSError::WS_ERROR_INVALID_PARAM; } } else { if (limits.minWidth_ && limits.maxHeight_ && MathHelper::LessNotEqual(ratio, static_cast(limits.minWidth_) / limits.maxHeight_)) { WLOGE("Failed, because aspectRatio is smaller than minWidth/maxHeight"); return WSError::WS_ERROR_INVALID_PARAM; } else if (limits.minHeight_ && limits.maxWidth_ && MathHelper::GreatNotEqual(ratio, static_cast(limits.maxWidth_) / limits.minHeight_)) { WLOGE("Failed, because aspectRatio is bigger than maxWidth/minHeight"); return WSError::WS_ERROR_INVALID_PARAM; } } } session->aspectRatio_ = ratio; if (session->moveDragController_) { session->moveDragController_->SetAspectRatio(ratio); } session->SaveAspectRatio(session->aspectRatio_); WSRect fixedRect = session->winRect_; WLOGFI("[WMSLayout] Before fixing, the id:%{public}d, the current rect: %{public}s", session->GetPersistentId(), fixedRect.ToString().c_str()); if (session->FixRectByAspectRatio(fixedRect)) { WLOGFI("[WMSLayout] After fixing, the id:%{public}d, the fixed rect: %{public}s", session->GetPersistentId(), fixedRect.ToString().c_str()); session->NotifySessionRectChange(fixedRect, SizeChangeReason::RESIZE); } return WSError::WS_OK; }; return PostSyncTask(task, "SetAspectRatio"); } WSError SceneSession::UpdateRect(const WSRect& rect, SizeChangeReason reason, const std::shared_ptr& rsTransaction) { auto task = [weakThis = wptr(this), rect, reason, rsTransaction]() { auto session = weakThis.promote(); if (!session) { WLOGFE("session is null"); return WSError::WS_ERROR_DESTROYED_OBJECT; } if (session->winRect_ == rect) { WLOGFI("[WMSLayout] skip same rect update id:%{public}d rect:%{public}s!", session->GetPersistentId(), rect.ToString().c_str()); return WSError::WS_OK; } if (rect.IsInvalid()) { WLOGFE("[WMSLayout] id:%{public}d rect:%{public}s is invalid", session->GetPersistentId(), rect.ToString().c_str()); return WSError::WS_ERROR_INVALID_PARAM; } HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "SceneSession::UpdateRect%d [%d, %d, %u, %u]", session->GetPersistentId(), rect.posX_, rect.posY_, rect.width_, rect.height_); // position change no need to notify client, since frame layout finish will notify if (NearEqual(rect.width_, session->winRect_.width_) && NearEqual(rect.height_, session->winRect_.height_)) { WLOGFI("[WMSLayout] position change no need notify client id:%{public}d, rect:%{public}s, \ preRect: %{public}s", session->GetPersistentId(), rect.ToString().c_str(), session->winRect_.ToString().c_str()); session->winRect_ = rect; session->isDirty_ = true; } else { session->winRect_ = rect; session->NotifyClientToUpdateRect(rsTransaction); } WLOGFD("[WMSLayout] id:%{public}d, reason:%{public}d, rect:%{public}s", session->GetPersistentId(), session->reason_, rect.ToString().c_str()); return WSError::WS_OK; }; PostTask(task, "UpdateRect" + GetRectInfo(rect)); return WSError::WS_OK; } WSError SceneSession::NotifyClientToUpdateRect(std::shared_ptr rsTransaction) { auto task = [weakThis = wptr(this), rsTransaction]() { auto session = weakThis.promote(); if (!session) { WLOGFE("session is null"); return WSError::WS_ERROR_DESTROYED_OBJECT; } WLOGD("[WMSLayout] NotifyClientToUpdateRect id:%{public}d, reason:%{public}d, rect:%{public}s", session->GetPersistentId(), session->reason_, session->winRect_.ToString().c_str()); bool isMoveOrDrag = session->moveDragController_ && (session->moveDragController_->GetStartDragFlag() || session->moveDragController_->GetStartMoveFlag()); if (isMoveOrDrag && session->reason_ == SizeChangeReason::UNDEFINED) { WLOGFD("[WMSLayout] skip redundant rect update!"); return WSError::WS_ERROR_REPEAT_OPERATION; } WSError ret = WSError::WS_OK; HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "SceneSession::NotifyClientToUpdateRect%d [%d, %d, %u, %u] reason:%u", session->GetPersistentId(), session->winRect_.posX_, session->winRect_.posY_, session->winRect_.width_, session->winRect_.height_, session->reason_); // once reason is undefined, not use rsTransaction // when rotation, sync cnt++ in marshalling. Although reason is undefined caused by resize if (session->reason_ == SizeChangeReason::UNDEFINED || session->reason_ == SizeChangeReason::MOVE) { ret = session->Session::UpdateRect(session->winRect_, session->reason_, nullptr); } else { ret = session->Session::UpdateRect(session->winRect_, session->reason_, rsTransaction); } if ((ret == WSError::WS_OK || session->sessionInfo_.isSystem_) && session->specificCallback_ != nullptr) { session->specificCallback_->onUpdateAvoidArea_(session->GetPersistentId()); } // clear after use if (ret == WSError::WS_OK || session->sessionInfo_.isSystem_) { session->reason_ = SizeChangeReason::UNDEFINED; session->isDirty_ = false; } return ret; }; PostTask(task, "NotifyClientToUpdateRect"); return WSError::WS_OK; } bool SceneSession::UpdateInputMethodSessionRect(const WSRect&rect, WSRect& newWinRect, WSRect& newRequestRect) { SessionGravity gravity; uint32_t percent = 0; GetSessionProperty()->GetSessionGravity(gravity, percent); if (GetWindowType() == WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT && (gravity == SessionGravity::SESSION_GRAVITY_BOTTOM || gravity == SessionGravity::SESSION_GRAVITY_DEFAULT)) { auto defaultDisplayInfo = DisplayManager::GetInstance().GetDefaultDisplay(); if (defaultDisplayInfo == nullptr) { WLOGFE("[WMSInput] defaultDisplayInfo is nullptr"); return false; } newWinRect.width_ = (gravity == SessionGravity::SESSION_GRAVITY_BOTTOM) ? defaultDisplayInfo->GetWidth() : rect.width_; newRequestRect.width_ = newWinRect.width_; newWinRect.height_ = (gravity == SessionGravity::SESSION_GRAVITY_BOTTOM && percent != 0) ? static_cast(defaultDisplayInfo->GetHeight()) * percent / 100u : rect.height_; newRequestRect.height_ = newWinRect.height_; newWinRect.posX_ = (gravity == SessionGravity::SESSION_GRAVITY_BOTTOM) ? 0 : newRequestRect.posX_; newRequestRect.posX_ = newWinRect.posX_; newWinRect.posY_ = defaultDisplayInfo->GetHeight() - static_cast(newWinRect.height_); newRequestRect.posY_ = newWinRect.posY_; WLOGFI("[WMSInput] rect: %{public}s, newRequestRect: %{public}s, " "newWinRect: %{public}s", rect.ToString().c_str(), newRequestRect.ToString().c_str(), newWinRect.ToString().c_str()); return true; } WLOGFD("There is no need to update input rect"); return false; } void SceneSession::SetSessionRectChangeCallback(const NotifySessionRectChangeFunc& func) { auto task = [weakThis = wptr(this), func]() { auto session = weakThis.promote(); if (!session) { WLOGFE("session is null"); return WSError::WS_ERROR_DESTROYED_OBJECT; } session->sessionRectChangeFunc_ = func; if (session->sessionRectChangeFunc_ && session->GetWindowType() != WindowType::WINDOW_TYPE_APP_MAIN_WINDOW) { auto reason = SizeChangeReason::UNDEFINED; auto rect = session->GetSessionRequestRect(); if (rect.width_ == 0 && rect.height_ == 0) { reason = SizeChangeReason::MOVE; } session->sessionRectChangeFunc_(session->GetSessionRequestRect(), reason); } return WSError::WS_OK; }; PostTask(task, "SetSessionRectChangeCallback"); } WSError SceneSession::UpdateSessionRect(const WSRect& rect, const SizeChangeReason& reason) { auto task = [weakThis = wptr(this), rect, reason]() { auto session = weakThis.promote(); if (!session) { WLOGFE("[WMSLayout] session is null"); return WSError::WS_ERROR_DESTROYED_OBJECT; } auto newWinRect = session->winRect_; auto newRequestRect = session->GetSessionRequestRect(); SizeChangeReason newReason = reason; if (reason == SizeChangeReason::MOVE) { newWinRect.posX_ = rect.posX_; newWinRect.posY_ = rect.posY_; newRequestRect.posX_ = rect.posX_; newRequestRect.posY_ = rect.posY_; session->SetSessionRect(newWinRect); session->SetSessionRequestRect(newRequestRect); session->NotifySessionRectChange(newRequestRect, reason); } else if (reason == SizeChangeReason::RESIZE) { bool needUpdateInputMethod = session->UpdateInputMethodSessionRect(rect, newWinRect, newRequestRect); if (needUpdateInputMethod) { newReason = SizeChangeReason::UNDEFINED; WLOGFD("[WMSInput] Input rect has totally changed, need to modify reason, id: %{public}d", session->GetPersistentId()); } else if (rect.width_ > 0 && rect.height_ > 0) { newWinRect.width_ = rect.width_; newWinRect.height_ = rect.height_; newRequestRect.width_ = rect.width_; newRequestRect.height_ = rect.height_; } session->SetSessionRect(newWinRect); session->SetSessionRequestRect(newRequestRect); session->NotifySessionRectChange(newRequestRect, newReason); } else { session->SetSessionRect(rect); session->NotifySessionRectChange(rect, reason); } WLOGFI("[WMSLayout] Id: %{public}d, reason: %{public}d, newReason: %{public}d, rect: %{public}s, " "newRequestRect: %{public}s, newWinRect: %{public}s", session->GetPersistentId(), reason, newReason, rect.ToString().c_str(), newRequestRect.ToString().c_str(), newWinRect.ToString().c_str()); return WSError::WS_OK; }; PostTask(task, "UpdateSessionRect" + GetRectInfo(rect)); return WSError::WS_OK; } WSError SceneSession::RaiseToAppTop() { if (!SessionPermission::IsSystemCalling()) { WLOGFE("raise to app top permission denied!"); return WSError::WS_ERROR_NOT_SYSTEM_APP; } auto task = [weakThis = wptr(this)]() { auto session = weakThis.promote(); if (!session) { WLOGFE("session is null"); return WSError::WS_ERROR_DESTROYED_OBJECT; } if (session->sessionChangeCallback_ && session->sessionChangeCallback_->onRaiseToTop_) { WLOGFI("[WMSSub] id: %{public}d", session->GetPersistentId()); session->sessionChangeCallback_->onRaiseToTop_(); } return WSError::WS_OK; }; return PostSyncTask(task, "RaiseToAppTop"); } WSError SceneSession::RaiseAboveTarget(int32_t subWindowId) { if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) { WLOGFE("RaiseAboveTarget permission denied!"); return WSError::WS_ERROR_NOT_SYSTEM_APP; } auto task = [weakThis = wptr(this), subWindowId]() { auto session = weakThis.promote(); if (!session) { WLOGFE("session is null"); return WSError::WS_ERROR_DESTROYED_OBJECT; } if (session->sessionChangeCallback_ && session->sessionChangeCallback_->onRaiseAboveTarget_) { session->sessionChangeCallback_->onRaiseAboveTarget_(subWindowId); } return WSError::WS_OK; }; return PostSyncTask(task, "RaiseAboveTarget"); } WSError SceneSession::BindDialogSessionTarget(const sptr& sceneSession) { if (sceneSession == nullptr) { WLOGFE("[WMSDialog] dialog session is null"); return WSError::WS_ERROR_NULLPTR; } if (sessionChangeCallback_ != nullptr && sessionChangeCallback_->onBindDialogTarget_) { WLOGFI("[WMSDialog] id: %{public}d", sceneSession->GetPersistentId()); sessionChangeCallback_->onBindDialogTarget_(sceneSession); } return WSError::WS_OK; } WSError SceneSession::SetSystemBarProperty(WindowType type, SystemBarProperty systemBarProperty) { auto property = GetSessionProperty(); if (property == nullptr) { return WSError::WS_ERROR_NULLPTR; } property->SetSystemBarProperty(type, systemBarProperty); WLOGFI("[WMSImms]SceneSession SetSystemBarProperty persistentId():%{public}u type:%{public}u" "enable:%{public}u bgColor:%{public}x Color:%{public}x", GetPersistentId(), static_cast(type), systemBarProperty.enable_, systemBarProperty.backgroundColor_, systemBarProperty.contentColor_); if (sessionChangeCallback_ != nullptr && sessionChangeCallback_->OnSystemBarPropertyChange_) { sessionChangeCallback_->OnSystemBarPropertyChange_(property->GetSystemBarProperty()); } return WSError::WS_OK; } void SceneSession::NotifyPropertyWhenConnect() { WLOGFI("Notify property when connect."); auto property = GetSessionProperty(); if (property == nullptr) { WLOGFD("id: %{public}d property is nullptr", persistentId_); return; } NotifySessionFocusableChange(property->GetFocusable()); NotifySessionTouchableChange(property->GetTouchable()); OnShowWhenLocked(IsShowWhenLocked()); } WSError SceneSession::RaiseAppMainWindowToTop() { auto task = [weakThis = wptr(this)]() { auto session = weakThis.promote(); if (!session) { WLOGFE("session is null"); return WSError::WS_ERROR_DESTROYED_OBJECT; } session->NotifyRequestFocusStatusNotifyManager(true, true); session->NotifyClick(); return WSError::WS_OK; }; PostTask(task, "RaiseAppMainWindowToTop"); return WSError::WS_OK; } WSError SceneSession::OnNeedAvoid(bool status) { auto task = [weakThis = wptr(this), status]() { auto session = weakThis.promote(); if (!session) { WLOGFE("session is null"); return WSError::WS_ERROR_DESTROYED_OBJECT; } WLOGFI("[WMSImms]SceneSession OnNeedAvoid status:%{public}d", static_cast(status)); if (session->sessionChangeCallback_ && session->sessionChangeCallback_->OnNeedAvoid_) { session->sessionChangeCallback_->OnNeedAvoid_(status); } return WSError::WS_OK; }; PostTask(task, "OnNeedAvoid"); return WSError::WS_OK; } WSError SceneSession::OnShowWhenLocked(bool showWhenLocked) { WLOGFD("SceneSession ShowWhenLocked status:%{public}d", static_cast(showWhenLocked)); if (sessionChangeCallback_ != nullptr && sessionChangeCallback_->OnShowWhenLocked_) { sessionChangeCallback_->OnShowWhenLocked_(showWhenLocked); } return WSError::WS_OK; } bool SceneSession::IsShowWhenLocked() const { return GetSessionProperty()->GetWindowFlags() & static_cast(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED); } void SceneSession::CalculateAvoidAreaRect(WSRect& rect, WSRect& avoidRect, AvoidArea& avoidArea) const { if (SessionHelper::IsEmptyRect(rect) || SessionHelper::IsEmptyRect(avoidRect)) { return; } Rect avoidAreaRect = SessionHelper::TransferToRect( SessionHelper::GetOverlap(rect, avoidRect, rect.posX_, rect.posY_)); if (WindowHelper::IsEmptyRect(avoidAreaRect)) { return; } uint32_t avoidAreaCenterX = static_cast(avoidAreaRect.posX_) + (avoidAreaRect.width_ >> 1); uint32_t avoidAreaCenterY = static_cast(avoidAreaRect.posY_) + (avoidAreaRect.height_ >> 1); float res1 = float(avoidAreaCenterY) - float(rect.height_) / float(rect.width_) * float(avoidAreaCenterX); float res2 = float(avoidAreaCenterY) + float(rect.height_) / float(rect.width_) * float(avoidAreaCenterX) - float(rect.height_); if (res1 < 0) { if (res2 < 0) { avoidArea.topRect_ = avoidAreaRect; } else { avoidArea.rightRect_ = avoidAreaRect; } } else { if (res2 < 0) { avoidArea.leftRect_ = avoidAreaRect; } else { avoidArea.bottomRect_ = avoidAreaRect; } } } void SceneSession::GetSystemAvoidArea(WSRect& rect, AvoidArea& avoidArea) { if (GetSessionProperty()->GetWindowFlags() & static_cast(WindowFlag::WINDOW_FLAG_NEED_AVOID)) { return; } if ((Session::GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING || Session::GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_PRIMARY || Session::GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) && WindowHelper::IsMainWindow(Session::GetWindowType()) && (system::GetParameter("const.product.devicetype", "unknown") == "phone" || system::GetParameter("const.product.devicetype", "unknown") == "tablet")) { float miniScale = 0.316f; // Pressed mini floating Scale with 0.001 precision if (Session::GetFloatingScale() <= miniScale) { return; } float vpr = 3.5f; // 3.5f: default pixel ratio auto display = DisplayManager::GetInstance().GetDefaultDisplay(); if (display) { vpr = display->GetVirtualPixelRatio(); } int32_t floatingBarHeight = 32; // 32: floating windowBar Height avoidArea.topRect_.height_ = vpr * floatingBarHeight; avoidArea.topRect_.width_ = display->GetWidth(); return; } std::vector> statusBarVector = specificCallback_->onGetSceneSessionVectorByType_(WindowType::WINDOW_TYPE_STATUS_BAR); for (auto& statusBar : statusBarVector) { if (!(statusBar->isVisible_)) { continue; } WSRect statusBarRect = statusBar->GetSessionRect(); CalculateAvoidAreaRect(rect, statusBarRect, avoidArea); } return; } void SceneSession::GetKeyboardAvoidArea(WSRect& rect, AvoidArea& avoidArea) { if (((Session::GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING && WindowHelper::IsMainWindow(Session::GetWindowType())) || (WindowHelper::IsSubWindow(Session::GetWindowType()) && GetParentSession() != nullptr && GetParentSession()->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING)) && (system::GetParameter("const.product.devicetype", "unknown") == "phone" || system::GetParameter("const.product.devicetype", "unknown") == "tablet")) { return; } std::vector> inputMethodVector = specificCallback_->onGetSceneSessionVectorByType_(WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT); for (auto& inputMethod : inputMethodVector) { if (inputMethod->GetSessionState() != SessionState::STATE_FOREGROUND && inputMethod->GetSessionState() != SessionState::STATE_ACTIVE) { continue; } SessionGravity gravity; uint32_t percent = 0; inputMethod->GetSessionProperty()->GetSessionGravity(gravity, percent); if (gravity == SessionGravity::SESSION_GRAVITY_FLOAT) { continue; } WSRect inputMethodRect = inputMethod->GetSessionRect(); CalculateAvoidAreaRect(rect, inputMethodRect, avoidArea); } return; } void SceneSession::GetCutoutAvoidArea(WSRect& rect, AvoidArea& avoidArea) { auto display = DisplayManager::GetInstance().GetDisplayById(GetSessionProperty()->GetDisplayId()); if (display == nullptr) { WLOGFE("Failed to get display manager"); return; } sptr cutoutInfo = display->GetCutoutInfo(); if (cutoutInfo == nullptr) { WLOGFI("GetCutoutAvoidArea There is no CutoutInfo"); return; } std::vector cutoutAreas = cutoutInfo->GetBoundingRects(); if (cutoutAreas.empty()) { WLOGFI("GetCutoutAvoidArea There is no cutoutAreas"); return; } for (auto& cutoutArea : cutoutAreas) { WSRect cutoutAreaRect = { cutoutArea.posX_, cutoutArea.posY_, cutoutArea.width_, cutoutArea.height_ }; CalculateAvoidAreaRect(rect, cutoutAreaRect, avoidArea); } return; } void SceneSession::GetAINavigationBarArea(WSRect rect, AvoidArea& avoidArea) { if (Session::GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING || Session::GetWindowMode() == WindowMode::WINDOW_MODE_PIP) { return; } WSRect barArea = specificCallback_->onGetAINavigationBarArea_(); CalculateAvoidAreaRect(rect, barArea, avoidArea); } AvoidArea SceneSession::GetAvoidAreaByType(AvoidAreaType type) { auto task = [weakThis = wptr(this), type]() -> AvoidArea { auto session = weakThis.promote(); if (!session) { WLOGFE("session is null"); return {}; } AvoidArea avoidArea; WSRect rect = session->GetSessionRect(); WLOGFD("[WMSImms]GetAvoidAreaByType avoidAreaType:%{public}u", type); switch (type) { case AvoidAreaType::TYPE_SYSTEM: { session->GetSystemAvoidArea(rect, avoidArea); return avoidArea; } case AvoidAreaType::TYPE_KEYBOARD: { session->GetKeyboardAvoidArea(rect, avoidArea); return avoidArea; } case AvoidAreaType::TYPE_CUTOUT: { session->GetCutoutAvoidArea(rect, avoidArea); return avoidArea; } case AvoidAreaType::TYPE_NAVIGATION_INDICATOR: { session->GetAINavigationBarArea(rect, avoidArea); return avoidArea; } default: { WLOGFI("[WMSImms]cannot find avoidAreaType: %{public}u", type); return avoidArea; } } }; return PostSyncTask(task, "GetAvoidAreaByType"); } WSError SceneSession::UpdateAvoidArea(const sptr& avoidArea, AvoidAreaType type) { if (!sessionStage_) { return WSError::WS_ERROR_NULLPTR; } return sessionStage_->UpdateAvoidArea(avoidArea, type); } void SceneSession::HandleStyleEvent(MMI::WindowArea area) { static std::pair preWindowArea = std::make_pair(INVALID_WINDOW_ID, MMI::WindowArea::EXIT); if (preWindowArea.first == Session::GetWindowId() && preWindowArea.second == area) { return; } if (area != MMI::WindowArea::EXIT) { if (Session::SetPointerStyle(area) != WSError::WS_OK) { WLOGFE("Failed to set the cursor style, WSError:%{public}d", Session::SetPointerStyle(area)); } } preWindowArea = { Session::GetWindowId(), area }; } WSError SceneSession::HandleEnterWinwdowArea(int32_t displayX, int32_t displayY) { if (displayX < 0 || displayY < 0) { WLOGE("Illegal parameter, displayX:%{public}d, displayY:%{public}d", displayX, displayY); return WSError::WS_ERROR_INVALID_PARAM; } auto windowType = Session::GetWindowType(); auto iter = Session::windowAreas_.cend(); if (!Session::IsSystemSession() && Session::GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING && (windowType == WindowType::WINDOW_TYPE_APP_MAIN_WINDOW || WindowHelper::IsSubWindow(windowType))) { iter = Session::windowAreas_.cbegin(); for (;iter != Session::windowAreas_.cend(); ++iter) { WSRectF rect = iter->second; if (rect.IsInRegion(displayX, displayY)) { break; } } } MMI::WindowArea area = MMI::WindowArea::EXIT; if (iter == Session::windowAreas_.cend()) { bool isInRegion = false; WSRect rect = Session::winRect_; if (Session::GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING && (windowType == WindowType::WINDOW_TYPE_APP_MAIN_WINDOW || WindowHelper::IsSubWindow(windowType))) { WSRectF rectF = Session::UpdateHotRect(rect); isInRegion = rectF.IsInRegion(displayX, displayY); } else { isInRegion = rect.IsInRegion(displayX, displayY); } if (!isInRegion) { WLOGFE("The wrong event(%{public}d, %{public}d) could not be matched to the region:" \ "[%{public}d, %{public}d, %{public}d, %{public}d]", displayX, displayY, rect.posX_, rect.posY_, rect.width_, rect.height_); return WSError::WS_ERROR_INVALID_TYPE; } area = MMI::WindowArea::FOCUS_ON_INNER; } else { area = iter->first; } HandleStyleEvent(area); return WSError::WS_OK; } WSError SceneSession::HandlePointerStyle(const std::shared_ptr& pointerEvent) { if (pointerEvent == nullptr) { WLOGFE("pointerEvent is nullptr"); return WSError::WS_ERROR_NULLPTR; } if (pointerEvent->GetSourceType() != MMI::PointerEvent::SOURCE_TYPE_MOUSE) { return WSError::WS_DO_NOTHING; } if (!(pointerEvent->GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_MOVE && pointerEvent->GetButtonId() == MMI::PointerEvent::BUTTON_NONE)) { return WSError::WS_DO_NOTHING; } MMI::PointerEvent::PointerItem pointerItem; if (!pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), pointerItem)) { WLOGFE("Get pointeritem failed"); pointerEvent->MarkProcessed(); return WSError::WS_ERROR_INVALID_PARAM; } int32_t mousePointX = pointerItem.GetDisplayX(); int32_t mousePointY = pointerItem.GetDisplayY(); auto displayInfo = DisplayManager::GetInstance().GetDisplayById(pointerEvent->GetTargetDisplayId()); if (displayInfo != nullptr) { float vpr = displayInfo->GetVirtualPixelRatio(); if (vpr <= 0) { vpr = 1.5f; } Session::SetVpr(vpr); } return HandleEnterWinwdowArea(mousePointX, mousePointY); } WSError SceneSession::ProcessPointDownSession(int32_t posX, int32_t posY) { const auto& id = GetPersistentId(); WLOGFI("id: %{public}d, type: %{public}d, pos: [%{public}d, %{public}d]", id, GetWindowType(), posX, posY); // notify touch outside if (specificCallback_ != nullptr && specificCallback_->onSessionTouchOutside_) { specificCallback_->onSessionTouchOutside_(id); } // notify outside down event if (specificCallback_ != nullptr && specificCallback_->onOutsideDownEvent_) { specificCallback_->onOutsideDownEvent_(posX, posY); } return WSError::WS_OK; } WSError SceneSession::SendPointEventForMoveDrag(const std::shared_ptr& pointerEvent) { NotifyOutsideDownEvent(pointerEvent); TransferPointerEvent(pointerEvent, false); return WSError::WS_OK; } void SceneSession::NotifyOutsideDownEvent(const std::shared_ptr& pointerEvent) { // notify touchOutside and touchDown event int32_t action = pointerEvent->GetPointerAction(); if (action != MMI::PointerEvent::POINTER_ACTION_DOWN && action != MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN) { return; } MMI::PointerEvent::PointerItem pointerItem; if (!pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), pointerItem)) { return; } // notify outside down event if (specificCallback_ != nullptr && specificCallback_->onOutsideDownEvent_) { specificCallback_->onOutsideDownEvent_(pointerItem.GetDisplayX(), pointerItem.GetDisplayY()); } } WSError SceneSession::TransferPointerEvent(const std::shared_ptr& pointerEvent, bool needNotifyClient) { WLOGFD("[WMSCom] TransferPointEvent, id: %{public}d, type: %{public}d, needNotifyClient: %{public}d", GetPersistentId(), GetWindowType(), needNotifyClient); if (pointerEvent == nullptr) { WLOGFE("pointerEvent is null"); return WSError::WS_ERROR_NULLPTR; } int32_t action = pointerEvent->GetPointerAction(); { bool isSystemWindow = GetSessionInfo().isSystem_; if (action == MMI::PointerEvent::POINTER_ACTION_ENTER_WINDOW) { std::lock_guard guard(enterSessionMutex_); WLOGFD("Set enter session, persistentId:%{public}d", GetPersistentId()); enterSession_ = wptr(this); } if ((enterSession_ != nullptr) && (isSystemWindow && (action != MMI::PointerEvent::POINTER_ACTION_ENTER_WINDOW))) { std::lock_guard guard(enterSessionMutex_); WLOGFD("Remove enter session, persistentId:%{public}d", GetPersistentId()); enterSession_ = nullptr; } } if (!CheckPointerEventDispatch(pointerEvent)) { WLOGFI("Do not dispatch this pointer event"); return WSError::WS_DO_NOTHING; } bool isPointDown = (action == MMI::PointerEvent::POINTER_ACTION_DOWN || action == MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN); if (specificCallback_ != nullptr && specificCallback_->onSessionTouchOutside_ != nullptr && isPointDown) { specificCallback_->onSessionTouchOutside_(GetPersistentId()); } auto property = GetSessionProperty(); if (property == nullptr) { return Session::TransferPointerEvent(pointerEvent, needNotifyClient); } auto windowType = property->GetWindowType(); if (property->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING && (WindowHelper::IsMainWindow(windowType) || WindowHelper::IsSubWindow(windowType)) && property->GetMaximizeMode() != MaximizeMode::MODE_AVOID_SYSTEM_BAR) { if (CheckDialogOnForeground() && isPointDown) { HandlePointDownDialog(); pointerEvent->MarkProcessed(); WLOGFI("[WMSDialog] There is dialog window foreground"); return WSError::WS_OK; } if (!moveDragController_) { WLOGE("moveDragController_ is null"); return Session::TransferPointerEvent(pointerEvent, needNotifyClient); } if (property->GetDragEnabled()) { auto is2in1 = system::GetParameter("const.product.devicetype", "unknown") == "2in1"; if (is2in1 && moveDragController_->ConsumeDragEvent(pointerEvent, winRect_, property, systemConfig_)) { moveDragController_->UpdateGravityWhenDrag(pointerEvent, surfaceNode_); PresentFoucusIfNeed(pointerEvent->GetPointerAction()); pointerEvent->MarkProcessed(); return WSError::WS_OK; } } if (IsDecorEnable() && moveDragController_->ConsumeMoveEvent(pointerEvent, winRect_)) { PresentFoucusIfNeed(pointerEvent->GetPointerAction()); pointerEvent->MarkProcessed(); return WSError::WS_OK; } } if (property->GetWindowMode() == WindowMode::WINDOW_MODE_PIP && WindowHelper::IsPipWindow(property->GetWindowType())) { if (!moveDragController_) { WLOGFE("moveDragController is null"); return Session::TransferPointerEvent(pointerEvent, needNotifyClient); } if (moveDragController_->ConsumeMoveEvent(pointerEvent, winRect_)) { pointerEvent->MarkProcessed(); return WSError::WS_OK; } } bool raiseEnabled = property->GetWindowType() == WindowType::WINDOW_TYPE_DIALOG && property->GetRaiseEnabled() && (action == MMI::PointerEvent::POINTER_ACTION_DOWN || action == MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN); if (raiseEnabled) { RaiseToAppTopForPointDown(); } return Session::TransferPointerEvent(pointerEvent, needNotifyClient); } WSError SceneSession::RequestSessionBack(bool needMoveToBackground) { auto task = [weakThis = wptr(this), needMoveToBackground]() { auto session = weakThis.promote(); if (!session) { WLOGFE("session is null"); return WSError::WS_ERROR_DESTROYED_OBJECT; } if (!session->backPressedFunc_) { WLOGFW("Session didn't register back event consumer!"); return WSError::WS_DO_NOTHING; } if (g_enableForceUIFirst) { auto rsTransaction = RSTransactionProxy::GetInstance(); if (rsTransaction) { rsTransaction->Begin(); } if (session->leashWinSurfaceNode_) { session->leashWinSurfaceNode_->SetForceUIFirst(true); WLOGFI("leashWinSurfaceNode_ SetForceUIFirst id:%{public}u!", session->GetPersistentId()); } else { WLOGFI("failed, leashWinSurfaceNode_ null id:%{public}u", session->GetPersistentId()); } if (rsTransaction) { rsTransaction->Commit(); } } session->backPressedFunc_(needMoveToBackground); return WSError::WS_OK; }; PostTask(task, "RequestSessionBack:" + std::to_string(needMoveToBackground)); return WSError::WS_OK; } const wptr SceneSession::GetEnterWindow() { std::lock_guard guard(enterSessionMutex_); return enterSession_; } void SceneSession::ClearEnterWindow() { std::lock_guard guard(enterSessionMutex_); enterSession_ = nullptr; } void SceneSession::NotifySessionRectChange(const WSRect& rect, const SizeChangeReason& reason) { auto task = [weakThis = wptr(this), rect, reason]() { auto session = weakThis.promote(); if (!session) { WLOGFE("session is null"); return; } if (session->sessionRectChangeFunc_) { HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "SceneSession::NotifySessionRectChange"); session->sessionRectChangeFunc_(rect, reason); } }; PostTask(task, "NotifySessionRectChange" + GetRectInfo(rect)); } bool SceneSession::IsDecorEnable() const { auto property = GetSessionProperty(); if (property == nullptr) { WLOGE("property is nullptr"); return false; } if (property->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING && system::GetParameter("const.product.devicetype", "unknown") == "phone") { /* FloatingWindow skip for Phone */ return false; } auto windowType = property->GetWindowType(); return (WindowHelper::IsMainWindow(windowType) || (WindowHelper::IsSubWindow(windowType) && property->IsDecorEnable())) && systemConfig_.isSystemDecorEnable_ && WindowHelper::IsWindowModeSupported(systemConfig_.decorModeSupportInfo_, property->GetWindowMode()); } std::string SceneSession::GetRatioPreferenceKey() { std::string key = sessionInfo_.bundleName_ + sessionInfo_.moduleName_ + sessionInfo_.abilityName_; if (key.length() > ScenePersistentStorage::MAX_KEY_LEN) { return key.substr(key.length() - ScenePersistentStorage::MAX_KEY_LEN); } return key; } bool SceneSession::SaveAspectRatio(float ratio) { std::string key = GetRatioPreferenceKey(); if (!key.empty()) { ScenePersistentStorage::Insert(key, ratio, ScenePersistentStorageType::ASPECT_RATIO); WLOGD("SceneSession save aspectRatio , key %{public}s, value: %{public}f", key.c_str(), aspectRatio_); return true; } return false; } void SceneSession::FixRectByLimits(WindowLimits limits, WSRect& rect, float ratio, bool isDecor, float vpr) { if (isDecor) { rect.width_ = SessionUtils::ToLayoutWidth(rect.width_, vpr); rect.height_ = SessionUtils::ToLayoutHeight(rect.height_, vpr); limits.minWidth_ = SessionUtils::ToLayoutWidth(limits.minWidth_, vpr); limits.maxWidth_ = SessionUtils::ToLayoutWidth(limits.maxWidth_, vpr); limits.minHeight_ = SessionUtils::ToLayoutHeight(limits.minHeight_, vpr); limits.maxHeight_ = SessionUtils::ToLayoutHeight(limits.maxHeight_, vpr); } if (static_cast(rect.height_) > limits.maxHeight_) { rect.height_ = static_cast(limits.maxHeight_); rect.width_ = floor(rect.height_ * ratio); } else if (static_cast(rect.width_) > limits.maxWidth_) { rect.width_ = static_cast(limits.maxWidth_); rect.height_ = floor(rect.width_ / ratio); } else if (static_cast(rect.width_) < limits.minWidth_) { rect.width_ = static_cast(limits.minWidth_); rect.height_ = ceil(rect.width_ / ratio); } else if (static_cast(rect.height_) < limits.minHeight_) { rect.height_ = static_cast(limits.minHeight_); rect.width_ = ceil(rect.height_ * ratio); } if (isDecor) { rect.height_ = SessionUtils::ToWinHeight(rect.height_, vpr) ; rect.width_ = SessionUtils::ToWinWidth(rect.width_, vpr); } } bool SceneSession::FixRectByAspectRatio(WSRect& rect) { const int tolerancePx = 2; // 2: tolerance delta pixel value, unit: px WSRect originalRect = rect; auto property = GetSessionProperty(); if (!property || property->GetWindowMode() != WindowMode::WINDOW_MODE_FLOATING || !WindowHelper::IsMainWindow(GetWindowType())) { return false; } if (MathHelper::NearZero(aspectRatio_)) { return false; } float vpr = 1.5f; // 1.5f: default virtual pixel ratio auto display = DisplayManager::GetInstance().GetDefaultDisplay(); if (display) { vpr = display->GetVirtualPixelRatio(); } int32_t minW; int32_t maxW; int32_t minH; int32_t maxH; SessionUtils::CalcFloatWindowRectLimits(property->GetWindowLimits(), systemConfig_.maxFloatingWindowSize_, vpr, minW, maxW, minH, maxH); rect.width_ = std::max(minW, static_cast(rect.width_)); rect.width_ = std::min(maxW, static_cast(rect.width_)); rect.height_ = std::max(minH, static_cast(rect.height_)); rect.height_ = std::min(maxH, static_cast(rect.height_)); if (IsDecorEnable()) { if (SessionUtils::ToLayoutWidth(rect.width_, vpr) > SessionUtils::ToLayoutHeight(rect.height_, vpr) * aspectRatio_) { rect.width_ = SessionUtils::ToWinWidth(SessionUtils::ToLayoutHeight(rect.height_, vpr)* aspectRatio_, vpr); } else { rect.height_ = SessionUtils::ToWinHeight(SessionUtils::ToLayoutWidth(rect.width_, vpr) / aspectRatio_, vpr); } } else { if (rect.width_ > rect.height_ * aspectRatio_) { rect.width_ = rect.height_ * aspectRatio_; } else { rect.height_ = rect.width_ / aspectRatio_; } } FixRectByLimits(property->GetWindowLimits(), rect, aspectRatio_, IsDecorEnable(), vpr); if (std::abs(static_cast(originalRect.width_) - static_cast(rect.width_)) <= tolerancePx && std::abs(static_cast(originalRect.height_) - static_cast(rect.height_)) <= tolerancePx) { rect = originalRect; return false; } return true; } void SceneSession::SetMoveDragCallback() { if (moveDragController_) { MoveDragCallback callBack = [this](const SizeChangeReason& reason) { this->OnMoveDragCallback(reason); }; moveDragController_->RegisterMoveDragCallback(callBack); } } void SceneSession::OnMoveDragCallback(const SizeChangeReason& reason) { WSRect rect = moveDragController_->GetTargetRect(); WLOGFD("OnMoveDragCallback rect: [%{public}d, %{public}d, %{public}u, %{public}u], reason : %{public}d", rect.posX_, rect.posY_, rect.width_, rect.height_, reason); if (reason == SizeChangeReason::DRAG || reason == SizeChangeReason::DRAG_END) { UpdateWinRectForSystemBar(rect); } HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "SceneSession::OnMoveDragCallback [%d, %d, %u, %u]", rect.posX_, rect.posY_, rect.width_, rect.height_); SetSurfaceBounds(rect); OnPiPMoveCallback(rect, reason); if (reason != SizeChangeReason::MOVE) { UpdateSizeChangeReason(reason); UpdateRect(rect, reason); } if (reason == SizeChangeReason::DRAG_END) { NotifySessionRectChange(rect, reason); OnSessionEvent(SessionEvent::EVENT_END_MOVE); } if (reason == SizeChangeReason::DRAG_START) { OnSessionEvent(SessionEvent::EVENT_DRAG_START); } } void SceneSession::UpdateWinRectForSystemBar(WSRect& rect) { if (!specificCallback_) { WLOGFE("specificCallback_ is null!"); return; } float tmpPosY = 0.0; std::vector> statusBarVector = specificCallback_->onGetSceneSessionVectorByType_(WindowType::WINDOW_TYPE_STATUS_BAR); for (auto& statusBar : statusBarVector) { if (!(statusBar->isVisible_)) { continue; } WSRect statusBarRect = statusBar->GetSessionRect(); if ((rect.posY_ < statusBarRect.posY_ + static_cast(statusBarRect.height_)) && (rect.height_ != winRect_.height_ || rect.width_ != winRect_.width_)) { tmpPosY = rect.posY_ + rect.height_; rect.posY_ = statusBarRect.posY_ + statusBarRect.height_; rect.height_ = tmpPosY - rect.posY_; } } WLOGFD("after UpdateWinRectForSystemBar rect: [%{public}d, %{public}d, %{public}u, %{public}u]", rect.posX_, rect.posY_, rect.width_, rect.height_); } void SceneSession::SetSurfaceBounds(const WSRect& rect) { auto rsTransaction = RSTransactionProxy::GetInstance(); if (rsTransaction) { rsTransaction->Begin(); } if (surfaceNode_ && leashWinSurfaceNode_) { leashWinSurfaceNode_->SetBounds(rect.posX_, rect.posY_, rect.width_, rect.height_); leashWinSurfaceNode_->SetFrame(rect.posX_, rect.posY_, rect.width_, rect.height_); surfaceNode_->SetBounds(0, 0, rect.width_, rect.height_); surfaceNode_->SetFrame(0, 0, rect.width_, rect.height_); } else if (WindowHelper::IsPipWindow(GetWindowType()) && surfaceNode_) { WLOGFD("PipWindow setSurfaceBounds"); surfaceNode_->SetBounds(rect.posX_, rect.posY_, rect.width_, rect.height_); surfaceNode_->SetFrame(rect.posX_, rect.posY_, rect.width_, rect.height_); } else if (WindowHelper::IsSubWindow(GetWindowType()) && surfaceNode_) { WLOGFD("subwindow setSurfaceBounds"); surfaceNode_->SetBounds(rect.posX_, rect.posY_, rect.width_, rect.height_); surfaceNode_->SetFrame(rect.posX_, rect.posY_, rect.width_, rect.height_); } else { WLOGE("SetSurfaceBounds surfaceNode is null!"); } if (rsTransaction) { rsTransaction->Commit(); } } void SceneSession::SetZOrder(uint32_t zOrder) { auto task = [weakThis = wptr(this), zOrder]() { auto session = weakThis.promote(); if (session == nullptr) { WLOGFE("session is null"); return; } if (session->zOrder_ != zOrder) { session->Session::SetZOrder(zOrder); if (session->specificCallback_ != nullptr) { session->specificCallback_->onWindowInfoUpdate_(session->GetPersistentId(), WindowUpdateType::WINDOW_UPDATE_PROPERTY); } } }; PostTask(task, "SetZOrder"); } void SceneSession::SetFloatingScale(float floatingScale) { if (floatingScale_ != floatingScale) { Session::SetFloatingScale(floatingScale); if (specificCallback_ != nullptr) { specificCallback_->onWindowInfoUpdate_(GetPersistentId(), WindowUpdateType::WINDOW_UPDATE_PROPERTY); specificCallback_->onUpdateAvoidArea_(GetPersistentId()); } } } void SceneSession::SetParentPersistentId(int32_t parentId) { auto property = GetSessionProperty(); if (property) { property->SetParentPersistentId(parentId); } } int32_t SceneSession::GetParentPersistentId() const { auto property = GetSessionProperty(); if (property) { return property->GetParentPersistentId(); } return INVALID_SESSION_ID; } const std::string& SceneSession::GetWindowName() const { return GetSessionProperty()->GetWindowName(); } const std::string& SceneSession::GetWindowNameAllType() const { if (GetSessionInfo().isSystem_) { return GetSessionInfo().abilityName_; } else { return GetWindowName(); } } WSError SceneSession::SetTurnScreenOn(bool turnScreenOn) { GetSessionProperty()->SetTurnScreenOn(turnScreenOn); return WSError::WS_OK; } bool SceneSession::IsTurnScreenOn() const { return GetSessionProperty()->IsTurnScreenOn(); } WSError SceneSession::SetKeepScreenOn(bool keepScreenOn) { GetSessionProperty()->SetKeepScreenOn(keepScreenOn); return WSError::WS_OK; } bool SceneSession::IsKeepScreenOn() const { return GetSessionProperty()->IsKeepScreenOn(); } std::string SceneSession::GetSessionSnapshotFilePath() const { WLOGFI("GetSessionSnapshotFilePath id %{public}d", GetPersistentId()); if (Session::GetSessionState() < SessionState::STATE_BACKGROUND) { WLOGFI("GetSessionSnapshotFilePath UpdateSnapshot"); auto snapshot = Snapshot(); if (scenePersistence_ != nullptr) { scenePersistence_->SaveSnapshot(snapshot); } } if (scenePersistence_ != nullptr) { return scenePersistence_->GetSnapshotFilePath(); } return ""; } void SceneSession::SaveUpdatedIcon(const std::shared_ptr &icon) { WLOGFI("run SaveUpdatedIcon"); if (scenePersistence_ != nullptr) { scenePersistence_->SaveUpdatedIcon(icon); } } std::string SceneSession::GetUpdatedIconPath() const { WLOGFI("run GetUpdatedIconPath"); if (scenePersistence_ != nullptr) { return scenePersistence_->GetUpdatedIconPath(); } return ""; } void SceneSession::UpdateNativeVisibility(bool visible) { WLOGFI("[WMSSCB] name: %{public}s, id: %{public}u, visible: %{public}u", sessionInfo_.bundleName_.c_str(), GetPersistentId(), visible); isVisible_ = visible; if (specificCallback_ == nullptr) { WLOGFW("specific callback is null."); return; } if (visible) { specificCallback_->onWindowInfoUpdate_(GetPersistentId(), WindowUpdateType::WINDOW_UPDATE_ADDED); } else { specificCallback_->onWindowInfoUpdate_(GetPersistentId(), WindowUpdateType::WINDOW_UPDATE_REMOVED); } NotifyAccessibilityVisibilityChange(); specificCallback_->onUpdateAvoidArea_(GetPersistentId()); // update private state if (!GetSessionProperty()) { WLOGFE("UpdateNativeVisibility property is null"); return; } } bool SceneSession::IsVisible() const { return isVisible_; } void SceneSession::UpdateRotationAvoidArea() { if (specificCallback_) { specificCallback_->onUpdateAvoidArea_(GetPersistentId()); } } void SceneSession::SetPrivacyMode(bool isPrivacy) { auto property = GetSessionProperty(); if (!property) { WLOGFE("SetPrivacyMode property is null"); return; } if (!surfaceNode_) { WLOGFE("surfaceNode_ is null"); return; } bool lastPrivacyMode = property->GetPrivacyMode() || property->GetSystemPrivacyMode(); if (lastPrivacyMode == isPrivacy) { WLOGFW("privacy mode is not change, do nothing, isPrivacy:%{public}d", isPrivacy); return; } property->SetPrivacyMode(isPrivacy); property->SetSystemPrivacyMode(isPrivacy); surfaceNode_->SetSecurityLayer(isPrivacy); if (leashWinSurfaceNode_ != nullptr) { leashWinSurfaceNode_->SetSecurityLayer(isPrivacy); } RSTransaction::FlushImplicitTransaction(); } void SceneSession::SetSystemSceneOcclusionAlpha(double alpha) { if (alpha < 0 || alpha > 1.0) { WLOGFE("OnSetSystemSceneOcclusionAlpha property is null"); return; } if (!surfaceNode_) { WLOGFE("surfaceNode_ is null"); return; } uint8_t alpha8bit = static_cast(alpha * 255); WLOGFI("surfaceNode SetAbilityBGAlpha=%{public}u.", alpha8bit); surfaceNode_->SetAbilityBGAlpha(alpha8bit); if (leashWinSurfaceNode_ != nullptr) { leashWinSurfaceNode_->SetAbilityBGAlpha(alpha8bit); } RSTransaction::FlushImplicitTransaction(); } WSError SceneSession::UpdateWindowAnimationFlag(bool needDefaultAnimationFlag) { auto task = [weakThis = wptr(this), needDefaultAnimationFlag]() { auto session = weakThis.promote(); if (!session) { WLOGFE("session is null"); return WSError::WS_ERROR_DESTROYED_OBJECT; } session->needDefaultAnimationFlag_ = needDefaultAnimationFlag; if (session->sessionChangeCallback_ && session->sessionChangeCallback_->onWindowAnimationFlagChange_) { session->sessionChangeCallback_->onWindowAnimationFlagChange_(needDefaultAnimationFlag); } return WSError::WS_OK; }; return PostSyncTask(task, "UpdateWindowAnimationFlag"); } void SceneSession::SetWindowAnimationFlag(bool needDefaultAnimationFlag) { needDefaultAnimationFlag_ = needDefaultAnimationFlag; if (sessionChangeCallback_ && sessionChangeCallback_->onWindowAnimationFlagChange_) { sessionChangeCallback_->onWindowAnimationFlagChange_(needDefaultAnimationFlag); } return; } bool SceneSession::IsNeedDefaultAnimation() const { return needDefaultAnimationFlag_; } bool SceneSession::IsAppSession() const { if (GetWindowType() == WindowType::WINDOW_TYPE_APP_MAIN_WINDOW) { return true; } if (GetParentSession() && GetParentSession()->GetWindowType() == WindowType::WINDOW_TYPE_APP_MAIN_WINDOW) { return true; } return false; } void SceneSession::NotifyIsCustomAnimationPlaying(bool isPlaying) { WLOGFI("id %{public}d %{public}u", GetPersistentId(), isPlaying); if (sessionChangeCallback_ != nullptr && sessionChangeCallback_->onIsCustomAnimationPlaying_) { sessionChangeCallback_->onIsCustomAnimationPlaying_(isPlaying); } } WSError SceneSession::UpdateWindowSceneAfterCustomAnimation(bool isAdd) { if (!SessionPermission::IsSystemCalling()) { WLOGFE("[WMSSystem]failed to update with id:%{public}u!", GetPersistentId()); return WSError::WS_ERROR_NOT_SYSTEM_APP; } auto task = [weakThis = wptr(this), isAdd]() { auto session = weakThis.promote(); if (!session) { WLOGFE("session is null"); return WSError::WS_ERROR_DESTROYED_OBJECT; } WLOGFI("UpdateWindowSceneAfterCustomAnimation, id %{public}d, isAdd: %{public}d", session->GetPersistentId(), isAdd); if (isAdd) { WLOGFE("SetOpacityFunc not register %{public}d", session->GetPersistentId()); return WSError::WS_ERROR_INVALID_OPERATION; } else { WLOGFI("background after custom animation id %{public}d", session->GetPersistentId()); // since background will remove surfaceNode session->Background(); session->NotifyIsCustomAnimationPlaying(false); } return WSError::WS_OK; }; PostTask(task, "UpdateWindowSceneAfterCustomAnimation:" + std::to_string(isAdd)); return WSError::WS_OK; } bool SceneSession::IsFloatingWindowAppType() const { auto property = GetSessionProperty(); if (property == nullptr) { return false; } return property->IsFloatingWindowAppType(); } std::vector SceneSession::GetTouchHotAreas() const { std::vector touchHotAreas; auto property = GetSessionProperty(); if (property) { property->GetTouchHotAreas(touchHotAreas); } return touchHotAreas; } void SceneSession::DumpSessionElementInfo(const std::vector& params) { if (!sessionStage_) { return; } return sessionStage_->DumpSessionElementInfo(params); } void SceneSession::NotifyTouchOutside() { WLOGFI("id: %{public}d, type: %{public}d", GetPersistentId(), GetWindowType()); if (sessionStage_) { WLOGFD("Notify sessionStage TouchOutside"); sessionStage_->NotifyTouchOutside(); } if (sessionChangeCallback_ && sessionChangeCallback_->OnTouchOutside_) { WLOGFD("Notify sessionChangeCallback TouchOutside"); sessionChangeCallback_->OnTouchOutside_(); } } void SceneSession::NotifyWindowVisibility() { if (sessionStage_) { sessionStage_->NotifyWindowVisibility(GetVisible()); } else { WLOGFE("Notify window(id:%{public}d) visibility failed, for this session stage is nullptr", GetPersistentId()); } } bool SceneSession::CheckOutTouchOutsideRegister() { if (sessionChangeCallback_ && sessionChangeCallback_->OnTouchOutside_) { return true; } return false; } void SceneSession::SetRequestedOrientation(Orientation orientation) { WLOGFI("id: %{public}d orientation: %{public}u", GetPersistentId(), static_cast(orientation)); GetSessionProperty()->SetRequestedOrientation(orientation); if (sessionChangeCallback_ && sessionChangeCallback_->OnRequestedOrientationChange_) { sessionChangeCallback_->OnRequestedOrientationChange_(static_cast(orientation)); } } void SceneSession::NotifyForceHideChange(bool hide) { WLOGFI("id: %{public}d forceHide: %{public}u", persistentId_, hide); auto property = GetSessionProperty(); if (property == nullptr) { WLOGFD("id: %{public}d property is nullptr", persistentId_); return; } property->SetForceHide(hide); if (sessionChangeCallback_ && sessionChangeCallback_->OnForceHideChange_) { sessionChangeCallback_->OnForceHideChange_(hide); } } Orientation SceneSession::GetRequestedOrientation() const { return GetSessionProperty()->GetRequestedOrientation(); } int32_t SceneSession::GetCollaboratorType() const { return collaboratorType_; } void SceneSession::SetCollaboratorType(int32_t collaboratorType) { collaboratorType_ = collaboratorType; sessionInfo_.collaboratorType_ = collaboratorType; } void SceneSession::DumpSessionInfo(std::vector &info) const { std::string dumpInfo = " Session ID #" + std::to_string(persistentId_); info.push_back(dumpInfo); dumpInfo = " session name [" + SessionUtils::ConvertSessionName(sessionInfo_.bundleName_, sessionInfo_.abilityName_, sessionInfo_.moduleName_, sessionInfo_.appIndex_) + "]"; info.push_back(dumpInfo); dumpInfo = " runningState [" + std::string(isActive_ ? "FOREGROUND" : "BACKGROUND") + "]"; info.push_back(dumpInfo); dumpInfo = " lockedState [" + std::to_string(sessionInfo_.lockedState) + "]"; info.push_back(dumpInfo); auto abilityInfo = sessionInfo_.abilityInfo; dumpInfo = " continuable [" + (abilityInfo ? std::to_string(abilityInfo->continuable) : " ") + "]"; info.push_back(dumpInfo); dumpInfo = " timeStamp [" + sessionInfo_.time + "]"; info.push_back(dumpInfo); dumpInfo = " label [" + (abilityInfo ? abilityInfo->label : " ") + "]"; info.push_back(dumpInfo); dumpInfo = " iconPath [" + (abilityInfo ? abilityInfo->iconPath : " ") + "]"; info.push_back(dumpInfo); dumpInfo = " want [" + (sessionInfo_.want ? sessionInfo_.want->ToUri() : " ") + "]"; info.push_back(dumpInfo); } std::shared_ptr SceneSession::GetAbilityInfo() const { const SessionInfo& sessionInfo = GetSessionInfo(); return sessionInfo.abilityInfo; } void SceneSession::SetAbilitySessionInfo(std::shared_ptr abilityInfo) { SetSessionInfoAbilityInfo(abilityInfo); } void SceneSession::SetSelfToken(sptr selfToken) { selfToken_ = selfToken; } sptr SceneSession::GetSelfToken() const { return selfToken_; } void SceneSession::SetSessionState(SessionState state) { Session::SetSessionState(state); NotifyAccessibilityVisibilityChange(); } void SceneSession::UpdateSessionState(SessionState state) { Session::UpdateSessionState(state); NotifyAccessibilityVisibilityChange(); } bool SceneSession::IsVisibleForAccessibility() const { return GetSystemTouchable() && GetForegroundInteractiveStatus() && (IsVisible() || state_ == SessionState::STATE_ACTIVE || state_ == SessionState::STATE_FOREGROUND); } void SceneSession::SetForegroundInteractiveStatus(bool interactive) { Session::SetForegroundInteractiveStatus(interactive); NotifyAccessibilityVisibilityChange(); } void SceneSession::NotifyAccessibilityVisibilityChange() { bool isVisibleForAccessibilityNew = IsVisibleForAccessibility(); if (isVisibleForAccessibilityNew == isVisibleForAccessibility_.load()) { return; } WLOGFD("[WMSAccess] NotifyAccessibilityVisibilityChange id: %{public}d, visible: %{public}d", GetPersistentId(), isVisibleForAccessibilityNew); isVisibleForAccessibility_.store(isVisibleForAccessibilityNew); if (specificCallback_ && specificCallback_->onWindowInfoUpdate_) { if (isVisibleForAccessibilityNew) { specificCallback_->onWindowInfoUpdate_(GetPersistentId(), WindowUpdateType::WINDOW_UPDATE_ADDED); } else { specificCallback_->onWindowInfoUpdate_(GetPersistentId(), WindowUpdateType::WINDOW_UPDATE_REMOVED); } } else { WLOGFD("specificCallback_->onWindowInfoUpdate_ not exist, persistent id: %{public}d", GetPersistentId()); } } void SceneSession::SetSystemTouchable(bool touchable) { Session::SetSystemTouchable(touchable); NotifyAccessibilityVisibilityChange(); } WSError SceneSession::PendingSessionActivation(const sptr abilitySessionInfo) { if (!SessionPermission::VerifySessionPermission()) { WLOGFE("The interface permission failed."); return WSError::WS_ERROR_INVALID_PERMISSION; } auto task = [weakThis = wptr(this), abilitySessionInfo]() { auto session = weakThis.promote(); if (!session) { WLOGFE("session is null"); return WSError::WS_ERROR_DESTROYED_OBJECT; } if (abilitySessionInfo == nullptr) { WLOGFE("abilitySessionInfo is null"); return WSError::WS_ERROR_NULLPTR; } session->sessionInfo_.startMethod = StartMethod::START_CALL; SessionInfo info; info.abilityName_ = abilitySessionInfo->want.GetElement().GetAbilityName(); info.bundleName_ = abilitySessionInfo->want.GetElement().GetBundleName(); info.moduleName_ = abilitySessionInfo->want.GetModuleName(); info.appIndex_ = abilitySessionInfo->want.GetIntParam(DLP_INDEX, 0); info.persistentId_ = abilitySessionInfo->persistentId; info.callerPersistentId_ = session->GetPersistentId(); info.callState_ = static_cast(abilitySessionInfo->state); info.uiAbilityId_ = abilitySessionInfo->uiAbilityId; info.want = std::make_shared(abilitySessionInfo->want); info.requestCode = abilitySessionInfo->requestCode; info.callerToken_ = abilitySessionInfo->callerToken; info.startSetting = abilitySessionInfo->startSetting; info.callingTokenId_ = abilitySessionInfo->callingTokenId; info.reuse = abilitySessionInfo->reuse; if (info.want != nullptr) { info.windowMode = info.want->GetIntParam(AAFwk::Want::PARAM_RESV_WINDOW_MODE, 0); info.sessionAffinity = info.want->GetStringParam(Rosen::PARAM_KEY::PARAM_MISSION_AFFINITY_KEY); info.screenId_ = info.want->GetIntParam(AAFwk::Want::PARAM_RESV_DISPLAY_ID, -1); WLOGFI("[WMSLife]PendingSessionActivation: want screenId %{public}" PRIu64 " uri: %{public}s", info.screenId_, info.want->GetElement().GetURI().c_str()); } WLOGFI("PendingSessionActivation:bundleName %{public}s, moduleName:%{public}s, abilityName:%{public}s, \ appIndex:%{public}d, affinity:%{public}s", info.bundleName_.c_str(), info.moduleName_.c_str(), info.abilityName_.c_str(), info.appIndex_, info.sessionAffinity.c_str()); WLOGFI("PendingSessionActivation callState:%{public}d, want persistentId: %{public}d, " "callingTokenId:%{public}d, uiAbilityId: %{public}" PRIu64 ", windowMode: %{public}d, caller persistentId: %{public}d", info.callState_, info.persistentId_, info.callingTokenId_, info.uiAbilityId_, info.windowMode, info.callerPersistentId_); if (session->pendingSessionActivationFunc_) { session->pendingSessionActivationFunc_(info); } return WSError::WS_OK; }; PostTask(task, "PendingSessionActivation"); return WSError::WS_OK; } WSError SceneSession::TerminateSession(const sptr abilitySessionInfo) { auto task = [weakThis = wptr(this), abilitySessionInfo]() { auto session = weakThis.promote(); if (!session) { WLOGFE("session is null"); return WSError::WS_ERROR_DESTROYED_OBJECT; } if (abilitySessionInfo == nullptr) { WLOGFE("abilitySessionInfo is null"); return WSError::WS_ERROR_NULLPTR; } if (session->isTerminating) { WLOGFE("TerminateSession isTerminating, return!"); return WSError::WS_ERROR_INVALID_OPERATION; } session->isTerminating = true; SessionInfo info; info.abilityName_ = abilitySessionInfo->want.GetElement().GetAbilityName(); info.bundleName_ = abilitySessionInfo->want.GetElement().GetBundleName(); info.callerToken_ = abilitySessionInfo->callerToken; info.persistentId_ = static_cast(abilitySessionInfo->persistentId); { std::lock_guard lock(session->sessionInfoMutex_); session->sessionInfo_.closeAbilityWant = std::make_shared(abilitySessionInfo->want); session->sessionInfo_.resultCode = abilitySessionInfo->resultCode; } if (session->terminateSessionFunc_) { session->terminateSessionFunc_(info); } return WSError::WS_OK; }; PostLifeCycleTask(task, "TerminateSession", LifeCycleTaskType::STOP); return WSError::WS_OK; } WSError SceneSession::NotifySessionException(const sptr abilitySessionInfo, bool needRemoveSession) { if (!SessionPermission::VerifySessionPermission()) { WLOGFE("The interface permission failed."); return WSError::WS_ERROR_INVALID_PERMISSION; } auto task = [weakThis = wptr(this), abilitySessionInfo, needRemoveSession]() { auto session = weakThis.promote(); if (!session) { WLOGFE("session is null"); return WSError::WS_ERROR_DESTROYED_OBJECT; } if (abilitySessionInfo == nullptr) { WLOGFE("abilitySessionInfo is null"); return WSError::WS_ERROR_NULLPTR; } if (session->isTerminating) { WLOGFE("NotifySessionException isTerminating, return!"); return WSError::WS_ERROR_INVALID_OPERATION; } session->isTerminating = true; SessionInfo info; info.abilityName_ = abilitySessionInfo->want.GetElement().GetAbilityName(); info.bundleName_ = abilitySessionInfo->want.GetElement().GetBundleName(); info.callerToken_ = abilitySessionInfo->callerToken; info.errorCode = abilitySessionInfo->errorCode; info.errorReason = abilitySessionInfo->errorReason; info.persistentId_ = static_cast(abilitySessionInfo->persistentId); { std::lock_guard lock(session->sessionInfoMutex_); session->sessionInfo_.closeAbilityWant = std::make_shared(abilitySessionInfo->want); session->sessionInfo_.errorCode = abilitySessionInfo->errorCode; session->sessionInfo_.errorReason = abilitySessionInfo->errorReason; } if (session->sessionExceptionFunc_) { auto exceptionFunc = *(session->sessionExceptionFunc_); exceptionFunc(info, needRemoveSession); } if (session->jsSceneSessionExceptionFunc_) { auto exceptionFunc = *(session->jsSceneSessionExceptionFunc_); exceptionFunc(info, needRemoveSession); } return WSError::WS_OK; }; PostLifeCycleTask(task, "NotifySessionException", LifeCycleTaskType::STOP); return WSError::WS_OK; } WSRect SceneSession::GetLastSafeRect() const { return lastSafeRect; } void SceneSession::SetLastSafeRect(WSRect rect) { lastSafeRect.posX_ = rect.posX_; lastSafeRect.posY_ = rect.posY_; lastSafeRect.width_ = rect.width_; lastSafeRect.height_ = rect.height_; return; } bool SceneSession::AddSubSession(const sptr& subSession) { if (subSession == nullptr) { WLOGFE("[WMSSub] subSession is nullptr"); return false; } const auto& persistentId = subSession->GetPersistentId(); auto iter = std::find_if(subSession_.begin(), subSession_.end(), [persistentId](sptr session) { bool res = (session != nullptr && session->GetPersistentId() == persistentId) ? true : false; return res; }); if (iter != subSession_.end()) { WLOGFE("[WMSSub] Sub ession is already exists, id: %{public}d, parentId: %{public}d", subSession->GetPersistentId(), GetPersistentId()); return false; } WLOGFD("[WMSSub] Success, id: %{public}d, parentId: %{public}d", subSession->GetPersistentId(), GetPersistentId()); subSession_.push_back(subSession); return true; } bool SceneSession::RemoveSubSession(int32_t persistentId) { auto iter = std::find_if(subSession_.begin(), subSession_.end(), [persistentId](sptr session) { bool res = (session != nullptr && session->GetPersistentId() == persistentId) ? true : false; return res; }); if (iter == subSession_.end()) { WLOGFE("[WMSSub] Could not find subsession, id: %{public}d, parentId: %{public}d", persistentId, GetPersistentId()); return false; } WLOGFD("[WMSSub] Success, id: %{public}d, parentId: %{public}d", persistentId, GetPersistentId()); subSession_.erase(iter); return true; } void SceneSession::NotifyPiPWindowPrepareClose() { WLOGFD("NotifyPiPWindowPrepareClose"); auto task = [weakThis = wptr(this)]() { auto session = weakThis.promote(); if (!session) { WLOGFE("session is null"); return; } if (session->sessionChangeCallback_ && session->sessionChangeCallback_->onPrepareClosePiPSession_) { session->sessionChangeCallback_->onPrepareClosePiPSession_(); } WLOGFD("NotifyPiPWindowPrepareClose, id: %{public}d", session->GetPersistentId()); return; }; PostTask(task, "NotifyPiPWindowPrepareClose"); } WSError SceneSession::RecoveryPullPiPMainWindow(int32_t persistentId, const Rect& rect) { WLOGFD("NotifyRecoveryPullPiPMainWindow"); auto task = [weakThis = wptr(this), persistentId, rect]() { auto session = weakThis.promote(); if (!session) { WLOGFE("session is null"); return WSError::WS_ERROR_DESTROYED_OBJECT; } if (session->specificCallback_ != nullptr) { session->specificCallback_->onRecoveryPullPiPMainWindow_(persistentId, rect); } return WSError::WS_OK; }; PostTask(task, "RecoveryPullPiPMainWindow"); return WSError::WS_OK; } std::vector> SceneSession::GetSubSession() const { return subSession_; } WSRect SceneSession::GetSessionTargetRect() const { WSRect rect; if (moveDragController_) { rect = moveDragController_->GetTargetRect(); } else { WLOGFI("moveDragController_ is null"); } return rect; } void SceneSession::SetWindowDragHotAreaListener(const NotifyWindowDragHotAreaFunc& func) { if (moveDragController_) { moveDragController_->SetWindowDragHotAreaFunc(func); } } void SceneSession::NotifySessionForeground(uint32_t reason, bool withAnimation) { if (!sessionStage_) { return; } return sessionStage_->NotifySessionForeground(reason, withAnimation); } void SceneSession::NotifySessionBackground(uint32_t reason, bool withAnimation, bool isFromInnerkits) { if (!sessionStage_) { return; } return sessionStage_->NotifySessionBackground(reason, withAnimation, isFromInnerkits); } WSError SceneSession::SetTextFieldAvoidInfo(double textFieldPositionY, double textFieldHeight) { textFieldPositionY_ = textFieldPositionY; textFieldHeight_ = textFieldHeight; return WSError::WS_OK; } void SceneSession::OnPiPMoveCallback(const WSRect& rect, const SizeChangeReason& reason) { if (!WindowHelper::IsPipWindow(GetWindowType())) { return; } if (reason == SizeChangeReason::MOVE) { NotifySessionRectChange(rect, reason); } if (reason == SizeChangeReason::DRAG_END) { ClearPiPRectPivotInfo(); ScenePersistentStorage::Insert("pip_window_pos_x", rect.posX_, ScenePersistentStorageType::PIP_INFO); ScenePersistentStorage::Insert("pip_window_pos_y", rect.posY_, ScenePersistentStorageType::PIP_INFO); } } bool SceneSession::InitPiPRectInfo() { auto requestRect = GetSessionRequestRect(); if (requestRect.width_ == 0 || requestRect.height_ == 0) { return false; } ClearPiPRectPivotInfo(); pipRectInfo_.originWidth_ = requestRect.width_; pipRectInfo_.originHeight_ = requestRect.height_; int32_t level = 0; ScenePersistentStorage::Get("pip_window_level", level, ScenePersistentStorageType::PIP_INFO); pipRectInfo_.level_ = static_cast(level); return true; } void SceneSession::ClearPiPRectPivotInfo() { pipRectInfo_.xPivot_ = PiPScalePivot::UNDEFINED; pipRectInfo_.yPivot_ = PiPScalePivot::UNDEFINED; } void SceneSession::SavePiPRectInfo() { ScenePersistentStorage::Insert("pip_window_level", static_cast(pipRectInfo_.level_), ScenePersistentStorageType::PIP_INFO); } void SceneSession::GetNewPiPRect(const uint32_t displayWidth, const uint32_t displayHeight, Rect& rect) { auto display = DisplayManager::GetInstance().GetDefaultDisplay(); if (!display) { WLOGFE("cannot find display"); return; } Rotation rotation = display->GetRotation(); bool isLandscape = rotation == Rotation::ROTATION_90 || rotation == Rotation::ROTATION_270; PiPUtil::GetRectByScale(displayWidth, displayHeight, pipRectInfo_.level_, rect, isLandscape); WLOGFD("scale rect = (%{public}d, %{public}d, %{public}d, %{public}d)", rect.posX_, rect.posY_, rect.width_, rect.height_); auto sessionRect = GetSessionRect(); WLOGFD("session rect = (%{public}d, %{public}d, %{public}d, %{public}d)", sessionRect.posX_, sessionRect.posY_, sessionRect.width_, sessionRect.height_); bool isMoveOrDrag = moveDragController_ && (moveDragController_->GetStartDragFlag() || moveDragController_->GetStartMoveFlag()); if (sessionRect.width_ != 0 && sessionRect.height_ != 0 && !isMoveOrDrag) { if (pipRectInfo_.xPivot_ == PiPScalePivot::UNDEFINED || pipRectInfo_.yPivot_ == PiPScalePivot::UNDEFINED) { // If no anchor, create anchor PiPUtil::UpdateRectPivot(sessionRect.posX_, sessionRect.width_, displayWidth, pipRectInfo_.xPivot_); PiPUtil::UpdateRectPivot(sessionRect.posY_, sessionRect.height_, displayHeight, pipRectInfo_.yPivot_); } PiPUtil::GetRectByPivot(rect.posX_, sessionRect.width_, rect.width_, displayWidth, pipRectInfo_.xPivot_); PiPUtil::GetRectByPivot(rect.posY_, sessionRect.height_, rect.height_, displayHeight, pipRectInfo_.yPivot_); WLOGFD("pivot rect = (%{public}d, %{public}d, %{public}d, %{public}d)", rect.posX_, rect.posY_, rect.width_, rect.height_); } PiPUtil::GetValidRect(displayWidth, displayHeight, rect); WLOGFD("valid rect = (%{public}d, %{public}d, %{public}d, %{public}d)", rect.posX_, rect.posY_, rect.width_, rect.height_); } void SceneSession::ProcessUpdatePiPRect(SizeChangeReason reason) { if (!WindowHelper::IsPipWindow(GetWindowType())) { WLOGFW("Session is not PiP type!"); return; } auto display = DisplayManager::GetInstance().GetDefaultDisplay(); if (!display) { WLOGFE("can't find display info"); return; } uint32_t displayWidth = static_cast(display->GetWidth()); uint32_t displayHeight = static_cast(display->GetHeight()); float displayVpr = display->GetVirtualPixelRatio(); if (displayVpr < 0.0f) { displayVpr = 1.5f; } PiPUtil::SetDisplayVpr(displayVpr); // default pos of phone is the right top Rect rect = { 0, 0, pipRectInfo_.originWidth_, pipRectInfo_.originHeight_ }; if (reason != SizeChangeReason::ROTATION) { ScenePersistentStorage::Get("pip_window_pos_x", rect.posX_, ScenePersistentStorageType::PIP_INFO); ScenePersistentStorage::Get("pip_window_pos_y", rect.posY_, ScenePersistentStorageType::PIP_INFO); } if (rect.posX_ == 0) { rect.posX_ = displayWidth; } WLOGFD("window rect: (%{public}d, %{public}d, %{public}u, %{public}u)", rect.posX_, rect.posY_, rect.width_, rect.height_); GetNewPiPRect(displayWidth, displayHeight, rect); WLOGFD("window new rect: (%{public}d, %{public}d, %{public}u, %{public}u)", rect.posX_, rect.posY_, rect.width_, rect.height_); ScenePersistentStorage::Insert("pip_window_pos_x", rect.posX_, ScenePersistentStorageType::PIP_INFO); ScenePersistentStorage::Insert("pip_window_pos_y", rect.posY_, ScenePersistentStorageType::PIP_INFO); WSRect newRect = SessionHelper::TransferToWSRect(rect); SetSessionRect(newRect); SetSessionRequestRect(newRect); Session::UpdateRect(newRect, reason); NotifySessionRectChange(newRect, reason); SingletonContainer::Get() .ReportPiPResize(static_cast(pipRectInfo_.level_), newRect.width_, newRect.height_); } WSError SceneSession::UpdatePiPRect(uint32_t width, uint32_t height, PiPRectUpdateReason reason) { if (!WindowHelper::IsPipWindow(GetWindowType())) { return WSError::WS_DO_NOTHING; } auto task = [weakThis = wptr(this), width, height, reason]() { auto session = weakThis.promote(); if (!session || session->isTerminating) { WLOGE("SceneSession::UpdatePiPRect session is null or is terminating"); return WSError::WS_ERROR_INVALID_OPERATION; } switch (reason) { case PiPRectUpdateReason::REASON_PIP_START_WINDOW: session->InitPiPRectInfo(); session->ProcessUpdatePiPRect(SizeChangeReason::CUSTOM_ANIMATION_SHOW); break; case PiPRectUpdateReason::REASON_PIP_SCALE_CHANGE: session->pipRectInfo_.level_ = static_cast((static_cast( session->pipRectInfo_.level_) + 1) % static_cast(PiPScaleLevel::COUNT)); session->ProcessUpdatePiPRect(SizeChangeReason::TRANSFORM); break; case PiPRectUpdateReason::REASON_PIP_VIDEO_RATIO_CHANGE: session->ClearPiPRectPivotInfo(); session->pipRectInfo_.originWidth_ = width; session->pipRectInfo_.originHeight_ = height; if (session->moveDragController_ && (session->moveDragController_->GetStartDragFlag() || session->moveDragController_->GetStartMoveFlag())) { WSRect rect = session->moveDragController_->GetTargetRect(); ScenePersistentStorage::Insert( "pip_window_pos_x", rect.posX_, ScenePersistentStorageType::PIP_INFO); ScenePersistentStorage::Insert( "pip_window_pos_y", rect.posY_, ScenePersistentStorageType::PIP_INFO); } session->ProcessUpdatePiPRect(SizeChangeReason::UNDEFINED); SingletonContainer::Get().ReportPiPRatio(width, height); break; case PiPRectUpdateReason::REASON_DISPLAY_ROTATION_CHANGE: session->ProcessUpdatePiPRect(SizeChangeReason::ROTATION); session->ClearPiPRectPivotInfo(); break; default: return WSError::WS_DO_NOTHING; } return WSError::WS_OK; }; PostTask(task, "UpdatePiPRect"); return WSError::WS_OK; } void SceneSession::SendPointerEventToUI(std::shared_ptr pointerEvent) { std::lock_guard lock(pointerEventMutex_); if (systemSessionPointerEventFunc_ != nullptr) { systemSessionPointerEventFunc_(pointerEvent); } } void SceneSession::SendKeyEventToUI(std::shared_ptr keyEvent) { std::lock_guard lock(keyEventMutex_); if (systemSessionKeyEventFunc_ != nullptr) { systemSessionKeyEventFunc_(keyEvent); } } WSError SceneSession::UpdateSizeChangeReason(SizeChangeReason reason) { auto task = [weakThis = wptr(this), reason]() { auto session = weakThis.promote(); if (!session) { WLOGFE("session is null"); return WSError::WS_ERROR_DESTROYED_OBJECT; } if (session->sessionInfo_.isSystem_) { // system scene no need to update reason return WSError::WS_DO_NOTHING; } session->reason_ = reason; if (reason != SizeChangeReason::UNDEFINED) { HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "SceneSession::UpdateSizeChangeReason%d reason:%d", session->GetPersistentId(), static_cast(reason)); WLOGFD("[WMSLayout]UpdateSizeChangeReason Id: %{public}d, reason: %{public}d", session->GetPersistentId(), reason); } return WSError::WS_OK; }; PostTask(task, "UpdateSizeChangeReason"); return WSError::WS_OK; } bool SceneSession::IsDirtyWindow() { return isDirty_; } void SceneSession::NotifyUILostFocus() { if (moveDragController_) { moveDragController_->OnLostFocus(); } Session::NotifyUILostFocus(); } void SceneSession::SetScale(float scaleX, float scaleY, float pivotX, float pivotY) { if (scaleX_ != scaleX || scaleY_ != scaleY || pivotX_ != pivotX || pivotY_ != pivotY) { Session::SetScale(scaleX, scaleY, pivotX, pivotY); if (specificCallback_ != nullptr) { specificCallback_->onWindowInfoUpdate_(GetPersistentId(), WindowUpdateType::WINDOW_UPDATE_PROPERTY); } if (sessionStage_ != nullptr) { Transform transform; transform.scaleX_ = scaleX; transform.scaleY_ = scaleY; transform.pivotX_ = pivotX; transform.pivotY_ = pivotY; sessionStage_->NotifyTransformChange(transform); } else { WLOGFE("sessionStage_ is nullptr"); } } } void SceneSession::RequestHideKeyboard(bool isAppColdStart) { #ifdef IMF_ENABLE auto task = [weakThis = wptr(this), isAppColdStart]() { auto session = weakThis.promote(); if (!session) { WLOGFE("[WMSInput] Session is null, notify inputMethod framework hide keyboard failed!"); return; } WLOGFI("[WMSInput] Notify inputMethod framework hide keyboard start, id: %{public}d," "isAppColdStart: %{public}d", session->GetPersistentId(), isAppColdStart); if (MiscServices::InputMethodController::GetInstance()) { MiscServices::InputMethodController::GetInstance()->RequestHideInput(); WLOGFI("[WMSInput] Notify inputMethod framework hide keyboard end, id: %{public}d", session->GetPersistentId()); } }; PostExportTask(task, "RequestHideKeyboard"); #endif } bool SceneSession::IsStartMoving() const { return isStartMoving_.load(); } void SceneSession::SetIsStartMoving(const bool startMoving) { isStartMoving_.store(startMoving); } } // namespace OHOS::Rosen