* 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/session.h"
#include <cmath>
#include <regex>
#include <string>
#include <application_context.h>
#include "ability_info.h"
#include "input_manager.h"
#include "key_event.h"
#include "pointer_event.h"
#include <transaction/rs_interfaces.h>
#include <transaction/rs_transaction.h>
#include <ui/rs_surface_node.h>
#include "proxy/include/window_info.h"
#include "common/include/session_permission.h"
#include "fold_screen_state_internel.h"
#include "image_source.h"
#include "rs_adapter.h"
#include "session_coordinate_helper.h"
#include "session_helper.h"
#include "surface_capture_future.h"
#include "window_helper.h"
#include "window_manager_hilog.h"
#include "parameters.h"
#include <hisysevent.h>
#include "hitrace_meter.h"
#include "screen_session_manager_client/include/screen_session_manager_client.h"
#include "session/host/include/pc_fold_screen_manager.h"
#include "perform_reporter.h"
#include "session/host/include/scene_persistent_storage.h"
#include "screen_manager.h"
namespace OHOS::Rosen {
namespace {
constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, HILOG_DOMAIN_WINDOW, "Session" };
std::atomic<int32_t> g_persistentId = INVALID_SESSION_ID;
std::set<int32_t> g_persistentIdSet;
std::mutex g_persistentIdSetMutex;
constexpr float INNER_BORDER_VP = 5.0f;
constexpr float OUTSIDE_BORDER_VP = 4.0f;
constexpr float INNER_ANGLE_VP = 16.0f;
constexpr uint32_t MAX_LIFE_CYCLE_TASK_IN_QUEUE = 15;
constexpr int64_t LIFE_CYCLE_TASK_EXPIRED_TIME_LIMIT = 350;
static bool g_enableForceUIFirst = system::GetParameter("window.forceUIFirst.enabled", "1") == "1";
constexpr int64_t STATE_DETECT_DELAYTIME = 6 * 1000;
constexpr DisplayId VIRTUAL_DISPLAY_ID = 999;
constexpr int32_t SNAPSHOT_ERROR_INVALID_SURFACE_NODE = -1;
constexpr int32_t SNAPSHOT_ERROR_RENDER_CONTEXT = -2;
constexpr int32_t SNAPSHOT_ERROR_TAKE_CAPTURE = -3;
constexpr int32_t SNAPSHOT_ERROR_EMPTY_PIXELMAP = -4;
constexpr int32_t TIMES_TO_WAIT_FOR_VSYNC_ONECE = 1;
constexpr int32_t TIMES_TO_WAIT_FOR_VSYNC_TWICE = 2;
constexpr double KILOBYTE = 1024.0;
constexpr int32_t SNAP_SHOT_RECOVER_KEY = 10;
const std::map<SessionState, bool> ATTACH_MAP = {
{ SessionState::STATE_DISCONNECT, false },
{ SessionState::STATE_CONNECT, false },
{ SessionState::STATE_FOREGROUND, true },
{ SessionState::STATE_ACTIVE, true },
{ SessionState::STATE_INACTIVE, false },
{ SessionState::STATE_BACKGROUND, false },
};
const std::map<SessionState, bool> DETACH_MAP = {
{ SessionState::STATE_DISCONNECT, true },
{ SessionState::STATE_CONNECT, false },
{ SessionState::STATE_FOREGROUND, false },
{ SessionState::STATE_ACTIVE, false },
{ SessionState::STATE_INACTIVE, true },
{ SessionState::STATE_BACKGROUND, true },
};
const bool CORRECTION_ENABLE = system::GetIntParameter<int32_t>("const.system.sensor_correction_enable", 0) == 1;
const uint32_t ROTATION_90 = 90;
const uint32_t ROTATION_360 = 360;
const uint32_t ROTATION_LANDSCAPE_INVERTED = 3;
const std::string APP_CAST_SCREEN_NAME = "HwCast_AppModeDisplay";
constexpr float BLUR_SNAPSHOT_SCALE = 0.5f;
}
const std::string ATTACH_EVENT_NAME { "wms::ReportWindowTimeout_Attach" };
const std::string DETACH_EVENT_NAME { "wms::ReportWindowTimeout_Detach" };
std::shared_ptr<AppExecFwk::EventHandler> Session::mainHandler_;
bool Session::isScbCoreEnabled_ = false;
Session::Session(const SessionInfo& info) : sessionInfo_(info)
{
property_ = sptr<WindowSessionProperty>::MakeSptr();
property_->SetWindowType(static_cast<WindowType>(info.windowType_));
layoutController_ = sptr<LayoutController>::MakeSptr(property_);
layoutController_->SetSystemConfigFunc([this]() {
return this->GetSystemConfig();
});
if (!mainHandler_) {
auto runner = AppExecFwk::EventRunner::GetMainEventRunner();
mainHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner);
}
using type = std::underlying_type_t<MMI::WindowArea>;
for (type area = static_cast<type>(MMI::WindowArea::FOCUS_ON_TOP);
area <= static_cast<type>(MMI::WindowArea::FOCUS_ON_BOTTOM_RIGHT); ++area) {
auto ret = windowAreas_.insert(
std::pair<MMI::WindowArea, WSRectF>(static_cast<MMI::WindowArea>(area), WSRectF()));
if (!ret.second) {
WLOGFE("Failed to insert area:%{public}d", area);
}
}
if (info.want != nullptr) {
auto focusedOnShow = info.want->GetBoolParam(AAFwk::Want::PARAM_RESV_WINDOW_FOCUSED, true);
TLOGD(WmsLogTag::WMS_FOCUS, "focusedOnShow:%{public}d", focusedOnShow);
SetFocusedOnShow(focusedOnShow);
}
static const std::regex pattern(R"(^SCBScreenLock[0-9]+$)");
if (std::regex_match(info.bundleName_, pattern)) {
TLOGD(WmsLogTag::WMS_LIFE, "bundleName: %{public}s", info.bundleName_.c_str());
isScreenLockWindow_ = true;
}
}
Session::~Session()
{
TLOGI(WmsLogTag::WMS_LIFE, "id:%{public}d", GetPersistentId());
if (mainHandler_) {
mainHandler_->PostTask([surfaceNode = std::move(surfaceNode_),
shadowSurfaceNode = std::move(shadowSurfaceNode_),
leashWinShadowSurfaceNode = std::move(leashWinShadowSurfaceNode_)]() {
});
}
}
void Session::SetEventHandler(const std::shared_ptr<AppExecFwk::EventHandler>& handler,
const std::shared_ptr<AppExecFwk::EventHandler>& exportHandler)
{
handler_ = handler;
exportHandler_ = exportHandler;
}
void Session::PostTask(Task&& task, const std::string& name, int64_t delayTime)
{
if (!handler_ || handler_->GetEventRunner()->IsCurrentRunnerThread()) {
HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "s:%s", name.c_str());
return task();
}
auto localTask = [task = std::move(task), name] {
HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "s:%s", name.c_str());
task();
};
handler_->PostTask(std::move(localTask), "wms:" + name, delayTime, AppExecFwk::EventQueue::Priority::IMMEDIATE);
}
void Session::PostExportTask(Task&& task, const std::string& name, int64_t delayTime)
{
if (!exportHandler_ || exportHandler_->GetEventRunner()->IsCurrentRunnerThread()) {
HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "s:%s", name.c_str());
return task();
}
auto localTask = [task = std::move(task), name] {
HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "s:%s", name.c_str());
task();
};
exportHandler_->PostTask(std::move(localTask), "wms:" + name, delayTime,
AppExecFwk::EventQueue::Priority::IMMEDIATE);
}
int32_t Session::GetPersistentId() const
{
return persistentId_;
}
int32_t Session::GetCurrentRotation() const
{
return currentRotation_;
}
void Session::SetSurfaceNodeAlphaChangedCallback(const std::shared_ptr<RSSurfaceNode>& surfaceNode)
{
if (surfaceNode == nullptr) {
TLOGE(WmsLogTag::WMS_ATTRIBUTE, "surfaceNode is null, win=[%{public}d, %{public}s]",
GetWindowId(), GetWindowName().c_str());
return;
}
surfaceNode->SetAlphaChangedCallback([weak = wptr(this), where = __func__](float alpha) {
auto session = weak.promote();
if (!session) {
TLOGNE(WmsLogTag::WMS_ATTRIBUTE, "%{public}s: session is null", where);
return;
}
TLOGNI(WmsLogTag::WMS_ATTRIBUTE, "%{public}s: win=[%{public}d, %{public}s], alpha=%{public}f",
where, session->GetWindowId(), session->GetWindowName().c_str(), alpha);
session->SetSurfaceNodeAlpha(alpha);
});
}
void Session::SetSurfaceNode(const std::shared_ptr<RSSurfaceNode>& surfaceNode)
{
RSAdapterUtil::SetRSUIContext(surfaceNode, GetRSUIContext(), true);
SetSurfaceNodeAlphaChangedCallback(surfaceNode);
{
std::lock_guard<std::mutex> lock(surfaceNodeMutex_);
surfaceNode_ = surfaceNode;
if (surfaceNode_) {
surfaceNode_->MarkLayerPartRender(isLayerPartRender_);
}
shadowSurfaceNode_ = RSAdapterUtil::IsClientMultiInstanceEnabled() && surfaceNode_ ?
surfaceNode_->CreateShadowSurfaceNode() : nullptr;
}
OnSurfaceNodeChanged();
}
std::shared_ptr<RSSurfaceNode> Session::GetSurfaceNode() const
{
std::lock_guard<std::mutex> lock(surfaceNodeMutex_);
return surfaceNode_;
}
std::shared_ptr<RSSurfaceNode> Session::GetSurfaceNode(bool isUpdateContextBeforeGet)
{
std::lock_guard<std::mutex> lock(surfaceNodeMutex_);
if (isUpdateContextBeforeGet) {
TLOGI(WmsLogTag::WMS_SCB,
"id: %{public}d, surfaceNode: %{public}s, original: %{public}s",
GetPersistentId(),
RSAdapterUtil::RSNodeToStr(surfaceNode_).c_str(),
RSAdapterUtil::RSUIContextToStr(GetRSUIContext()).c_str());
if (surfaceNode_) {
RSAdapterUtil::SetRSUIContext(surfaceNode_, GetRSUIContext(), true);
}
}
return surfaceNode_;
}
std::optional<NodeId> Session::GetSurfaceNodeId() const
{
std::lock_guard<std::mutex> lock(surfaceNodeMutex_);
if (surfaceNode_ != nullptr) {
return surfaceNode_->GetId();
}
return std::nullopt;
}
std::shared_ptr<RSSurfaceNode> Session::GetShadowSurfaceNode() const
{
std::lock_guard<std::mutex> lock(surfaceNodeMutex_);
return RSAdapterUtil::IsClientMultiInstanceEnabled() ? shadowSurfaceNode_ : surfaceNode_;
}
void Session::SetLeashWinSurfaceNode(std::shared_ptr<RSSurfaceNode> leashWinSurfaceNode)
{
auto rsUIContext = GetRSUIContext();
RSAdapterUtil::SetRSUIContext(leashWinSurfaceNode, rsUIContext, true);
if (g_enableForceUIFirst) {
AutoRSTransaction trans(rsUIContext);
if (!leashWinSurfaceNode && leashWinSurfaceNode_) {
leashWinSurfaceNode_->SetForceUIFirst(false);
}
}
std::lock_guard<std::mutex> lock(leashWinSurfaceNodeMutex_);
leashWinSurfaceNode_ = leashWinSurfaceNode;
leashWinShadowSurfaceNode_ = RSAdapterUtil::IsClientMultiInstanceEnabled() && leashWinSurfaceNode_ ?
leashWinSurfaceNode_->CreateShadowSurfaceNode() : nullptr;
}
std::shared_ptr<RSSurfaceNode> Session::GetLeashWinSurfaceNode() const
{
std::lock_guard<std::mutex> lock(leashWinSurfaceNodeMutex_);
return leashWinSurfaceNode_;
}
std::shared_ptr<RSSurfaceNode> Session::GetLeashWinShadowSurfaceNode() const
{
std::lock_guard<std::mutex> lock(leashWinSurfaceNodeMutex_);
return RSAdapterUtil::IsClientMultiInstanceEnabled() ? leashWinShadowSurfaceNode_ : leashWinSurfaceNode_;
}
std::shared_ptr<RSSurfaceNode> Session::GetMoveDragTargetSurfaceNode() const
{
if (auto leashWinSurfaceNode = GetLeashWinSurfaceNode()) {
return leashWinSurfaceNode;
}
return GetSurfaceNode();
}
void Session::SetFrameLayoutFinishListener(const NotifyFrameLayoutFinishFunc& func)
{
frameLayoutFinishFunc_ = func;
}
std::shared_ptr<Media::PixelMap> Session::GetSnapshot() const
{
std::lock_guard<std::mutex> lock(snapshotMutex_);
return snapshot_;
}
std::shared_ptr<Media::PixelMap> Session::GetPreloadSnapshot() const
{
std::lock_guard<std::mutex> lock(preloadSnapshotMutex_);
return preloadSnapshot_;
}
void Session::SetSessionInfoAncoSceneState(int32_t ancoSceneState)
{
std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
sessionInfo_.ancoSceneState = ancoSceneState;
}
void Session::SetSessionInfoTime(const std::string& time)
{
std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
sessionInfo_.time = time;
}
void Session::SetSessionInfoAbilityInfo(const std::shared_ptr<AppExecFwk::AbilityInfo>& abilityInfo)
{
std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
sessionInfo_.abilityInfo = abilityInfo;
}
void Session::SetSessionInfoSupportedWindowModes(const std::vector<AppExecFwk::SupportWindowMode>& updatedWindowModes)
{
std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
sessionInfo_.supportedWindowModes = updatedWindowModes;
}
void Session::SetSessionInfoWant(const std::shared_ptr<AAFwk::Want>& want)
{
std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
sessionInfo_.SetWantSafely(want);
}
void Session::ResetSessionInfoResultCode()
{
std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
sessionInfo_.resultCode = -1;
}
void Session::SetSessionInfoPersistentId(int32_t persistentId)
{
std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
sessionInfo_.persistentId_ = persistentId;
}
void Session::SetSessionInfoCallerPersistentId(int32_t callerPersistentId)
{
std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
sessionInfo_.callerPersistentId_ = callerPersistentId;
}
void Session::SetSessionInfoContinueState(ContinueState state)
{
std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
sessionInfo_.continueState = state;
}
void Session::SetSessionInfoLockedState(bool lockedState)
{
std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
sessionInfo_.lockedState = lockedState;
NotifySessionInfoLockedStateChange(lockedState);
}
void Session::SetSessionInfoIsClearSession(bool isClearSession)
{
std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
sessionInfo_.isClearSession = isClearSession;
}
void Session::SetSessionInfoAffinity(std::string affinity)
{
std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
sessionInfo_.sessionAffinity = affinity;
}
void Session::GetCloseAbilityWantAndClean(AAFwk::Want& outWant)
{
std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
if (sessionInfo_.closeAbilityWant != nullptr) {
outWant = *sessionInfo_.closeAbilityWant;
sessionInfo_.closeAbilityWant = nullptr;
}
}
void Session::SetSessionInfo(const SessionInfo& info)
{
std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
sessionInfo_.want = info.want;
sessionInfo_.callerToken_ = info.callerToken_;
sessionInfo_.requestCode = info.requestCode;
sessionInfo_.scenarios = info.scenarios;
sessionInfo_.callerPersistentId_ = info.callerPersistentId_;
sessionInfo_.callingTokenId_ = info.callingTokenId_;
sessionInfo_.uiAbilityId_ = info.uiAbilityId_;
sessionInfo_.requestId = info.requestId;
sessionInfo_.scbRequestId = info.scbRequestId;
sessionInfo_.startSetting = info.startSetting;
if (!info.continueSessionId_.empty()) {
sessionInfo_.continueSessionId_ = info.continueSessionId_;
}
sessionInfo_.isAtomicService_ = info.isAtomicService_;
sessionInfo_.callState_ = info.callState_;
sessionInfo_.processOptions = info.processOptions;
sessionInfo_.disableDelegator = info.disableDelegator;
sessionInfo_.reuseDelegatorWindow = info.reuseDelegatorWindow;
sessionInfo_.isGamePrelaunch_ = info.isGamePrelaunch_;
sessionInfo_.reuseSessionInGamePreLaunch_ = info.reuseSessionInGamePreLaunch_;
}
void Session::SetSessionInfoWindowInputType(uint32_t windowInputType)
{
TLOGI(WmsLogTag::WMS_EVENT, "id:%{public}d, type:%{public}u", GetPersistentId(), windowInputType);
{
std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
sessionInfo_.windowInputType_ = windowInputType;
}
NotifySessionInfoChange();
}
void Session::SetSessionInfoExpandInputFlag(uint32_t expandInputFlag)
{
{
std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
if (sessionInfo_.expandInputFlag_ != expandInputFlag) {
sessionInfo_.expandInputFlag_ = expandInputFlag;
TLOGI(WmsLogTag::WMS_EVENT, "id:%{public}d, flag:%{public}u", GetPersistentId(), expandInputFlag);
}
}
NotifySessionInfoChange();
}
uint32_t Session::GetSessionInfoExpandInputFlag() const
{
return sessionInfo_.expandInputFlag_;
}
void Session::SetSessionInfoCursorDragCount(int32_t count)
{
std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
sessionInfo_.cursorDragCount_ = count;
}
int32_t Session::GetSessionInfoCursorDragCount()
{
std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
return sessionInfo_.cursorDragCount_;
}
void Session::SetSessionInfoCursorDragFlag(bool value)
{
std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
sessionInfo_.cursorDragFlag_ = value;
}
bool Session::GetSessionInfoCursorDragFlag()
{
std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
return sessionInfo_.cursorDragFlag_;
}
void Session::SetSessionInfoReceiveDragEventEnabled(bool value)
{
std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
sessionInfo_.isReceiveDragEventEnabled_ = value;
}
bool Session::GetSessionInfoReceiveDragEventEnabled()
{
std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
return sessionInfo_.isReceiveDragEventEnabled_;
}
void Session::SetSessionInfoSeparationTouchEnabled(bool value)
{
std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
sessionInfo_.isSeparationTouchEnabled_ = value;
}
bool Session::GetSessionInfoSeparationTouchEnabled()
{
std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
return sessionInfo_.isSeparationTouchEnabled_;
}
void Session::SetSessionInfoAdvancedFeatureFlag(uint32_t bitPosition, bool value)
{
if (bitPosition >= ADVANCED_FEATURE_BIT_MAX) {
TLOGE(WmsLogTag::WMS_EVENT, "id:%{public}d, bitPosition:%{public}u", GetPersistentId(), bitPosition);
return;
}
{
std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
sessionInfo_.advancedFeatureFlag_.set(bitPosition, value);
}
}
bool Session::GetSessionInfoAdvancedFeatureFlag(uint32_t bitPosition)
{
if (bitPosition >= ADVANCED_FEATURE_BIT_MAX) {
TLOGE(WmsLogTag::WMS_EVENT, "id:%{public}d, bitPosition:%{public}u", GetPersistentId(), bitPosition);
return false;
}
{
std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
return sessionInfo_.advancedFeatureFlag_.test(bitPosition);
}
}
void Session::SetSessionInfoWindowMode(int32_t windowMode)
{
sessionInfo_.windowMode = windowMode;
}
void Session::SetDeviceType(const std::string& deviceType)
{
deviceType_ = deviceType;
}
const std::string& Session::GetDeviceType() const
{
return deviceType_;
}
void Session::SetSessionInfoRequestId(int32_t requestId)
{
sessionInfo_.requestId = requestId;
}
int32_t Session::GetSessionInfoRequestId() const
{
return sessionInfo_.requestId;
}
void Session::SetSessionInfoScbRequestId(int32_t scbRequestId)
{
sessionInfo_.scbRequestId = scbRequestId;
}
int32_t Session::GetSessionInfoScbRequestId() const
{
return sessionInfo_.scbRequestId;
}
DisplayId Session::GetScreenId() const
{
return sessionInfo_.screenId_;
}
void Session::SetScreenId(uint64_t screenId)
{
TLOGI(WmsLogTag::WMS_ATTRIBUTE, "win=[%{public}d, %{public}s], hasStage=%{public}d, screenId=%{public}" PRIu64,
GetPersistentId(), GetWindowName().c_str(), sessionStage_ != nullptr, screenId);
sessionInfo_.screenId_ = screenId;
if (sessionStage_) {
sessionStage_->UpdateDisplayId(screenId);
}
RSAdapterUtil::SetRSUIContext(GetSurfaceNode(), GetRSUIContext(), true);
}
void Session::SetScreenIdOnServer(uint64_t screenId)
{
sessionInfo_.screenId_ = screenId;
RSAdapterUtil::SetRSUIContext(GetSurfaceNode(), GetRSUIContext(), true);
}
void Session::SetAppInstanceKey(const std::string& appInstanceKey)
{
sessionInfo_.appInstanceKey_ = appInstanceKey;
}
std::shared_ptr<AppExecFwk::AbilityInfo> Session::GetSessionInfoAbilityInfo()
{
std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
return sessionInfo_.abilityInfo;
}
std::string Session::GetAppInstanceKey() const
{
return sessionInfo_.appInstanceKey_;
}
const SessionInfo& Session::GetSessionInfo() const
{
return sessionInfo_;
}
SessionInfo& Session::EditSessionInfo()
{
return sessionInfo_;
}
bool Session::GetNeedBackgroundAfterConnect() const
{
return needBackgroundAfterConnect_;
}
void Session::SetNeedBackgroundAfterConnect(bool isNeed)
{
TLOGI(WmsLogTag::WMS_LIFE, "id:%{public}d, need background after connect:%{public}d",
GetPersistentId(), isNeed);
needBackgroundAfterConnect_ = isNeed;
}
void Session::RecordLifecycleSessionStateError(SessionState expectState, SessionState currentState) const
{
std::ostringstream oss;
oss << "[Event]Session lifecycle scheduling error, expect session state:" << static_cast<uint32_t>(expectState)
<< ", current session state:" << static_cast<uint32_t>(currentState)
<< ", id:" << GetWindowId()
<< ", name:" << GetWindowName().c_str();
int32_t ret = HiSysEventWrite(
OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER,
"WINDOW_LIFE_CYCLE_EXCEPTION",
OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
"PID", getpid(),
"UID", getuid(),
"MSG", oss.str());
if (ret != 0) {
TLOGE(WmsLogTag::WMS_LIFE, "Write HiSysEvent error! ret:%{public}d", ret);
}
}
bool Session::RegisterLifecycleListener(const std::shared_ptr<ILifecycleListener>& listener)
{
return RegisterListenerLocked(lifecycleListeners_, listener);
}
bool Session::UnregisterLifecycleListener(const std::shared_ptr<ILifecycleListener>& listener)
{
return UnregisterListenerLocked(lifecycleListeners_, listener);
}
template<typename T>
bool Session::RegisterListenerLocked(std::vector<std::shared_ptr<T>>& holder, const std::shared_ptr<T>& listener)
{
if (listener == nullptr) {
WLOGFE("listener is nullptr");
return false;
}
std::lock_guard<std::recursive_mutex> lock(lifecycleListenersMutex_);
if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
WLOGFE("Listener already registered");
return false;
}
holder.emplace_back(listener);
return true;
}
template<typename T>
bool Session::UnregisterListenerLocked(std::vector<std::shared_ptr<T>>& holder, const std::shared_ptr<T>& listener)
{
if (listener == nullptr) {
WLOGFE("listener could not be null");
return false;
}
std::lock_guard<std::recursive_mutex> lock(lifecycleListenersMutex_);
holder.erase(std::remove_if(holder.begin(), holder.end(),
[listener](std::shared_ptr<T> registeredListener) { return registeredListener == listener; }),
holder.end());
return true;
}
void Session::NotifyActivation()
{
auto lifecycleListeners = GetListeners<ILifecycleListener>();
for (auto& listener : lifecycleListeners) {
if (auto listenerPtr = listener.lock()) {
listenerPtr->OnActivation();
}
}
lastSnapshotScreen_ = WSSnapshotHelper::GetInstance()->GetScreenStatus();
snapshotNeedCancel_.store(true);
}
void Session::NotifyConnect()
{
auto lifecycleListeners = GetListeners<ILifecycleListener>();
for (auto& listener : lifecycleListeners) {
if (auto listenerPtr = listener.lock()) {
listenerPtr->OnConnect();
}
}
}
void Session::NotifyForeground()
{
auto lifecycleListeners = GetListeners<ILifecycleListener>();
for (auto& listener : lifecycleListeners) {
if (auto listenerPtr = listener.lock()) {
listenerPtr->OnForeground();
}
}
}
void Session::NotifyBackground()
{
auto lifecycleListeners = GetListeners<ILifecycleListener>();
for (auto& listener : lifecycleListeners) {
if (auto listenerPtr = listener.lock()) {
listenerPtr->OnBackground();
}
}
}
void Session::NotifyDisconnect()
{
auto lifecycleListeners = GetListeners<ILifecycleListener>();
for (auto& listener : lifecycleListeners) {
if (auto listenerPtr = listener.lock()) {
listenerPtr->OnDisconnect();
}
}
}
void Session::NotifyLayoutFinished()
{
auto lifecycleListeners = GetListeners<ILifecycleListener>();
for (auto& listener : lifecycleListeners) {
if (auto listenerPtr = listener.lock()) {
listenerPtr->OnLayoutFinished();
}
}
}
void Session::NotifyRemoveBlank()
{
auto lifecycleListeners = GetListeners<ILifecycleListener>();
for (auto& listener : lifecycleListeners) {
if (auto listenerPtr = listener.lock()) {
listenerPtr->OnRemoveBlank();
}
}
}
void Session::NotifyPreLoadStartingWindowFinished()
{
auto lifecycleListeners = GetListeners<ILifecycleListener>();
for (auto& listener : lifecycleListeners) {
if (auto listenerPtr = listener.lock()) {
listenerPtr->OnPreLoadStartingWindowFinished();
}
}
}
void Session::NotifyRestart()
{
auto lifecycleListeners = GetListeners<ILifecycleListener>();
for (auto& listener : lifecycleListeners) {
if (auto listenerPtr = listener.lock()) {
listenerPtr->OnRestart();
}
}
}
void Session::NotifyAddSnapshot(bool useFfrt, bool needPersist,
bool needSaveSnapshot, std::function<void()>&& callback)
{
* for blankness prolems, persist snapshot could conflict with background process,
* thus no need to persist snapshot here
*/
if (needSaveSnapshot) {
SaveSnapshot(useFfrt, needPersist);
}
if (GetSurfaceNode() == nullptr) {
TLOGE(WmsLogTag::WMS_PATTERN, "surfaceNode invalid %{public}d", persistentId_);
return;
}
auto task = [weakThis = wptr(this), where = __func__, callback = std::move(callback)]() mutable {
auto session = weakThis.promote();
if (session == nullptr) {
TLOGNE(WmsLogTag::WMS_PATTERN, "%{public}s session is null", where);
return;
}
auto lifecycleListeners = session->GetListeners<ILifecycleListener>();
for (auto& listener : lifecycleListeners) {
if (auto listenerPtr = listener.lock()) {
listenerPtr->OnAddSnapshot(std::move(callback));
}
}
};
if (useFfrt) {
SetAddSnapshotCallback(task);
} else {
task();
}
}
void Session::NotifyRemoveSnapshot()
{
if (GetAppLockControl()) {
TLOGI(WmsLogTag::WMS_PATTERN, "not allowed");
return;
}
auto lifecycleListeners = GetListeners<ILifecycleListener>();
for (auto& listener : lifecycleListeners) {
if (auto listenerPtr = listener.lock()) {
listenerPtr->OnRemoveSnapshot();
}
}
}
void Session::NotifyUpdateSnapshotWindow()
{
auto lifecycleListeners = GetListeners<ILifecycleListener>();
for (auto& listener : lifecycleListeners) {
if (auto listenerPtr = listener.lock()) {
listenerPtr->OnUpdateSnapshotWindow();
}
}
}
void Session::NotifyExtensionDied()
{
if (!SessionPermission::IsSystemCalling()) {
TLOGE(WmsLogTag::WMS_UIEXT, "permission denied!");
return;
}
TLOGI(WmsLogTag::WMS_UIEXT, "NotifyExtensionDied called in session(persistentId:%{public}d).", persistentId_);
auto lifecycleListeners = GetListeners<ILifecycleListener>();
for (auto& listener : lifecycleListeners) {
if (auto listenerPtr = listener.lock()) {
listenerPtr->OnExtensionDied();
}
}
}
void Session::NotifyExtensionTimeout(int32_t errorCode)
{
if (!SessionPermission::IsSystemCalling()) {
TLOGE(WmsLogTag::WMS_UIEXT, "permission denied!");
return;
}
TLOGI(WmsLogTag::WMS_UIEXT, "NotifyExtensionTimeout(errorCode:%{public}d) in session(persistentId:%{public}d).",
errorCode, persistentId_);
auto lifecycleListeners = GetListeners<ILifecycleListener>();
for (auto& listener : lifecycleListeners) {
if (auto listenerPtr = listener.lock()) {
listenerPtr->OnExtensionTimeout(errorCode);
}
}
}
void Session::NotifyTransferAccessibilityEvent(const Accessibility::AccessibilityEventInfo& info,
int64_t uiExtensionIdLevel)
{
auto lifecycleListeners = GetListeners<ILifecycleListener>();
for (auto& listener : lifecycleListeners) {
if (auto listenerPtr = listener.lock()) {
listenerPtr->OnAccessibilityEvent(info, uiExtensionIdLevel);
}
}
}
void Session::NotifyExtensionDetachToDisplay()
{
TLOGI(WmsLogTag::WMS_UIEXT, "called");
if (!SessionPermission::IsSystemCalling()) {
TLOGE(WmsLogTag::WMS_UIEXT, "permission denied!");
return;
}
auto lifecycleListeners = GetListeners<ILifecycleListener>();
for (auto& listener : lifecycleListeners) {
if (auto listenerPtr = listener.lock()) {
listenerPtr->OnExtensionDetachToDisplay();
}
}
}
float Session::GetAspectRatio() const
{
return layoutController_->GetAspectRatio();
}
WSError Session::SetAspectRatio(float ratio)
{
layoutController_->SetAspectRatio(ratio);
return WSError::WS_OK;
}
SessionState Session::GetSessionState() const
{
return state_;
}
void Session::SetSessionState(SessionState state)
{
if (state < SessionState::STATE_DISCONNECT || state > SessionState::STATE_END) {
WLOGFD("Invalid session state: %{public}u", state);
return;
}
state_ = state;
SetMainSessionUIStateDirty(true);
}
void Session::UpdateSessionState(SessionState state)
{
if (state == SessionState::STATE_DISCONNECT ||
state == SessionState::STATE_INACTIVE ||
state == SessionState::STATE_BACKGROUND) {
RemoveWindowDetectTask();
}
state_ = state;
SetMainSessionUIStateDirty(true);
NotifySessionStateChange(state);
}
void Session::UpdateSessionTouchable(bool touchable)
{
auto property = GetSessionProperty();
if (property == nullptr) {
TLOGE(WmsLogTag::WMS_EVENT, "property is null");
return;
}
property->SetTouchable(touchable);
NotifySessionTouchableChange(touchable);
}
WSError Session::SetFocusable(bool isFocusable)
{
TLOGI(WmsLogTag::WMS_FOCUS, "id: %{public}d, focusable: %{public}d", GetPersistentId(), isFocusable);
auto property = GetSessionProperty();
if (property == nullptr) {
TLOGE(WmsLogTag::WMS_EVENT, "property is null");
return WSError::WS_ERROR_NULLPTR;
}
property->SetFocusable(isFocusable);
if (isFocused_ && !GetFocusable()) {
FocusChangeReason reason = FocusChangeReason::FOCUSABLE;
NotifyRequestFocusStatusNotifyManager(false, true, reason);
}
return WSError::WS_OK;
}
void Session::SetSystemFocusable(bool systemFocusable)
{
TLOGI(WmsLogTag::WMS_FOCUS, "id: %{public}d, systemFocusable: %{public}d", GetPersistentId(), systemFocusable);
systemFocusable_ = systemFocusable;
if (isFocused_ && !systemFocusable) {
FocusChangeReason reason = FocusChangeReason::FOCUSABLE;
NotifyRequestFocusStatusNotifyManager(false, true, reason);
}
}
WSError Session::SetFocusableOnShow(bool isFocusableOnShow)
{
PostTask([weakThis = wptr(this), isFocusableOnShow] {
auto session = weakThis.promote();
if (session == nullptr) {
TLOGNE(WmsLogTag::WMS_FOCUS, "session is invalid");
return;
}
TLOGND(WmsLogTag::WMS_FOCUS, "id: %{public}d, focusableOnShow: %{public}d",
session->GetPersistentId(), isFocusableOnShow);
session->focusableOnShow_ = isFocusableOnShow;
}, __func__);
return WSError::WS_OK;
}
bool Session::GetFocusable() const
{
auto property = GetSessionProperty();
if (property) {
return property->GetFocusable();
}
WLOGFD("property is null");
return true;
}
bool Session::GetSystemFocusable() const
{
if (parentSession_) {
return systemFocusable_ && parentSession_->GetSystemFocusable();
}
return systemFocusable_;
}
bool Session::CheckFocusable() const
{
return GetFocusable() && GetSystemFocusable();
}
bool Session::IsFocusableOnShow() const
{
return focusableOnShow_;
}
bool Session::IsFocused() const
{
return isFocused_;
}
void Session::SetNeedNotify(bool needNotify)
{
needNotify_ = needNotify;
}
bool Session::NeedNotify() const
{
return needNotify_;
}
void Session::SetFocusedOnShow(bool focusedOnShow)
{
if (focusedOnShow == focusedOnShow_) {
return;
}
TLOGI(WmsLogTag::WMS_FOCUS, "[%{public}d, %{public}d]", focusedOnShow, GetPersistentId());
focusedOnShow_ = focusedOnShow;
}
bool Session::IsFocusedOnShow() const
{
TLOGD(WmsLogTag::WMS_FOCUS, "IsFocusedOnShow:%{public}d, id: %{public}d", focusedOnShow_, GetPersistentId());
return focusedOnShow_;
}
WSError Session::SetTouchable(bool touchable)
{
SetSystemTouchable(touchable);
if (!IsSessionValid()) {
TLOGW(WmsLogTag::WMS_MAIN, "Session is invalid, id: %{public}d state: %{public}u",
GetPersistentId(), GetSessionState());
return WSError::WS_ERROR_INVALID_SESSION;
}
if (touchable != GetSessionProperty()->GetTouchable()) {
TLOGI(WmsLogTag::WMS_EVENT, "id:%{public}d, %{public}d", GetPersistentId(), touchable);
}
UpdateSessionTouchable(touchable);
return WSError::WS_OK;
}
bool Session::GetTouchable() const
{
auto property = GetSessionProperty();
if (property) {
return property->GetTouchable();
}
TLOGE(WmsLogTag::WMS_EVENT, "property is null");
return true;
}
void Session::SetForceTouchable(bool forceTouchable)
{
if (forceTouchable != forceTouchable_) {
TLOGI(WmsLogTag::WMS_EVENT, "id:%{public}d, %{public}d", GetPersistentId(), forceTouchable);
}
forceTouchable_ = forceTouchable;
}
void Session::SetSystemTouchable(bool touchable)
{
if (touchable != systemTouchable_) {
TLOGNI(WmsLogTag::WMS_EVENT, "sysTouch:%{public}d, %{public}d", GetPersistentId(), touchable);
}
systemTouchable_ = touchable;
NotifySessionInfoChange();
}
bool Session::GetSystemTouchable() const
{
return forceTouchable_ && systemTouchable_ && GetTouchable();
}
bool Session::GetWindowTouchableForMMI(DisplayId displayId) const
{
bool isTouchable = true;
auto screenSession = ScreenSessionManagerClient::GetInstance().GetScreenSession(displayId);
if (screenSession != nullptr) {
if (!screenSession->IsTouchEnabled() || !GetSessionTouchable()) {
isTouchable = false;
}
}
return isTouchable;
}
bool Session::GetSessionTouchable() const
{
bool isTouchable = true;
if (!GetSystemTouchable() || !GetForegroundInteractiveStatus()) {
isTouchable = false;
}
return isTouchable;
}
bool Session::IsSystemActive() const
{
return isSystemActive_;
}
void Session::SetSystemActive(bool systemActive)
{
isSystemActive_ = systemActive;
NotifySessionInfoChange();
}
WSError Session::SetRSVisible(bool isVisible)
{
isRSVisible_ = isVisible;
return WSError::WS_OK;
}
bool Session::GetRSVisible() const
{
return isRSVisible_;
}
WSError Session::SetVisibilityState(WindowVisibilityState state)
{
visibilityState_ = state;
return WSError::WS_OK;
}
WindowVisibilityState Session::GetVisibilityState() const
{
return visibilityState_;
}
WSError Session::SetDrawingContentState(bool isRSDrawing)
{
isRSDrawing_ = isRSDrawing;
return WSError::WS_OK;
}
bool Session::GetDrawingContentState() const
{
return isRSDrawing_;
}
int32_t Session::GetWindowId() const
{
return GetPersistentId();
}
void Session::SetCallingPid(int32_t id)
{
TLOGI(WmsLogTag::WMS_EVENT, "id:%{public}d, %{public}d", persistentId_, id);
callingPid_ = id;
if (visibilityChangedDetectFunc_ && isVisible_.load()) {
visibilityChangedDetectFunc_(callingPid_, false, isVisible_.load());
}
}
void Session::SetCallingUid(int32_t id)
{
callingUid_ = id;
}
int32_t Session::GetCallingPid() const
{
return callingPid_;
}
int32_t Session::GetCallingUid() const
{
return callingUid_;
}
void Session::SetSceneLastUsedPosition(const std::string& position)
{
sceneLastUsedPosition_ = position;
}
const std::string Session::GetSceneLastUsedPosition() const
{
return sceneLastUsedPosition_;
}
void Session::SetAbilityToken(sptr<IRemoteObject> token)
{
abilityToken_ = token;
}
sptr<IRemoteObject> Session::GetAbilityToken() const
{
return abilityToken_;
}
WSError Session::UpdateBrightness(float brightness)
{
if (sessionStage_) {
sessionStage_->UpdateBrightness(brightness);
}
return WSError::WS_OK;
}
WSError Session::SetBrightness(float brightness)
{
auto property = GetSessionProperty();
if (!property) {
return WSError::WS_ERROR_NULLPTR;
}
property->SetBrightness(brightness);
return WSError::WS_OK;
}
float Session::GetBrightness() const
{
auto property = GetSessionProperty();
if (!property) {
return UNDEFINED_BRIGHTNESS;
}
return property->GetBrightness();
}
bool Session::IsSessionValid() const
{
if (sessionInfo_.isSystem_) {
WLOGFD("session is system, id: %{public}d, name: %{public}s, state: %{public}u",
GetPersistentId(), sessionInfo_.bundleName_.c_str(), GetSessionState());
return false;
}
bool res = state_ > SessionState::STATE_DISCONNECT && state_ < SessionState::STATE_END;
return res;
}
bool Session::IsActive() const
{
return isActive_;
}
bool Session::IsSystemSession() const
{
return sessionInfo_.isSystem_;
}
bool Session::IsTerminated() const
{
return (GetSessionState() == SessionState::STATE_DISCONNECT || isTerminating_);
}
bool Session::IsLifecycleForeground() const
{
return state_ == SessionState::STATE_FOREGROUND || state_ == SessionState::STATE_ACTIVE;
}
bool Session::IsSessionNotBackground() const
{
return state_ >= SessionState::STATE_DISCONNECT && state_ <= SessionState::STATE_ACTIVE;
}
WSRectF Session::UpdateTopBottomArea(const WSRectF& rect, MMI::WindowArea area)
{
const float innerBorder = INNER_BORDER_VP * vpr_;
const float outsideBorder = OUTSIDE_BORDER_VP * vpr_;
const float innerAngle = INNER_ANGLE_VP * vpr_;
const float horizontalBorderLength = outsideBorder + innerAngle;
const float verticalBorderLength = outsideBorder + innerBorder;
const size_t innerAngleCount = 2;
WSRectF tbRect;
tbRect.posX_ = rect.posX_ + horizontalBorderLength;
tbRect.width_ = rect.width_ - horizontalBorderLength * innerAngleCount;
tbRect.height_ = verticalBorderLength;
if (area == MMI::WindowArea::FOCUS_ON_TOP) {
tbRect.posY_ = rect.posY_;
} else if (area == MMI::WindowArea::FOCUS_ON_BOTTOM) {
tbRect.posY_ = rect.posY_ + rect.height_ - verticalBorderLength;
} else {
return WSRectF();
}
return tbRect;
}
WSRectF Session::UpdateLeftRightArea(const WSRectF& rect, MMI::WindowArea area)
{
const float innerBorder = INNER_BORDER_VP * vpr_;
const float outsideBorder = OUTSIDE_BORDER_VP * vpr_;
const float innerAngle = INNER_ANGLE_VP * vpr_;
const float verticalBorderLength = outsideBorder + innerAngle;
const float horizontalBorderLength = outsideBorder + innerBorder;
const size_t innerAngleCount = 2;
WSRectF lrRect;
lrRect.posY_ = rect.posY_ + verticalBorderLength;
lrRect.width_ = horizontalBorderLength;
lrRect.height_ = rect.height_ - verticalBorderLength * innerAngleCount;
if (area == MMI::WindowArea::FOCUS_ON_LEFT) {
lrRect.posX_ = rect.posX_;
} else if (area == MMI::WindowArea::FOCUS_ON_RIGHT) {
lrRect.posX_ = rect.posX_ + rect.width_ - horizontalBorderLength;
} else {
return WSRectF();
}
return lrRect;
}
WSRectF Session::UpdateInnerAngleArea(const WSRectF& rect, MMI::WindowArea area)
{
const float outsideBorder = OUTSIDE_BORDER_VP * vpr_;
const float innerAngle = INNER_ANGLE_VP * vpr_;
WSRectF iaRect;
iaRect.width_ = outsideBorder + innerAngle;
iaRect.height_ = outsideBorder + innerAngle;
if (area == MMI::WindowArea::FOCUS_ON_TOP_LEFT) {
iaRect.posX_ = rect.posX_;
iaRect.posY_ = rect.posY_;
} else if (area == MMI::WindowArea::FOCUS_ON_TOP_RIGHT) {
iaRect.posX_ = rect.posX_ + rect.width_ - iaRect.width_;
iaRect.posY_ = rect.posY_;
} else if (area == MMI::WindowArea::FOCUS_ON_BOTTOM_LEFT) {
iaRect.posX_ = rect.posX_;
iaRect.posY_ = rect.posY_ + rect.height_ - iaRect.height_;
} else if (area == MMI::WindowArea::FOCUS_ON_BOTTOM_RIGHT) {
iaRect.posX_ = rect.posX_ + rect.width_ - iaRect.width_;
iaRect.posY_ = rect.posY_ + rect.height_ - iaRect.height_;
} else {
return WSRectF();
}
return iaRect;
}
WSRectF Session::UpdateHotRect(const WSRect& rect)
{
WSRectF newRect;
const float outsideBorder = OUTSIDE_BORDER_VP * vpr_;
const size_t outsideBorderCount = 2;
newRect.posX_ = rect.posX_ - outsideBorder;
newRect.posY_ = rect.posY_ - outsideBorder;
newRect.width_ = rect.width_ + outsideBorder * outsideBorderCount;
newRect.height_ = rect.height_ + outsideBorder * outsideBorderCount;
return newRect;
}
void Session::UpdatePointerArea(const WSRect& rect)
{
if (preRect_ == rect) {
WLOGFD("The window area does not change");
return;
}
WSRectF hotRect = UpdateHotRect(rect);
for (const auto &[area, _] : windowAreas_) {
if (area == MMI::WindowArea::FOCUS_ON_TOP || area == MMI::WindowArea::FOCUS_ON_BOTTOM) {
windowAreas_[area] = UpdateTopBottomArea(hotRect, area);
} else if (area == MMI::WindowArea::FOCUS_ON_RIGHT || area == MMI::WindowArea::FOCUS_ON_LEFT) {
windowAreas_[area] = UpdateLeftRightArea(hotRect, area);
} else if (area == MMI::WindowArea::FOCUS_ON_TOP_LEFT || area == MMI::WindowArea::FOCUS_ON_TOP_RIGHT ||
area == MMI::WindowArea::FOCUS_ON_BOTTOM_LEFT || area == MMI::WindowArea::FOCUS_ON_BOTTOM_RIGHT) {
windowAreas_[area] = UpdateInnerAngleArea(hotRect, area);
}
}
preRect_ = rect;
}
WSError Session::UpdateSizeChangeReason(SizeChangeReason reason)
{
if (GetSizeChangeReason() == reason) {
return WSError::WS_DO_NOTHING;
}
GetLayoutController()->UpdateSizeChangeReason(reason);
return WSError::WS_OK;
}
bool Session::IsDraggingReason(SizeChangeReason reason) const
{
return reason == SizeChangeReason::DRAG || reason == SizeChangeReason::DRAG_MOVE ||
reason == SizeChangeReason::DRAG_START;
}
void Session::SetClientDisplayIdChangeListener(const NotifyClientDisplayIdChangeFunc& func)
{
clientDisplayIdChangeFunc_ = func;
}
WSError Session::UpdateClientDisplayId(DisplayId displayId)
{
if (sessionStage_ == nullptr) {
TLOGE(WmsLogTag::WMS_LAYOUT, "sessionStage_ is nullptr");
return WSError::WS_ERROR_NULLPTR;
}
TLOGI(WmsLogTag::WMS_LAYOUT, "windowId: %{public}d move display %{public}" PRIu64 " from %{public}" PRIu64,
GetPersistentId(), displayId, clientDisplayId_);
sessionStage_->UpdateDisplayId(displayId);
if (displayId != clientDisplayId_) {
AddPropertyDirtyFlags(static_cast<uint32_t>(SessionPropertyFlag::DISPLAY_ID));
NotifyDisplayIdChanged(GetPersistentId(), displayId);
}
clientDisplayId_ = displayId;
return WSError::WS_OK;
}
DisplayId Session::TransformGlobalRectToRelativeRect(WSRect& rect) const
{
const auto& [defaultDisplayRect, virtualDisplayRect, foldCreaseRect] =
PcFoldScreenManager::GetInstance().GetDisplayRects();
int32_t lowerScreenPosY = defaultDisplayRect.height_ + foldCreaseRect.height_;
TLOGI(WmsLogTag::WMS_LAYOUT, "lowerScreenPosY: %{public}d", lowerScreenPosY);
if (IsCompatibilityModeSubWin()) {
auto parentSession = GetParentSession();
if (parentSession) {
DisplayId parentClientDisplayId = parentSession->GetClientDisplayId();
if (parentClientDisplayId == VIRTUAL_DISPLAY_ID) {
rect.posY_ -= lowerScreenPosY;
}
return parentClientDisplayId;
}
}
auto screenHeight = defaultDisplayRect.height_ + foldCreaseRect.height_ + virtualDisplayRect.height_;
if (rect.posY_ > screenHeight) {
rect.posY_ -= lowerScreenPosY;
return clientDisplayId_;
}
DisplayId updatedDisplayId = DEFAULT_DISPLAY_ID;
if (rect.posY_ >= lowerScreenPosY) {
updatedDisplayId = VIRTUAL_DISPLAY_ID;
rect.posY_ -= lowerScreenPosY;
}
return updatedDisplayId;
}
bool Session::IsCompatibilityModeSubWin() const
{
if (!WindowHelper::IsSubWindow(GetWindowType())) {
return false;
}
auto parentSession = GetParentSession();
if (parentSession &&
parentSession->GetSessionProperty() &&
parentSession->GetSessionProperty()->IsAdaptToDragScale() &&
GetCallingPid() == parentSession->GetCallingPid()) {
return true;
}
return false;
}
void Session::UpdateClientRectPosYAndDisplayId(WSRect& rect)
{
if (GetSessionProperty()->IsSystemKeyboard()) {
TLOGI(WmsLogTag::WMS_LAYOUT, "skip update SystemKeyboard: %{public}d", GetPersistentId());
return;
}
if (WindowHelper::IsUIExtensionWindow(GetWindowType())) {
TLOGD(WmsLogTag::WMS_LAYOUT, "skip update UIExtension: %{public}d, rect: %{public}s",
GetPersistentId(), rect.ToString().c_str());
return;
}
if (rect.IsInvalid()) {
TLOGI(WmsLogTag::WMS_LAYOUT, "skip window: %{public}d invalid rect: %{public}s",
GetPersistentId(), rect.ToString().c_str());
return;
}
auto currScreenFoldStatus = PcFoldScreenManager::GetInstance().GetScreenFoldStatus();
if (currScreenFoldStatus == SuperFoldStatus::UNKNOWN || currScreenFoldStatus == SuperFoldStatus::FOLDED) {
TLOGD(WmsLogTag::WMS_LAYOUT, "Error status");
return;
}
if (GetScreenId() != DISPLAY_ID_INVALID &&
!PcFoldScreenManager::GetInstance().IsPcFoldScreen(GetScreenId())) {
TLOGI(WmsLogTag::WMS_LAYOUT, "winId: %{public}d, displayId: %{public}" PRIu64 " not need",
GetPersistentId(), GetScreenId());
return;
}
TLOGI(WmsLogTag::WMS_LAYOUT, "lastStatus: %{public}d, curStatus: %{public}d",
lastScreenFoldStatus_, currScreenFoldStatus);
if (currScreenFoldStatus == SuperFoldStatus::EXPANDED || currScreenFoldStatus == SuperFoldStatus::KEYBOARD) {
lastScreenFoldStatus_ = currScreenFoldStatus;
auto ret = UpdateClientDisplayId(DEFAULT_DISPLAY_ID);
TLOGI(WmsLogTag::WMS_LAYOUT, "JustUpdateId: winId: %{public}d, result: %{public}d",
GetPersistentId(), ret);
return;
}
WSRect lastRect = rect;
auto updatedDisplayId = TransformGlobalRectToRelativeRect(rect);
auto ret = UpdateClientDisplayId(updatedDisplayId);
lastScreenFoldStatus_ = currScreenFoldStatus;
configDisplayId_ = DISPLAY_ID_INVALID;
TLOGI(WmsLogTag::WMS_LAYOUT, "CalculatedRect: winId: %{public}d, input: %{public}s, output: %{public}s,"
" result: %{public}d, clientDisplayId: %{public}" PRIu64, GetPersistentId(), lastRect.ToString().c_str(),
rect.ToString().c_str(), ret, updatedDisplayId);
}
void Session::SetSingleHandTransform(const SingleHandTransform& transform)
{
singleHandTransform_ = transform;
}
SingleHandTransform Session::GetSingleHandTransform() const
{
return singleHandTransform_;
}
void Session::SetSingleHandModeFlag(bool flag)
{
singleHandModeFlag_ = flag;
}
bool Session::SessionIsSingleHandMode()
{
return singleHandModeFlag_;
}
WSError Session::UpdateRect(const WSRect& rect, SizeChangeReason reason,
const std::string& updateReason, const std::shared_ptr<RSTransaction>& rsTransaction)
{
return UpdateRectWithLayoutInfo(rect, reason, updateReason, rsTransaction, {});
}
void Session::IsNeedNotifySubSessionParentSizeChange(const WSRect& rect)
{
WSRect lastParentRect = GetLayoutController()->GetLastClientParentSize();
if (lastParentRect.width_ != rect.width_ || lastParentRect.height_ != rect.height_) {
Rect parentRect = { rect.posX_, rect.posY_, static_cast<uint32_t>(rect.width_),
static_cast<uint32_t>(rect.height_)};
NotifySubSessionParentSizeChange(parentRect);
}
}
WSError Session::UpdateRectWithLayoutInfo(const WSRect& rect, SizeChangeReason reason,
const std::string& updateReason, const std::shared_ptr<RSTransaction>& rsTransaction,
const std::map<AvoidAreaType, AvoidArea>& avoidAreas)
{
const auto persistentId = GetPersistentId();
TLOGD(WmsLogTag::WMS_LAYOUT, "session update rect: id: %{public}d, rect:%{public}s, "
"reason:%{public}u %{public}s", persistentId, rect.ToString().c_str(), reason, updateReason.c_str());
IsNeedNotifySubSessionParentSizeChange(rect);
GetLayoutController()->SetSessionRect(rect);
GetLayoutController()->SetLastClientParentSize(rect);
if (!IsSessionValid()) {
TLOGD(WmsLogTag::WMS_LAYOUT, "Session is invalid, id: %{public}d state: %{public}u",
persistentId, GetSessionState());
return WSError::WS_ERROR_INVALID_SESSION;
}
WSRect updateRect = IsNeedConvertToRelativeRect(reason) ?
GetLayoutController()->ConvertGlobalRectToRelative(rect, GetDisplayId()) : rect;
HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "id:[%d]rect[%d,%d,%d,%d]ConvertToRelativeRect[%d,%d,%d,%d]",
persistentId, rect.posX_, rect.posY_, rect.width_, rect.height_, updateRect.posX_, updateRect.posY_,
updateRect.width_, updateRect.height_);
auto globalDisplayRect = SessionCoordinateHelper::RelativeToGlobalDisplayRect(GetScreenId(), updateRect);
UpdateGlobalDisplayRect(globalDisplayRect, reason);
if (sessionStage_ != nullptr) {
UpdateClientRectPosYAndDisplayId(updateRect);
UpdateClientRectInfo(updateRect, reason, avoidAreas, rsTransaction);
SetClientRect(updateRect);
NotifyWindowStatusDidChangeIfNeedWhenUpdateRect(reason);
RectCheckProcess();
} else {
WLOGFE("sessionStage_ is nullptr");
}
UpdatePointerArea(GetSessionRect());
return WSError::WS_OK;
}
void Session::NotifyWindowStatusDidChangeIfNeedWhenUpdateRect(SizeChangeReason reason)
{
if (!sessionStage_) {
return;
}
if (reason == SizeChangeReason::MAXIMIZE || reason == SizeChangeReason::MAXIMIZE_IN_IMPLICT) {
sessionStage_->NotifyLayoutFinishAfterWindowModeChange(GetWindowMode());
}
}
WSError Session::UpdateDensity()
{
WLOGFI("session update density: id: %{public}d.", GetPersistentId());
if (!IsSessionValid()) {
TLOGW(WmsLogTag::WMS_MAIN, "Session is invalid, id: %{public}d state: %{public}u",
GetPersistentId(), GetSessionState());
return WSError::WS_ERROR_INVALID_SESSION;
}
if (sessionStage_ != nullptr) {
sessionStage_->UpdateDensity();
} else {
WLOGFE("Session::UpdateDensity sessionStage_ is nullptr");
return WSError::WS_ERROR_NULLPTR;
}
return WSError::WS_OK;
}
WSError Session::UpdateOrientation()
{
TLOGD(WmsLogTag::DMS, "update orientation: id: %{public}d.", GetPersistentId());
if (!IsSessionValid()) {
TLOGE(WmsLogTag::DMS, "update orientation failed because of session is invalid, id=%{public}d.",
GetPersistentId());
return WSError::WS_ERROR_INVALID_SESSION;
}
if (sessionStage_ == nullptr) {
TLOGE(WmsLogTag::DMS, "update orientation failed because of sessionStage_ is nullptr, id=%{public}d.",
GetPersistentId());
return WSError::WS_ERROR_NULLPTR;
}
return sessionStage_->UpdateOrientation();
}
RSSurfaceNodeType GetRSSurfaceNodeType(sptr<WindowSessionProperty> property)
{
RSSurfaceNodeType rsSurfaceNodeType = RSSurfaceNodeType::DEFAULT;
WindowType type = property->GetWindowType();
switch (type) {
case WindowType::WINDOW_TYPE_BOOT_ANIMATION:
case WindowType::WINDOW_TYPE_POINTER:
rsSurfaceNodeType = RSSurfaceNodeType::SELF_DRAWING_WINDOW_NODE;
break;
case WindowType::WINDOW_TYPE_APP_MAIN_WINDOW:
rsSurfaceNodeType = RSSurfaceNodeType::APP_WINDOW_NODE;
break;
case WindowType::WINDOW_TYPE_UI_EXTENSION:
TLOGD(WmsLogTag::WMS_UIEXT, "uiExtensionUsage=%{public}u", property->GetUIExtensionUsage());
if (SessionHelper::IsSecureUIExtension(property->GetUIExtensionUsage())) {
rsSurfaceNodeType = RSSurfaceNodeType::UI_EXTENSION_SECURE_NODE;
} else {
rsSurfaceNodeType = RSSurfaceNodeType::UI_EXTENSION_COMMON_NODE;
}
break;
case WindowType::WINDOW_TYPE_PIP:
rsSurfaceNodeType = RSSurfaceNodeType::APP_WINDOW_NODE;
break;
case WindowType::WINDOW_TYPE_MAGNIFICATION:
rsSurfaceNodeType = RSSurfaceNodeType::ABILITY_MAGNIFICATION_NODE;
break;
default:
rsSurfaceNodeType = RSSurfaceNodeType::DEFAULT;
break;
}
return rsSurfaceNodeType;
}
std::shared_ptr<RSSurfaceNode> Session::CreateSurfaceNode(uint64_t nodeId, sptr<WindowSessionProperty> property)
{
struct RSSurfaceNodeConfig rsSurfaceNodeConfig;
rsSurfaceNodeConfig.SurfaceNodeName = property->GetWindowName();
rsSurfaceNodeConfig.nodeId = nodeId;
RSSurfaceNodeType rsSurfaceNodeType = GetRSSurfaceNodeType(property);
auto surfaceNode = RSSurfaceNode::Create(rsSurfaceNodeConfig,
rsSurfaceNodeType, true, property_->IsConstrainedModal(), GetRSUIContext());
RSAdapterUtil::SetSkipCheckInMultiInstance(surfaceNode, true);
TLOGI(WmsLogTag::WMS_SCB, "Create RSSurfaceNode: %{public}s, name: %{public}s",
RSAdapterUtil::RSNodeToStr(surfaceNode).c_str(), property->GetWindowName().c_str());
return surfaceNode;
}
__attribute__((no_sanitize("cfi"))) WSError Session::ConnectInner(const sptr<ISessionStage>& sessionStage,
const sptr<IWindowEventChannel>& eventChannel, uint64_t nodeId, SystemSessionConfig& systemConfig,
sptr<IRemoteObject>& renderSession, std::shared_ptr<RSSurfaceNode>& surfaceNode,
sptr<WindowSessionProperty> property, sptr<IRemoteObject> token,
int32_t pid, int32_t uid, const std::string& identityToken)
{
if (property == nullptr) {
TLOGE(WmsLogTag::WMS_LIFE, "property is nullptr");
return WSError::WS_ERROR_NULLPTR;
}
TLOGI(WmsLogTag::WMS_LIFE, "[id: %{public}d] state: %{public}u,"
"isTerminating:%{public}d, callingPid:%{public}d, disableDelegator:%{public}d", GetPersistentId(),
static_cast<uint32_t>(GetSessionState()), isTerminating_, pid, property->GetIsAbilityHookOff());
if (GetSessionState() != SessionState::STATE_DISCONNECT && !isTerminating_ &&
!GetSessionInfo().reuseDelegatorWindow) {
TLOGE(WmsLogTag::WMS_LIFE, "state is not disconnect state:%{public}u id:%{public}u!, reuse %{public}d",
GetSessionState(), GetPersistentId(), GetSessionInfo().reuseDelegatorWindow);
return WSError::WS_ERROR_INVALID_SESSION;
}
if (sessionStage == nullptr || eventChannel == nullptr) {
TLOGE(WmsLogTag::WMS_LIFE, "session stage or eventChannel is nullptr");
return WSError::WS_ERROR_NULLPTR;
}
sessionStage_ = sessionStage;
sessionStage_->SetCurrentRotation(currentRotation_);
windowEventChannel_ = eventChannel;
surfaceNode = CreateSurfaceNode(nodeId, property);
SetSurfaceNode(surfaceNode);
abilityToken_ = token;
systemConfig = systemConfig_;
InitSessionPropertyWhenConnect(property);
SetCallingPid(pid);
callingUid_ = uid;
UpdateSessionState(SessionState::STATE_CONNECT);
const auto prelayoutContext = GetPrelayoutContext();
HandleInitialRect(prelayoutContext);
HandleHookDisplay(prelayoutContext);
EditSessionInfo().disableDelegator = property->GetIsAbilityHookOff();
NotifyConnect();
if (WindowHelper::IsSubWindow(GetWindowType()) && surfaceNode_ != nullptr) {
surfaceNode_->SetFrameGravity(Gravity::TOP_LEFT);
}
TLOGI(WmsLogTag::WMS_LIFE, "set session id %{public}d disableDelegator %{public}d", GetPersistentId(),
GetSessionInfo().disableDelegator);
return WSError::WS_OK;
}
void Session::InitSessionPropertyWhenConnect(const sptr<WindowSessionProperty>& property)
{
if (property == nullptr) {
return;
}
if (GetSessionProperty()->GetIsNeedUpdateWindowMode()) {
property->SetIsNeedUpdateWindowMode(true);
property->SetWindowModeInfo(GetSessionProperty()->GetWindowModeInfo());
}
if (SessionHelper::IsMainWindow(GetWindowType()) && GetSessionInfo().screenId_ != SCREEN_ID_INVALID) {
property->SetDisplayId(GetSessionInfo().screenId_);
}
if (systemConfig_.IsPcWindow() || systemConfig_.IsFreeMultiWindowMode()) {
InitSystemSessionDragEnable(property);
} else {
property->SetDragEnabled(false);
}
property->SetSessionPropertyChangeCallback(
[weakThis = wptr(this)]() {
auto session = weakThis.promote();
if (session == nullptr) {
TLOGNE(WmsLogTag::DEFAULT, "session is null");
return;
}
session->NotifySessionInfoChange();
});
WSRect winRect = GetSessionRect();
Rect rect = {winRect.posX_, winRect.posY_, static_cast<uint32_t>(winRect.width_),
static_cast<uint32_t>(winRect.height_)};
property->SetWindowRect(rect);
property->SetPersistentId(GetPersistentId());
property->SetAppIndex(GetSessionInfo().appIndex_);
property->SetFullScreenStart(GetSessionInfo().fullScreenStart_);
std::vector<AppExecFwk::SupportWindowMode> supportedWindowModes =
IsAnco() && GetSessionInfo().abilityInfo != nullptr ?
GetSessionInfo().abilityInfo->windowModes : GetSessionInfo().supportedWindowModes;
property->SetSupportedWindowModes(supportedWindowModes);
property->SetWindowSizeLimits(GetSessionInfo().windowSizeLimits);
auto windowCreateParams = GetSessionInfo().windowCreateParams;
bool isWindowLimitsForcible = windowCreateParams ? windowCreateParams->isWindowLimitsForcible : false;
property->SetIsWindowLimitsForcible(isWindowLimitsForcible);
property->SetIsAtomicService(GetSessionInfo().isAtomicService_);
property->SetRequestedOrientation(GetSessionProperty()->GetRequestedOrientation());
property->SetDefaultRequestedOrientation(GetSessionProperty()->GetDefaultRequestedOrientation());
property->SetUserRequestedOrientation(GetSessionProperty()->GetUserRequestedOrientation());
TLOGI(WmsLogTag::WMS_MAIN, "[id: %{public}d] requestedOrientation: %{public}u,"
" defaultRequestedOrientation: %{public}u,"
" userRequestedOrientation: %{public}u, isWindowLimitsForcible: %{public}d", GetPersistentId(),
static_cast<uint32_t>(GetSessionProperty()->GetRequestedOrientation()),
static_cast<uint32_t>(GetSessionProperty()->GetDefaultRequestedOrientation()),
static_cast<uint32_t>(GetSessionProperty()->GetUserRequestedOrientation()),
isWindowLimitsForcible);
property->SetCompatibleModeProperty(GetSessionProperty()->GetCompatibleModeProperty());
if (property->GetCompatibleModeProperty()) {
property->SetDragEnabled(!GetSessionProperty()->IsDragResizeDisabled());
}
if (property->IsAdaptToEventMapping()) {
std::vector<Rect> touchHotAreas;
GetSessionProperty()->GetTouchHotAreas(touchHotAreas);
property->SetTouchHotAreas(touchHotAreas);
}
property->SetIsAppSupportPhoneInPc(GetSessionProperty()->GetIsAppSupportPhoneInPc());
std::optional<bool> clientDragEnable = GetClientDragEnable();
if (clientDragEnable.has_value()) {
property->SetDragEnabled(clientDragEnable.value());
}
if (SessionHelper::IsMainWindow(GetWindowType())) {
property->SetIsPcAppInPad(GetSessionProperty()->GetIsPcAppInPad());
property->SetForceSplitEnable(GetSessionProperty()->GetForceSplitEnable());
property->SetHookWindowInfo(GetSessionProperty()->GetHookWindowInfo());
}
property->SetSkipSelfWhenShowOnVirtualScreen(GetSessionProperty()->GetSkipSelfWhenShowOnVirtualScreen());
property->SetSkipEventOnCastPlus(GetSessionProperty()->GetSkipEventOnCastPlus());
property->SetIsAbilityHook(GetSessionInfo().isAbilityHook_);
property->SetPcAppInpadCompatibleMode(GetSessionProperty()->GetPcAppInpadCompatibleMode());
property->SetPcAppInpadSpecificSystemBarInvisible(GetSessionProperty()->GetPcAppInpadSpecificSystemBarInvisible());
property->SetPcAppInpadOrientationLandscape(GetSessionProperty()->GetPcAppInpadOrientationLandscape());
property->SetMobileAppInPadLayoutFullScreen(GetSessionProperty()->GetMobileAppInPadLayoutFullScreen());
if (!property_->GetIsNeedUpdateShowDecor()) {
const bool isPcMode = system::GetBoolParameter("persist.sceneboard.ispcmode", false);
const bool isShow = !(isScreenLockedCallback_ && isScreenLockedCallback_() &&
systemConfig_.freeMultiWindowSupport_ && !isPcMode);
property->SetIsShowDecorInFreeMultiWindow(isShow);
} else {
property->SetIsShowDecorInFreeMultiWindow(property_->GetIsShowDecorInFreeMultiWindow());
property_->SetIsNeedUpdateShowDecor(false);
}
SetSessionProperty(property);
GetSessionProperty()->SetIsNeedUpdateWindowMode(false);
DisplayId screenId = GetSessionProperty()->GetDisplayId();
if (screenId == DEFAULT_DISPLAY_ID && PcFoldScreenManager::GetInstance().IsHalfFolded(screenId)) {
property->SetDisplayId(GetClientDisplayId());
}
TLOGI(WmsLogTag::WMS_ATTRIBUTE,
"win=[%{public}d, %{public}s], screenId=%{public}" PRIu64 ", clientScreenId=%{public}" PRIu64,
GetWindowId(), GetWindowName().c_str(), screenId, property->GetDisplayId());
}
void Session::InitSystemSessionDragEnable(const sptr<WindowSessionProperty>& property)
{
auto defaultDragEnable = false;
auto isSystemWindow = WindowHelper::IsSystemWindow(property->GetWindowType());
bool isDialog = WindowHelper::IsDialogWindow(property->GetWindowType());
bool isSystemCalling = property->GetSystemCalling();
TLOGI(WmsLogTag::WMS_LAYOUT, "windId: %{public}d, defaultDragEnable: %{public}d, isSystemWindow: %{public}d, "
"isDialog: %{public}d, isSystemCalling: %{public}d", GetPersistentId(), defaultDragEnable,
isSystemWindow, isDialog, isSystemCalling);
if (isSystemWindow && !isDialog && !isSystemCalling) {
property->SetDragEnabled(defaultDragEnable);
}
}
WSError Session::Reconnect(const sptr<ISessionStage>& sessionStage, const sptr<IWindowEventChannel>& eventChannel,
const std::shared_ptr<RSSurfaceNode>& surfaceNode, sptr<WindowSessionProperty> property, sptr<IRemoteObject> token,
int32_t pid, int32_t uid)
{
if (property == nullptr) {
TLOGE(WmsLogTag::WMS_RECOVER, "property is nullptr");
return WSError::WS_ERROR_NULLPTR;
}
TLOGI(WmsLogTag::WMS_RECOVER, "id:%{public}d, state:%{public}u, pid:%{public}d, disableDelegator:%{public}d",
property->GetPersistentId(), static_cast<uint32_t>(property->GetWindowState()), pid,
property->GetIsAbilityHookOff());
if (sessionStage == nullptr || eventChannel == nullptr) {
TLOGE(WmsLogTag::WMS_RECOVER, "session stage or eventChannel is nullptr");
return WSError::WS_ERROR_NULLPTR;
}
sessionStage_ = sessionStage;
SetSurfaceNode(surfaceNode);
windowEventChannel_ = eventChannel;
abilityToken_ = token;
SetSessionPropertyForReconnect(property);
persistentId_ = property->GetPersistentId();
SetCallingPid(pid);
callingUid_ = uid;
bufferAvailable_ = true;
auto windowRect = property->GetWindowRect();
layoutRect_ = { windowRect.posX_, windowRect.posY_,
static_cast<int32_t>(windowRect.width_), static_cast<int32_t>(windowRect.height_) };
UpdateSessionState(SessionState::STATE_CONNECT);
EditSessionInfo().disableDelegator = property->GetIsAbilityHookOff();
for (const auto& [transitionType, animation] : property->GetTransitionAnimationConfig()) {
property_->SetTransitionAnimationConfig(transitionType, *animation);
}
return WSError::WS_OK;
}
WSError Session::Foreground(sptr<WindowSessionProperty> property, bool isFromClient, const std::string& identityToken)
{
HandleDialogForeground();
SessionState state = GetSessionState();
TLOGI(WmsLogTag::WMS_LIFE, "[id: %{public}d] state:%{public}u, isTerminating:%{public}d",
GetPersistentId(), static_cast<uint32_t>(state), isTerminating_);
if ((state == SessionState::STATE_DISCONNECT || state == SessionState::STATE_END) &&
SessionHelper::IsMainWindow(GetWindowType())) {
TLOGE(WmsLogTag::WMS_LIFE, "Main window foreground error! state:%{public}u", state);
RecordLifecycleSessionStateError(SessionState::STATE_FOREGROUND, state);
}
if (state != SessionState::STATE_CONNECT && state != SessionState::STATE_BACKGROUND &&
state != SessionState::STATE_INACTIVE) {
TLOGE(WmsLogTag::WMS_LIFE, "Foreground state invalid! state:%{public}u", state);
SetNeedBackgroundAfterConnect(false);
return WSError::WS_ERROR_INVALID_SESSION;
}
NotifyCrossProcessChildrenLifecycle(ParentLifeCycleEvent::FOREGROUND);
UpdateSessionState(SessionState::STATE_FOREGROUND);
if (!isActive_ || GetSessionInfo().reuseDelegatorWindow) {
SetActive(true);
}
isStarting_ = false;
NotifyForeground();
isTerminating_ = false;
PostSpecificSessionLifeCycleTimeoutTask(ATTACH_EVENT_NAME);
NotifyClientToUpdateGlobalDisplayRect(GetGlobalDisplayRect(), SizeChangeReason::UNDEFINED);
return WSError::WS_OK;
}
void Session::HandleDialogBackground()
{
const auto& type = GetWindowType();
if (type < WindowType::APP_MAIN_WINDOW_BASE || type >= WindowType::APP_MAIN_WINDOW_END) {
TLOGD(WmsLogTag::WMS_DIALOG, "Current session is not main window, id: %{public}d, type: %{public}d",
GetPersistentId(), type);
return;
}
auto dialogVec = GetDialogVector();
for (const auto& dialog : dialogVec) {
if (dialog == nullptr) {
continue;
}
TLOGI(WmsLogTag::WMS_DIALOG, "Background dialog, id: %{public}d, dialogId: %{public}d",
GetPersistentId(), dialog->GetPersistentId());
if (!dialog->sessionStage_) {
TLOGE(WmsLogTag::WMS_DIALOG, "dialog session stage is nullptr");
return;
}
dialog->sessionStage_->NotifyDialogStateChange(false);
}
}
void Session::HandleDialogForeground()
{
const auto& type = GetWindowType();
if (type < WindowType::APP_MAIN_WINDOW_BASE || type >= WindowType::APP_MAIN_WINDOW_END) {
TLOGD(WmsLogTag::WMS_DIALOG, "Current session is not main window, id: %{public}d, type: %{public}d",
GetPersistentId(), type);
return;
}
auto dialogVec = GetDialogVector();
for (const auto& dialog : dialogVec) {
if (dialog == nullptr) {
continue;
}
TLOGI(WmsLogTag::WMS_DIALOG, "Foreground dialog, id: %{public}d, dialogId: %{public}d",
GetPersistentId(), dialog->GetPersistentId());
if (!dialog->sessionStage_) {
TLOGE(WmsLogTag::WMS_DIALOG, "dialog session stage is nullptr");
return;
}
dialog->sessionStage_->NotifyDialogStateChange(true);
}
}
WSError Session::Background(bool isFromClient, const std::string& identityToken, bool isFromInnerkits)
{
HandleDialogBackground();
NotifySubSessionParentStatusChange(GetWindowMode());
SessionState state = GetSessionState();
TLOGI(WmsLogTag::WMS_LIFE, "[id: %{public}d] Background session, state: %{public}" PRIu32, GetPersistentId(),
static_cast<uint32_t>(state));
if (state == SessionState::STATE_ACTIVE && GetWindowType() == WindowType::WINDOW_TYPE_APP_MAIN_WINDOW) {
UpdateSessionState(SessionState::STATE_INACTIVE);
state = SessionState::STATE_INACTIVE;
isActive_ = false;
}
isStarting_ = false;
if (state != SessionState::STATE_INACTIVE) {
TLOGW(WmsLogTag::WMS_LIFE, "[id: %{public}d] Background state invalid! state: %{public}u",
GetPersistentId(), state);
if (state == SessionState::STATE_DISCONNECT && systemConfig_.IsPcWindow()) {
SetNeedBackgroundAfterConnect(true);
}
return WSError::WS_ERROR_INVALID_SESSION;
}
UpdateSessionState(SessionState::STATE_BACKGROUND);
SetIsPendingToBackgroundState(false);
NotifyBackground();
PostSpecificSessionLifeCycleTimeoutTask(DETACH_EVENT_NAME);
return WSError::WS_OK;
}
void Session::ResetSessionConnectState()
{
TLOGI(WmsLogTag::WMS_LIFE, "[id: %{public}d] state: %{public}u",
GetPersistentId(), GetSessionState());
SetSessionState(SessionState::STATE_DISCONNECT);
SetCallingPid(-1);
}
void Session::ResetIsActive()
{
TLOGI(WmsLogTag::WMS_LIFE, "[id: %{public}d] isActive: %{public}u",
GetPersistentId(), IsActive());
isActive_ = false;
}
WSError Session::Disconnect(bool isFromClient, const std::string& identityToken, bool isFromInnerkits)
{
auto state = GetSessionState();
TLOGI(WmsLogTag::WMS_LIFE, "[id: %{public}d] Disconnect session, state: %{public}u", GetPersistentId(), state);
isActive_ = false;
isStarting_ = false;
bufferAvailable_ = false;
isNeedSyncSessionRect_ = true;
isAlreadyDisconnect_ = true;
if (mainHandler_ && !IsSystemSession()) {
std::shared_ptr<RSSurfaceNode> surfaceNode;
std::shared_ptr<RSSurfaceNode> shadowSurfaceNode;
{
std::lock_guard<std::mutex> lock(surfaceNodeMutex_);
surfaceNode_.swap(surfaceNode);
shadowSurfaceNode.swap(shadowSurfaceNode_);
}
mainHandler_->PostTask([surfaceNode = std::move(surfaceNode),
shadowSurfaceNode = std::move(shadowSurfaceNode)]() mutable {
surfaceNode.reset();
shadowSurfaceNode.reset();
});
}
UpdateSessionState(SessionState::STATE_BACKGROUND);
UpdateSessionState(SessionState::STATE_DISCONNECT);
NotifyDisconnect();
if (visibilityChangedDetectFunc_) {
visibilityChangedDetectFunc_(GetCallingPid(), isVisible_.load(), false);
}
OutlineStyleParams defaultParams;
UpdateSessionOutline(false, defaultParams);
return WSError::WS_OK;
}
WSError Session::Show(sptr<WindowSessionProperty> property)
{
TLOGD(WmsLogTag::WMS_LIFE, "Show session, id: %{public}d", GetPersistentId());
return WSError::WS_OK;
}
WSError Session::Hide()
{
TLOGD(WmsLogTag::WMS_LIFE, "Hide session, id: %{public}d", GetPersistentId());
return WSError::WS_OK;
}
WSError Session::DrawingCompleted()
{
TLOGI(WmsLogTag::WMS_LIFE, "id: %{public}d", GetPersistentId());
if (!SessionPermission::IsSystemAppCall()) {
TLOGE(WmsLogTag::WMS_LIFE, "permission denied!");
return WSError::WS_ERROR_INVALID_PERMISSION;
}
auto lifecycleListeners = GetListeners<ILifecycleListener>();
for (auto& listener : lifecycleListeners) {
if (auto listenerPtr = listener.lock()) {
listenerPtr->OnDrawingCompleted();
}
}
return WSError::WS_OK;
}
WSError Session::RemoveStartingWindow()
{
auto lifecycleListeners = GetListeners<ILifecycleListener>();
for (auto& listener : lifecycleListeners) {
if (auto listenerPtr = listener.lock()) {
listenerPtr->OnAppRemoveStartingWindow();
}
}
return WSError::WS_OK;
}
WSError Session::SetActive(bool active)
{
SessionState state = GetSessionState();
TLOGI(WmsLogTag::WMS_LIFE, "new active:%{public}d, id:%{public}d, state:%{public}u",
active, GetPersistentId(), static_cast<uint32_t>(state));
if (!IsSessionValid()) {
TLOGW(WmsLogTag::WMS_LIFE, "Session is invalid, id: %{public}d state: %{public}u",
GetPersistentId(), GetSessionState());
return WSError::WS_ERROR_INVALID_SESSION;
}
if (active == isActive_ && !GetSessionInfo().reuseDelegatorWindow) {
TLOGD(WmsLogTag::WMS_LIFE, "Session active do not change: [%{public}d]", active);
return WSError::WS_DO_NOTHING;
}
if (!sessionStage_) {
TLOGE(WmsLogTag::WMS_LIFE, "session stage is nullptr");
return WSError::WS_ERROR_NULLPTR;
}
if (active && GetSessionState() == SessionState::STATE_FOREGROUND) {
sessionStage_->SetActive(true);
UpdateSessionState(SessionState::STATE_ACTIVE);
isActive_ = active;
}
if (!active && GetSessionState() == SessionState::STATE_ACTIVE) {
sessionStage_->SetActive(false);
UpdateSessionState(SessionState::STATE_INACTIVE);
isActive_ = active;
}
return WSError::WS_OK;
}
void Session::ProcessClickModalWindowOutside(int32_t posX, int32_t posY)
{
if (clickModalWindowOutsideFunc_ && !GetSessionRect().IsInRegion(posX, posY)) {
clickModalWindowOutsideFunc_();
}
}
void Session::SetClickModalWindowOutsideListener(NotifyClickModalWindowOutsideFunc&& func)
{
const char* const where = __func__;
PostTask([weakThis = wptr(this), func = std::move(func), where] {
auto session = weakThis.promote();
if (!session || !func) {
TLOGNE(WmsLogTag::WMS_LIFE, "%{public}s session or func is null", where);
return;
}
session->clickModalWindowOutsideFunc_ = std::move(func);
TLOGNI(WmsLogTag::WMS_DIALOG, "%{public}s id: %{public}d", where, session->GetPersistentId());
}, __func__);
}
void Session::SetClientDragEnable(bool dragEnable)
{
clientDragEnable_ = dragEnable;
}
std::optional<bool> Session::GetClientDragEnable() const
{
return clientDragEnable_;
}
void Session::SetDragActivated(DragActivateSource source, bool activated)
{
uint32_t bit = static_cast<uint32_t>(source);
if (activated) {
dragActivatedBitmap_ |= bit;
} else {
dragActivatedBitmap_ &= ~bit;
}
}
bool Session::IsDragAccessible() const
{
bool isDragEnabled = GetSessionProperty()->GetDragEnabled();
bool isDragActivated = (dragActivatedBitmap_ & DRAG_ACTIVATE_ALL_MASK) == DRAG_ACTIVATE_ALL_MASK;
TLOGD(WmsLogTag::WMS_LAYOUT, "PersistentId: %{public}d, dragEnabled: %{public}d, dragActivate: %{public}d",
GetPersistentId(), isDragEnabled, isDragActivated);
return isDragEnabled && isDragActivated;
}
bool Session::IsScreenLockWindow() const
{
return isScreenLockWindow_;
}
void Session::NotifyForegroundInteractiveStatus(bool interactive)
{
SetForegroundInteractiveStatus(interactive);
}
void Session::SetForegroundInteractiveStatus(bool interactive)
{
if (interactive != GetForegroundInteractiveStatus()) {
TLOGI(WmsLogTag::WMS_EVENT, "id:%{public}d, %{public}d", GetPersistentId(),
static_cast<int>(interactive));
}
foregroundInteractiveStatus_.store(interactive);
if (Session::IsScbCoreEnabled()) {
return;
}
NotifySessionInfoChange();
}
bool Session::GetForegroundInteractiveStatus() const
{
return foregroundInteractiveStatus_.load();
}
bool Session::IsActivatedAfterScreenLocked() const
{
return isActivatedAfterScreenLocked_.load();
}
void Session::SetIsActivatedAfterScreenLocked(bool isActivatedAfterScreenLocked)
{
TLOGI(WmsLogTag::WMS_LIFE, "id:%{public}d, isLocked:%{public}d",
GetPersistentId(), isActivatedAfterScreenLocked);
isActivatedAfterScreenLocked_.store(isActivatedAfterScreenLocked);
}
bool Session::GetIsPendingToBackgroundState() const
{
return isPendingToBackgroundState_.load();
}
void Session::SetIsPendingToBackgroundState(bool isPendingToBackgroundState)
{
TLOGI(WmsLogTag::WMS_LIFE, "id:%{public}d State:%{public}d",
GetPersistentId(), isPendingToBackgroundState);
return isPendingToBackgroundState_.store(isPendingToBackgroundState);
}
bool Session::IsNeedNotifyAttachState(bool isAttach)
{
if (WindowHelper::IsMainWindow(GetWindowType()) && (showRecent_ || isAttach == isClientAttach_)) {
TLOGI(WmsLogTag::WMS_LIFE, "No need notifyWindowAttachStateChange, persistentId:%{public}d",
GetPersistentId());
return false;
}
if (WindowHelper::IsSubWindow(GetWindowType())) {
auto mainSession = GetMainSession();
if ((mainSession && mainSession->GetShowRecent()) || isAttach == isClientAttach_) {
TLOGI(WmsLogTag::WMS_LIFE, "No need notifyWindowAttachStateChange, persistentId:%{public}d",
GetPersistentId());
return false;
}
}
return true;
}
void Session::SetAttachState(bool isAttach, WindowMode windowMode)
{
isAttach_ = isAttach;
if (handler_ && IsNeedReportTimeout()) {
handler_->RemoveTask(isAttach_ ? ATTACH_EVENT_NAME : DETACH_EVENT_NAME);
}
PostTask([weakThis = wptr(this), isAttach]() {
auto session = weakThis.promote();
if (session == nullptr) {
TLOGD(WmsLogTag::WMS_LIFE, "session is null");
return;
}
if (WindowHelper::IsNeedWaitAttachStateWindow(session->GetWindowType()) &&
session->IsNeedNotifyAttachState(isAttach)) {
session->isClientAttach_ = isAttach;
TLOGI(WmsLogTag::WMS_LIFE, "NotifyWindowAttachStateChange, persistentId:%{public}d",
session->GetPersistentId());
if (session->sessionStage_) {
session->sessionStage_->NotifyWindowAttachStateChange(isAttach);
}
}
TLOGD(WmsLogTag::WMS_LIFE, "isAttach:%{public}d persistentId:%{public}d", isAttach,
session->GetPersistentId());
if (!isAttach && session->detachCallback_ != nullptr) {
TLOGNI(WmsLogTag::WMS_LIFE, "Session detach, persistentId:%{public}d", session->GetPersistentId());
session->detachCallback_->OnPatternDetach(session->GetPersistentId());
session->detachCallback_ = nullptr;
}
}, "SetAttachState");
CreateDetectStateTask(isAttach, windowMode);
}
void Session::CreateDetectStateTask(bool isAttach, WindowMode windowMode)
{
if (!IsSupportDetectWindow(isAttach)) {
return;
}
if (showRecent_) {
return;
}
if (!ShouldCreateDetectTask(isAttach, windowMode)) {
RemoveWindowDetectTask();
DetectTaskInfo detectTaskInfo;
SetDetectTaskInfo(detectTaskInfo);
return;
}
CreateWindowStateDetectTask(isAttach, windowMode);
}
void Session::RegisterDetachCallback(const sptr<IPatternDetachCallback>& callback)
{
detachCallback_ = callback;
if (!isAttach_ && detachCallback_ != nullptr) {
TLOGI(WmsLogTag::WMS_LIFE, "Session detach before register, persistentId:%{public}d", GetPersistentId());
detachCallback_->OnPatternDetach(GetPersistentId());
detachCallback_ = nullptr;
}
}
void Session::SetChangeSessionVisibilityWithStatusBarEventListener(
NotifyChangeSessionVisibilityWithStatusBarFunc&& func)
{
PostTask([weakThis = wptr(this), func = std::move(func), where = __func__] {
auto session = weakThis.promote();
if (!session || !func) {
TLOGNE(WmsLogTag::WMS_LIFE, "%{public}s session is nullptr", where);
return;
}
session->changeSessionVisibilityWithStatusBarFunc_ = std::move(func);
}, __func__);
}
void Session::SetPendingSessionActivationEventListener(NotifyPendingSessionActivationFunc&& func)
{
const char* const where = __func__;
PostTask([weakThis = wptr(this), func = std::move(func), where] {
auto session = weakThis.promote();
if (!session) {
TLOGNE(WmsLogTag::WMS_LIFE, "%{public}s session is nullptr", where);
return;
}
session->pendingSessionActivationFunc_ = std::move(func);
}, where);
}
void Session::SetBatchPendingSessionsActivationEventListener(NotifyBatchPendingSessionsActivationFunc&& func)
{
const char* const where = __func__;
PostTask([weakThis = wptr(this), func = std::move(func), where] {
auto session = weakThis.promote();
if (!session) {
TLOGNE(WmsLogTag::WMS_LIFE, "%{public}s session is nullptr", where);
return;
}
session->batchPendingSessionsActivationFunc_ = std::move(func);
}, where);
}
void Session::SetBackPressedListenser(NotifyBackPressedFunc&& func)
{
const char* const where = __func__;
PostTask([weakThis = wptr(this), func = std::move(func), where] {
auto session = weakThis.promote();
if (!session) {
TLOGNE(WmsLogTag::WMS_LIFE, "%{public}s session is nullptr", where);
return;
}
session->backPressedFunc_ = std::move(func);
}, where);
}
void Session::SetTerminateSessionListener(NotifyTerminateSessionFunc&& func)
{
const char* const where = __func__;
PostTask([weakThis = wptr(this), func = std::move(func), where] {
auto session = weakThis.promote();
if (!session) {
TLOGNE(WmsLogTag::WMS_LIFE, "%{public}s session is nullptr", where);
return;
}
session->terminateSessionFunc_ = std::move(func);
}, where);
}
void Session::SetRestartAppListener(NotifyRestartAppFunc&& func)
{
const char* const where = __func__;
PostTask([weakThis = wptr(this), func = std::move(func), where] {
auto session = weakThis.promote();
if (!session) {
TLOGE(WmsLogTag::WMS_LIFE, "%{public}s session is nullptr", where);
return;
}
session->restartAppFunc_ = std::move(func);
}, where);
}
void Session::RemoveLifeCycleTask(const LifeCycleTaskType& taskType)
{
sptr<SessionLifeCycleTask> frontLifeCycleTask = nullptr;
{
std::lock_guard<std::mutex> lock(lifeCycleTaskQueueMutex_);
if (lifeCycleTaskQueue_.empty()) {
return;
}
sptr<SessionLifeCycleTask> currLifeCycleTask = lifeCycleTaskQueue_.front();
if (currLifeCycleTask->type != taskType) {
TLOGW(WmsLogTag::WMS_LIFE,
"not match, current running taskName=%{public}s, PersistentId=%{public}d",
currLifeCycleTask->name.c_str(), persistentId_);
return;
}
TLOGI(WmsLogTag::WMS_LIFE, "Removed lifeCyleTask %{public}s. PersistentId=%{public}d",
currLifeCycleTask->name.c_str(), persistentId_);
lifeCycleTaskQueue_.pop_front();
if (lifeCycleTaskQueue_.empty()) {
return;
}
frontLifeCycleTask = lifeCycleTaskQueue_.front();
SetLifeCycleTaskRunning(frontLifeCycleTask);
}
PostTask(std::move(frontLifeCycleTask->task), frontLifeCycleTask->name);
}
void Session::ClearLifeCycleTask()
{
TLOGI(WmsLogTag::WMS_LIFE, "Clear LifeCycleTask, PersistentId=%{public}d", persistentId_);
std::lock_guard<std::mutex> lock(lifeCycleTaskQueueMutex_);
lifeCycleTaskQueue_.clear();
}
sptr<Session::SessionLifeCycleTask> Session::GetLastLifeCycleTask() const
{
std::lock_guard<std::mutex> lock(lifeCycleTaskQueueMutex_);
if (lifeCycleTaskQueue_.empty()) {
return nullptr;
}
return lifeCycleTaskQueue_.back();
}
void Session::PostLifeCycleTask(Task&& task, const std::string& name, const LifeCycleTaskType& taskType)
{
sptr<SessionLifeCycleTask> frontLifeCycleTask = nullptr;
{
std::lock_guard<std::mutex> lock(lifeCycleTaskQueueMutex_);
if (!lifeCycleTaskQueue_.empty()) {
sptr<SessionLifeCycleTask> currLifeCycleTask = lifeCycleTaskQueue_.front();
std::chrono::steady_clock::time_point currentTime = std::chrono::steady_clock::now();
bool isCurrentTaskExpired =
std::chrono::duration_cast<std::chrono::milliseconds>(currentTime - currLifeCycleTask->startTime)
.count() > LIFE_CYCLE_TASK_EXPIRED_TIME_LIMIT;
if (isCurrentTaskExpired) {
TLOGE(WmsLogTag::WMS_LIFE, "Remove expired LifeCycleTask %{public}s. PersistentId=%{public}d",
currLifeCycleTask->name.c_str(), persistentId_);
lifeCycleTaskQueue_.pop_front();
}
}
if (lifeCycleTaskQueue_.size() == MAX_LIFE_CYCLE_TASK_IN_QUEUE) {
TLOGE(WmsLogTag::WMS_LIFE, "Failed to add task %{public}s to life cycle queue", name.c_str());
return;
}
sptr<SessionLifeCycleTask> lifeCycleTask =
sptr<SessionLifeCycleTask>::MakeSptr(std::move(task), name, taskType);
lifeCycleTaskQueue_.push_back(lifeCycleTask);
TLOGI(WmsLogTag::WMS_LIFE, "Add task %{public}s to life cycle queue, PersistentId=%{public}d",
name.c_str(), persistentId_);
frontLifeCycleTask = lifeCycleTaskQueue_.front();
if (!SetLifeCycleTaskRunning(frontLifeCycleTask)) {
return;
}
}
PostTask(std::move(frontLifeCycleTask->task), frontLifeCycleTask->name);
}
bool Session::SetLifeCycleTaskRunning(const sptr<SessionLifeCycleTask>& lifeCycleTask)
{
if (lifeCycleTask == nullptr || lifeCycleTask->running) {
TLOGW(WmsLogTag::WMS_LIFE, "LifeCycleTask is running or null. PersistentId: %{public}d", persistentId_);
return false;
}
TLOGI(WmsLogTag::WMS_LIFE, "Execute LifeCycleTask %{public}s. PersistentId: %{public}d",
lifeCycleTask->name.c_str(), persistentId_);
lifeCycleTask->running = true;
lifeCycleTask->startTime = std::chrono::steady_clock::now();
return true;
}
WSError Session::TerminateSessionNew(
const sptr<AAFwk::SessionInfo> abilitySessionInfo, bool needStartCaller, bool isFromBroker)
{
if (abilitySessionInfo == nullptr) {
TLOGE(WmsLogTag::WMS_LIFE, "abilitySessionInfo is null");
return WSError::WS_ERROR_INVALID_SESSION;
}
const char* const where = __func__;
auto task = [weakThis = wptr(this), abilitySessionInfo, needStartCaller, isFromBroker, where]() {
auto session = weakThis.promote();
if (!session) {
TLOGNE(WmsLogTag::WMS_LIFE, "%{public}s session is nullptr", where);
return;
}
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<int32_t>(abilitySessionInfo->persistentId);
{
std::lock_guard<std::recursive_mutex> lock(session->sessionInfoMutex_);
session->sessionInfo_.closeAbilityWant = std::make_shared<AAFwk::Want>(abilitySessionInfo->want);
session->sessionInfo_.resultCode = abilitySessionInfo->resultCode;
}
if (session->terminateSessionFuncNew_) {
session->terminateSessionFuncNew_(info, needStartCaller, isFromBroker, false);
}
TLOGNI(WmsLogTag::WMS_LIFE,
"%{public}s, id: %{public}d, needStartCaller: %{public}d, isFromBroker: %{public}d",
where, session->GetPersistentId(), needStartCaller, isFromBroker);
};
PostLifeCycleTask(task, "TerminateSessionNew", LifeCycleTaskType::STOP);
return WSError::WS_OK;
}
void Session::SetTerminateSessionListenerNew(NotifyTerminateSessionFuncNew&& func)
{
const char* const where = __func__;
PostTask([weakThis = wptr(this), func = std::move(func), where] {
auto session = weakThis.promote();
if (!session) {
TLOGNE(WmsLogTag::WMS_LIFE, "%{public}s session is nullptr", where);
return;
}
session->terminateSessionFuncNew_ = std::move(func);
}, where);
}
WSError Session::TerminateSessionTotal(const sptr<AAFwk::SessionInfo> abilitySessionInfo, TerminateType terminateType)
{
if (abilitySessionInfo == nullptr) {
TLOGE(WmsLogTag::WMS_LIFE, "abilitySessionInfo is null");
return WSError::WS_ERROR_INVALID_SESSION;
}
if (isTerminating_) {
TLOGE(WmsLogTag::WMS_LIFE, "is terminating, return!");
return WSError::WS_ERROR_INVALID_OPERATION;
}
isTerminating_ = true;
SessionInfo info;
info.abilityName_ = abilitySessionInfo->want.GetElement().GetAbilityName();
info.bundleName_ = abilitySessionInfo->want.GetElement().GetBundleName();
info.callerToken_ = abilitySessionInfo->callerToken;
info.persistentId_ = static_cast<int32_t>(abilitySessionInfo->persistentId);
{
std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
sessionInfo_.closeAbilityWant = std::make_shared<AAFwk::Want>(abilitySessionInfo->want);
sessionInfo_.resultCode = abilitySessionInfo->resultCode;
}
if (terminateSessionFuncTotal_) {
terminateSessionFuncTotal_(info, terminateType);
}
return WSError::WS_OK;
}
void Session::SetTerminateSessionListenerTotal(NotifyTerminateSessionFuncTotal&& func)
{
const char* const where = __func__;
PostTask([weakThis = wptr(this), func = std::move(func), where] {
auto session = weakThis.promote();
if (!session) {
TLOGNE(WmsLogTag::WMS_LIFE, "%{public}s session is nullptr", where);
return;
}
session->terminateSessionFuncTotal_ = std::move(func);
}, where);
}
WSError Session::SetSessionLabel(const std::string& label)
{
WLOGFI("run Session::SetSessionLabel");
if (updateSessionLabelFunc_) {
updateSessionLabelFunc_(label);
}
label_ = label;
return WSError::WS_OK;
}
void Session::UpdateSessionLabel(const std::string& label)
{
const char* const where = __func__;
PostTask([weakThis = wptr(this), label, where] {
auto session = weakThis.promote();
if (!session) {
TLOGNE(WmsLogTag::WMS_LIFE, "%{public}s session is nullptr", where);
return;
}
if (session->label_ == "") {
session->label_ = label;
TLOGNI(WmsLogTag::WMS_LIFE, "%{public}s set label success label:%{public}s", where, label.c_str());
}
}, where);
}
std::string Session::GetSessionLabel() const
{
return label_;
}
void Session::SetUpdateSessionLabelListener(const NofitySessionLabelUpdatedFunc& func)
{
updateSessionLabelFunc_ = func;
}
WSError Session::SetSessionIcon(const std::shared_ptr<Media::PixelMap>& icon)
{
WLOGFD("run Session::SetSessionIcon, id: %{public}d", GetPersistentId());
if (scenePersistence_ == nullptr) {
WLOGFE("scenePersistence_ is nullptr.");
return WSError::WS_ERROR_INVALID_OPERATION;
}
scenePersistence_->SaveUpdatedIcon(icon);
std::string updatedIconPath = scenePersistence_->GetUpdatedIconPath();
if (updateSessionIconFunc_) {
updateSessionIconFunc_(updatedIconPath);
}
return WSError::WS_OK;
}
void Session::SetUpdateSessionIconListener(const NofitySessionIconUpdatedFunc& func)
{
updateSessionIconFunc_ = func;
}
WSError Session::Clear(bool needStartCaller, bool isForceClean)
{
TLOGI(WmsLogTag::WMS_LIFE, "id:%{public}d, needStartCaller:%{public}u, isForceClean:%{public}u",
GetPersistentId(), needStartCaller, isForceClean);
auto task = [weakThis = wptr(this), needStartCaller, isForceClean]() {
auto session = weakThis.promote();
if (session == nullptr) {
TLOGNE(WmsLogTag::WMS_LIFE, "session is null");
return;
}
session->isTerminating_ = true;
if (session->terminateSessionFuncNew_) {
session->terminateSessionFuncNew_(session->GetSessionInfo(), needStartCaller, false, isForceClean);
}
};
PostLifeCycleTask(task, "Clear", LifeCycleTaskType::STOP);
return WSError::WS_OK;
}
void Session::SetSessionExceptionListener(NotifySessionExceptionFunc&& func, bool fromJsScene)
{
PostTask([weakThis = wptr(this), where = __func__, func = std::move(func), fromJsScene] {
auto session = weakThis.promote();
if (!session) {
TLOGNE(WmsLogTag::WMS_LIFE, "%{public}s session is nullptr", where);
return;
}
if (fromJsScene) {
session->jsSceneSessionExceptionFunc_ = std::move(func);
} else {
session->sessionExceptionFunc_ = std::move(func);
}
}, __func__);
}
void Session::SetSessionSnapshotListener(const NotifySessionSnapshotFunc& func)
{
if (func == nullptr) {
WLOGFE("func is nullptr");
return;
}
notifySessionSnapshotFunc_ = func;
}
void Session::SetSessionSaveSnapshotCompleteListener(const NotifySessionSaveSnapshotCompleteFunc& func)
{
if (func == nullptr) {
WLOGFE("func is nullptr");
return;
}
notifySessionSaveSnapshotCompleteFunc_ = func;
}
void Session::SetPendingSessionToForegroundListener(NotifyPendingSessionToForegroundFunc&& func)
{
PostTask([weakThis = wptr(this), func = std::move(func), where = __func__] {
auto session = weakThis.promote();
if (!session) {
TLOGNE(WmsLogTag::WMS_LIFE, "%{public}s session is nullptr", where);
return;
}
session->pendingSessionToForegroundFunc_ = std::move(func);
}, __func__);
}
WSError Session::PendingSessionToForeground()
{
TLOGI(WmsLogTag::WMS_LIFE, "id: %{public}d", GetPersistentId());
if (pendingSessionActivationFunc_) {
SessionInfo info = GetSessionInfo();
pendingSessionActivationFunc_(info);
}
return WSError::WS_OK;
}
void Session::SetPendingSessionToBackgroundListener(NotifyPendingSessionToBackgroundFunc&& func)
{
PostTask([weakThis = wptr(this), func = std::move(func), where = __func__] {
auto session = weakThis.promote();
if (!session) {
TLOGNE(WmsLogTag::WMS_LIFE, "%{public}s session is nullptr", where);
return;
}
session->pendingSessionToBackgroundFunc_ = std::move(func);
}, __func__);
}
WSError Session::PendingSessionToBackground(const BackgroundParams& params)
{
TLOGI(WmsLogTag::WMS_LIFE, "id: %{public}d, shouldBackToCaller: %{public}d",
GetPersistentId(), params.shouldBackToCaller);
if (pendingSessionToBackgroundFunc_) {
pendingSessionToBackgroundFunc_(GetSessionInfo(), params);
}
return WSError::WS_OK;
}
void Session::SetPendingSessionToBackgroundForDelegatorListener(
NotifyPendingSessionToBackgroundForDelegatorFunc&& func)
{
PostTask([weakThis = wptr(this), func = std::move(func), where = __func__] {
auto session = weakThis.promote();
if (!session) {
TLOGNE(WmsLogTag::WMS_LIFE, "%{public}s session is nullptr", where);
return;
}
session->pendingSessionToBackgroundForDelegatorFunc_ = std::move(func);
}, __func__);
}
WSError Session::PendingSessionToBackgroundForDelegator(bool shouldBackToCaller, LifeCycleChangeReason reason)
{
TLOGI(WmsLogTag::WMS_LIFE, "id: %{public}d, shouldBackToCaller: %{public}d, reason: %{public}d",
GetPersistentId(), shouldBackToCaller, reason);
if (pendingSessionToBackgroundForDelegatorFunc_) {
pendingSessionToBackgroundForDelegatorFunc_(GetSessionInfo(), shouldBackToCaller, reason);
}
return WSError::WS_OK;
}
void Session::SetRaiseToAppTopForPointDownFunc(const NotifyRaiseToTopForPointDownFunc& func)
{
raiseToTopForPointDownFunc_ = func;
}
void Session::NotifyScreenshot()
{
if (!sessionStage_) {
return;
}
sessionStage_->NotifyScreenshot();
}
WSError Session::NotifyScreenshotAppEvent(ScreenshotEventType type)
{
TLOGI(WmsLogTag::WMS_ATTRIBUTE, "winId: %{public}d, event: %{public}d", GetPersistentId(), type);
if (!sessionStage_) {
TLOGE(WmsLogTag::WMS_ATTRIBUTE, "sessionStage is null");
return WSError::WS_ERROR_NULLPTR;
}
return sessionStage_->NotifyScreenshotAppEvent(type);
}
WSError Session::NotifyCloseExistPipWindow()
{
if (!sessionStage_) {
return WSError::WS_ERROR_NULLPTR;
}
return sessionStage_->NotifyCloseExistPipWindow();
}
WSError Session::NotifyDestroy()
{
if (!sessionStage_) {
return WSError::WS_ERROR_NULLPTR;
}
return sessionStage_->NotifyDestroy();
}
WSError Session::NotifyAppForceLandscapeConfigUpdated()
{
if (!sessionStage_) {
return WSError::WS_ERROR_NULLPTR;
}
return sessionStage_->NotifyAppForceLandscapeConfigUpdated();
}
void Session::SetParentSession(const sptr<Session>& session)
{
if (session == nullptr) {
WLOGFW("Session is nullptr");
return;
}
{
std::unique_lock<std::shared_mutex> lock(parentSessionMutex_);
parentSession_ = session;
}
TLOGD(WmsLogTag::WMS_SUB, "[WMSDialog][WMSSub]Set parent success, parentId: %{public}d, id: %{public}d",
session->GetPersistentId(), GetPersistentId());
}
sptr<Session> Session::GetParentSession() const
{
std::shared_lock<std::shared_mutex> lock(parentSessionMutex_);
return parentSession_;
}
sptr<Session> Session::GetMainSession() const
{
if (SessionHelper::IsMainWindow(GetWindowType())) {
return const_cast<Session*>(this);
} else if (parentSession_) {
return parentSession_->GetMainSession();
} else {
return nullptr;
}
}
sptr<Session> Session::GetMainSessionOrLoosenedSession() const
{
if (SessionHelper::IsMainWindow(GetWindowType()) || IsLoosenedWithFreeMultiMode()) {
return const_cast<Session*>(this);
} else if (parentSession_) {
return parentSession_->GetMainSessionOrLoosenedSession();
} else {
return nullptr;
}
}
sptr<Session> Session::GetMainOrFloatSession() const
{
auto windowType = GetWindowType();
if (SessionHelper::IsMainWindow(windowType) || windowType == WindowType::WINDOW_TYPE_FLOAT) {
return const_cast<Session*>(this);
} else if (parentSession_) {
return parentSession_->GetMainOrFloatSession();
} else {
return nullptr;
}
}
bool Session::IsAncestorsSession(int32_t ancestorsId) const
{
if (GetSessionProperty()->GetParentPersistentId() == ancestorsId) {
return true;
}
auto parentSession = GetParentSession();
if (parentSession != nullptr) {
return parentSession->IsAncestorsSession(ancestorsId);
}
return false;
}
void Session::BindDialogToParentSession(const sptr<Session>& session)
{
std::unique_lock<std::shared_mutex> lock(dialogVecMutex_);
auto iter = std::find(dialogVec_.begin(), dialogVec_.end(), session);
if (iter != dialogVec_.end()) {
TLOGW(WmsLogTag::WMS_DIALOG, "Dialog is existed in parentVec, id: %{public}d, parentId: %{public}d",
session->GetPersistentId(), GetPersistentId());
return;
}
dialogVec_.push_back(session);
TLOGD(WmsLogTag::WMS_DIALOG, "Bind dialog success, id: %{public}d, parentId: %{public}d",
session->GetPersistentId(), GetPersistentId());
}
void Session::RemoveDialogToParentSession(const sptr<Session>& session)
{
std::unique_lock<std::shared_mutex> lock(dialogVecMutex_);
auto iter = std::find(dialogVec_.begin(), dialogVec_.end(), session);
if (iter != dialogVec_.end()) {
TLOGD(WmsLogTag::WMS_DIALOG, "Remove dialog success, id: %{public}d, parentId: %{public}d",
session->GetPersistentId(), GetPersistentId());
dialogVec_.erase(iter);
}
TLOGW(WmsLogTag::WMS_DIALOG, "Remove dialog failed, id: %{public}d, parentId: %{public}d",
session->GetPersistentId(), GetPersistentId());
}
std::vector<sptr<Session>> Session::GetDialogVector() const
{
std::shared_lock<std::shared_mutex> lock(dialogVecMutex_);
return dialogVec_;
}
void Session::ClearDialogVector()
{
std::unique_lock<std::shared_mutex> lock(dialogVecMutex_);
dialogVec_.clear();
TLOGD(WmsLogTag::WMS_DIALOG, "parentId: %{public}d", GetPersistentId());
return;
}
bool Session::CheckDialogOnForeground()
{
auto dialogVec = GetDialogVector();
if (dialogVec.empty()) {
TLOGD(WmsLogTag::WMS_DIALOG, "Dialog is empty, id: %{public}d", GetPersistentId());
return false;
}
for (auto iter = dialogVec.rbegin(); iter != dialogVec.rend(); iter++) {
auto dialogSession = *iter;
if (dialogSession && (dialogSession->GetSessionState() == SessionState::STATE_ACTIVE ||
dialogSession->GetSessionState() == SessionState::STATE_FOREGROUND)) {
TLOGD(WmsLogTag::WMS_DIALOG, "Notify touch dialog window, id: %{public}d", GetPersistentId());
return true;
}
}
return false;
}
bool Session::CheckPointerEventDispatch(const std::shared_ptr<MMI::PointerEvent>& pointerEvent) const
{
return true;
}
bool Session::IsTopDialog() const
{
int32_t currentPersistentId = GetPersistentId();
auto parentSession = GetParentSession();
if (parentSession == nullptr) {
TLOGW(WmsLogTag::WMS_DIALOG, "Dialog's Parent is NULL. id: %{public}d", currentPersistentId);
return false;
}
auto parentDialogVec = parentSession->GetDialogVector();
if (parentDialogVec.size() <= 1) {
return true;
}
for (auto iter = parentDialogVec.rbegin(); iter != parentDialogVec.rend(); iter++) {
auto dialogSession = *iter;
if (dialogSession && (dialogSession->GetSessionState() == SessionState::STATE_ACTIVE ||
dialogSession->GetSessionState() == SessionState::STATE_FOREGROUND)) {
WLOGFI("Dialog id: %{public}d, current dialog id: %{public}d", dialogSession->GetPersistentId(),
currentPersistentId);
return dialogSession->GetPersistentId() == currentPersistentId;
}
}
return false;
}
const char* Session::DumpPointerWindowArea(MMI::WindowArea area) const
{
const std::map<MMI::WindowArea, const char*> areaMap = {
{ MMI::WindowArea::FOCUS_ON_INNER, "FOCUS_ON_INNER" },
{ MMI::WindowArea::FOCUS_ON_TOP, "FOCUS_ON_TOP" },
{ MMI::WindowArea::FOCUS_ON_BOTTOM, "FOCUS_ON_BOTTOM" },
{ MMI::WindowArea::FOCUS_ON_LEFT, "FOCUS_ON_LEFT" },
{ MMI::WindowArea::FOCUS_ON_RIGHT, "FOCUS_ON_RIGHT" },
{ MMI::WindowArea::FOCUS_ON_BOTTOM_LEFT, "FOCUS_ON_BOTTOM_LEFT" },
{ MMI::WindowArea::FOCUS_ON_BOTTOM_RIGHT, "FOCUS_ON_BOTTOM_RIGHT" },
{ MMI::WindowArea::FOCUS_ON_TOP_LEFT, "FOCUS_ON_TOP_LEFT" },
{ MMI::WindowArea::FOCUS_ON_TOP_RIGHT, "FOCUS_ON_TOP_RIGHT" },
{ MMI::WindowArea::EXIT, "EXIT" }
};
auto iter = areaMap.find(area);
if (iter == areaMap.end()) {
return "UNKNOWN";
}
return iter->second;
}
WSError Session::RaiseToAppTopForPointDown()
{
if (raiseToTopForPointDownFunc_) {
raiseToTopForPointDownFunc_();
WLOGFD("RaiseToAppTopForPointDown, id: %{public}d, type: %{public}d", GetPersistentId(), GetWindowType());
}
return WSError::WS_OK;
}
void Session::PresentFocusIfPointDown()
{
TLOGI(WmsLogTag::WMS_FOCUS, "id: %{public}d,type: %{public}d", GetPersistentId(), GetWindowType());
if (!isFocused_ && GetFocusable()) {
FocusChangeReason reason = FocusChangeReason::CLICK;
NotifyRequestFocusStatusNotifyManager(true, false, reason);
}
NotifyClickIfNeed();
}
void Session::HandlePointDownDialog()
{
sptr<Session> lastValidDialog = nullptr;
auto dialogVec = GetDialogVector();
for (auto dialog : dialogVec) {
if (dialog && (dialog->GetSessionState() == SessionState::STATE_FOREGROUND ||
dialog->GetSessionState() == SessionState::STATE_ACTIVE)) {
dialog->RaiseToAppTopForPointDown();
lastValidDialog = dialog;
TLOGD(WmsLogTag::WMS_DIALOG, "Point main window, raise to top and dialog need focus, "
"id: %{public}d, dialogId: %{public}d", GetPersistentId(), dialog->GetPersistentId());
}
}
if (lastValidDialog != nullptr) {
lastValidDialog->PresentFocusIfPointDown();
}
}
bool Session::IsSubWindowZLevelAboveParentLoosened() const
{
if (auto sessionProperty = GetSessionProperty()) {
return sessionProperty->IsSubWindowZLevelAboveParentLoosened();
}
return false;
}
bool Session::IsLoosenedWithFreeMultiMode() const
{
TLOGD(WmsLogTag::WMS_SUB,
"id: %{public}d, isAbover: %{public}d, IsFreeMultiWindowMode: %{public}d, ispc: %{public}d",
GetPersistentId(), IsSubWindowZLevelAboveParentLoosened(),
systemConfig_.IsFreeMultiWindowMode(), systemConfig_.IsPcWindow());
return WindowHelper::IsSubWindow(GetWindowType()) && IsSubWindowZLevelAboveParentLoosened() &&
(systemConfig_.IsPcWindow() || systemConfig_.IsFreeMultiWindowMode());
}
WSError Session::HandleSubWindowClick(int32_t action, int32_t sourceType, bool isExecuteDelayRaise)
{
const auto& property = GetSessionProperty();
auto parentSession = GetParentSession();
if (property->GetSubWindowZLevel() < DIALOG_SUB_WINDOW_Z_LEVEL && parentSession &&
parentSession->CheckDialogOnForeground()) {
return WSError::WS_ERROR_INVALID_PERMISSION;
}
bool raiseEnabled = property->GetRaiseEnabled();
bool isHoverDown = action == MMI::PointerEvent::POINTER_ACTION_HOVER_ENTER &&
sourceType == MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN;
bool isPointDown = action == MMI::PointerEvent::POINTER_ACTION_DOWN ||
action == MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN || isHoverDown;
bool isPointMove = action == MMI::PointerEvent::POINTER_ACTION_MOVE;
bool isLoosenedWithFreeMultiMode = IsLoosenedWithFreeMultiMode();
if (isExecuteDelayRaise) {
if (raiseEnabled && action == MMI::PointerEvent::POINTER_ACTION_BUTTON_UP) {
RaiseToAppTopForPointDown();
}
if (!raiseEnabled && parentSession && !isPointMove && !isLoosenedWithFreeMultiMode) {
parentSession->NotifyClick(!IsScbCoreEnabled());
}
return WSError::WS_OK;
}
bool isModal = WindowHelper::IsModalWindow(property->GetWindowFlags());
TLOGD(WmsLogTag::WMS_EVENT, "id:%{public}d raise:%{public}d down:%{public}d modal:%{public}d loose:%{public}d",
GetPersistentId(), raiseEnabled, isPointDown, isModal, isLoosenedWithFreeMultiMode);
if (!isPointDown) {
return WSError::WS_OK;
}
if (raiseEnabled) {
if (!isModal) {
RaiseToAppTopForPointDown();
return WSError::WS_OK;
}
if (auto mainSession = GetMainSessionOrLoosenedSession()) {
if (mainSession->IsLoosenedWithFreeMultiMode()) {
mainSession->RaiseToAppTopForPointDown();
} else {
mainSession->NotifyClick(false);
}
}
return WSError::WS_OK;
}
if (parentSession && !isLoosenedWithFreeMultiMode) {
parentSession->NotifyClick(!IsScbCoreEnabled());
}
return WSError::WS_OK;
}
WSError Session::HandlePointerEventForFocus(const std::shared_ptr<MMI::PointerEvent>& pointerEvent,
bool isExecuteDelayRaise)
{
if (pointerEvent == nullptr) {
TLOGE(WmsLogTag::WMS_EVENT, "PointerEvent is nullptr");
return WSError::WS_ERROR_NULLPTR;
}
TLOGD(WmsLogTag::WMS_EVENT, "eventId:%{public}d, action:%{public}s, persistentId:%{public}d ",
pointerEvent->GetId(), pointerEvent->DumpPointerAction(), persistentId_);
auto pointerAction = pointerEvent->GetPointerAction();
auto sourceType = pointerEvent->GetSourceType();
bool isHoverDown = pointerAction == MMI::PointerEvent::POINTER_ACTION_HOVER_ENTER &&
sourceType == MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN;
bool isPointDown = (pointerAction == MMI::PointerEvent::POINTER_ACTION_DOWN) ||
(pointerAction == MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN) || isHoverDown;
if (GetWindowType() == WindowType::WINDOW_TYPE_APP_MAIN_WINDOW) {
if (CheckDialogOnForeground() && isPointDown) {
HandlePointDownDialog();
return WSError::WS_ERROR_INVALID_PERMISSION;
}
} else if (GetWindowType() == WindowType::WINDOW_TYPE_APP_SUB_WINDOW && !IsLoosenedWithFreeMultiMode()) {
WSError ret = HandleSubWindowClick(pointerAction, sourceType, isExecuteDelayRaise);
if (ret != WSError::WS_OK) {
return ret;
}
} else if (GetWindowType() == WindowType::WINDOW_TYPE_DIALOG) {
auto parentSession = GetParentSession();
if (parentSession && parentSession->CheckDialogOnForeground() && isPointDown) {
parentSession->HandlePointDownDialog();
if (!IsTopDialog()) {
TLOGI(WmsLogTag::WMS_DIALOG, "There is at least one active dialog upon this dialog, id: %{public}d",
GetPersistentId());
return WSError::WS_ERROR_INVALID_PERMISSION;
}
}
}
if (!isExecuteDelayRaise) {
PresentFocusIfNeed(pointerAction, sourceType);
} else if (pointerAction == MMI::PointerEvent::POINTER_ACTION_BUTTON_UP) {
if (!isFocused_ && GetFocusable()) {
NotifyRequestFocusStatusNotifyManager(true, false, FocusChangeReason::CLICK);
}
NotifyClickIfNeed();
}
return WSError::WS_OK;
}
bool Session::HasParentSessionWithToken(const sptr<IRemoteObject>& token)
{
auto parentSession = GetParentSession();
if (parentSession == nullptr) {
TLOGD(WmsLogTag::WMS_FOCUS, "parent session is nullptr: %{public}d", GetPersistentId());
return false;
}
if (parentSession->GetAbilityToken() == token) {
return true;
}
return parentSession->HasParentSessionWithToken(token);
}
WSError Session::TransferPointerEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent,
bool needNotifyClient, bool isExecuteDelayRaise)
{
TLOGD(WmsLogTag::WMS_EVENT, "id: %{public}d", GetPersistentId());
if (!IsSystemSession() && !IsSessionValid()) {
return WSError::WS_ERROR_INVALID_SESSION;
}
if (pointerEvent == nullptr) {
TLOGE(WmsLogTag::WMS_EVENT, "PointerEvent is nullptr");
return WSError::WS_ERROR_NULLPTR;
}
WSError focusRet = HandlePointerEventForFocus(pointerEvent, isExecuteDelayRaise);
if (focusRet != WSError::WS_OK) {
return focusRet;
}
if (!windowEventChannel_) {
if (!IsSystemSession()) {
TLOGE(WmsLogTag::WMS_EVENT, "windowEventChannel_ is null");
}
return WSError::WS_ERROR_NULLPTR;
}
if (needNotifyClient) {
WSError ret = windowEventChannel_->TransferPointerEvent(pointerEvent);
if (ret != WSError::WS_OK) {
WLOGFE("InputTracking id:%{public}d, TransferPointer failed, ret:%{public}d ",
pointerEvent->GetId(), ret);
}
return ret;
} else {
pointerEvent->MarkProcessed();
}
auto pointerAction = pointerEvent->GetPointerAction();
if (pointerAction == MMI::PointerEvent::POINTER_ACTION_MOVE ||
pointerAction == MMI::PointerEvent::POINTER_ACTION_PULL_MOVE) {
TLOGD(WmsLogTag::WMS_EVENT, "eventId:%{public}d, action:%{public}s, persistentId:%{public}d, "
"bundleName:%{public}s, pid:%{public}d", pointerEvent->GetId(), pointerEvent->DumpPointerAction(),
persistentId_, callingBundleName_.c_str(), callingPid_);
} else {
TLOGD(WmsLogTag::WMS_EVENT, "eventId:%{public}d, action:%{public}s, "
"persistentId:%{public}d, bundleName:%{public}s, pid:%{public}d",
pointerEvent->GetId(), pointerEvent->DumpPointerAction(),
persistentId_, callingBundleName_.c_str(), callingPid_);
}
if (pointerAction == MMI::PointerEvent::POINTER_ACTION_ENTER_WINDOW ||
pointerAction == MMI::PointerEvent::POINTER_ACTION_LEAVE_WINDOW ||
pointerAction == MMI::PointerEvent::POINTER_ACTION_PULL_IN_WINDOW ||
pointerAction == MMI::PointerEvent::POINTER_ACTION_PULL_OUT_WINDOW) {
TLOGD(WmsLogTag::WMS_EVENT, "Action:%{public}s, eventId:%{public}d, report without timer",
pointerEvent->DumpPointerAction(), pointerEvent->GetId());
}
return WSError::WS_OK;
}
WSError Session::TransferKeyEvent(const std::shared_ptr<MMI::KeyEvent>& keyEvent)
{
WLOGFD("Session TransferKeyEvent eventId:%{public}d persistentId:%{public}d bundleName:%{public}s pid:%{public}d",
keyEvent->GetId(), persistentId_, callingBundleName_.c_str(), callingPid_);
if (!windowEventChannel_) {
WLOGFE("windowEventChannel_ is null");
return WSError::WS_ERROR_NULLPTR;
}
WLOGD("TransferKeyEvent, id: %{public}d", persistentId_);
WSError ret = windowEventChannel_->TransferKeyEvent(keyEvent);
if (ret != WSError::WS_OK) {
WLOGFE("TransferKeyEvent failed, ret:%{public}d", ret);
return ret;
}
return WSError::WS_OK;
}
WSError Session::TransferBackPressedEventForConsumed(bool& isConsumed)
{
if (!windowEventChannel_) {
WLOGFE("windowEventChannel_ is null");
return WSError::WS_ERROR_NULLPTR;
}
return windowEventChannel_->TransferBackpressedEventForConsumed(isConsumed);
}
WSError Session::TransferKeyEventForConsumed(const std::shared_ptr<MMI::KeyEvent>& keyEvent, bool& isConsumed,
bool isPreImeEvent)
{
if (!windowEventChannel_) {
WLOGFE("windowEventChannel_ is null");
return WSError::WS_ERROR_NULLPTR;
}
if (keyEvent == nullptr) {
WLOGFE("KeyEvent is nullptr");
return WSError::WS_ERROR_NULLPTR;
}
return windowEventChannel_->TransferKeyEventForConsumed(keyEvent, isConsumed, isPreImeEvent);
}
WSError Session::TransferFocusActiveEvent(bool isFocusActive)
{
if (!windowEventChannel_) {
WLOGFE("windowEventChannel_ is null");
return WSError::WS_ERROR_NULLPTR;
}
return windowEventChannel_->TransferFocusActiveEvent(isFocusActive);
}
WSError Session::TransferFocusStateEvent(bool focusState)
{
if (!windowEventChannel_) {
if (!IsSystemSession()) {
WLOGFW("windowEventChannel_ is null");
}
return WSError::WS_ERROR_NULLPTR;
}
return windowEventChannel_->TransferFocusState(focusState);
}
std::shared_ptr<Media::PixelMap> Session::Snapshot() const
{
return Snapshot(SnapshotOptions());
}
std::shared_ptr<Media::PixelMap> Session::Snapshot(const SnapshotOptions& options) const
{
HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "Snapshot[%d][%s]", persistentId_, sessionInfo_.bundleName_.c_str());
auto surfaceNode = GetSurfaceNode();
if (!CheckSurfaceNodeForSnapshot(surfaceNode)) {
TLOGE(WmsLogTag::WMS_PATTERN, "SurfaceNode invalid %{public}d", persistentId_);
ReportPrivacyWindowSnapshotFail(SNAPSHOT_ERROR_INVALID_SURFACE_NODE, "surface node is invalid");
return nullptr;
}
bool needBlurSnapshot = options.disableBlur ? false : GetNeedUseBlurSnapshot();
auto callback = std::make_shared<SurfaceCaptureFuture>();
auto scaleValue = (options.scaleParam < 0.0f || std::fabs(options.scaleParam) < std::numeric_limits<float>::min()) ?
snapshotScale_ : options.scaleParam;
scaleValue = needBlurSnapshot ? scaleValue * BLUR_SNAPSHOT_SCALE : scaleValue;
RSSurfaceCaptureConfig config = {
.scaleX = scaleValue,
.scaleY = scaleValue,
.useDma = true,
.useCurWindow = options.useCurWindow,
.windowSync = options.windowSync,
.backGroundColor = GetBackgroundColor(),
.needErrorCode = true,
};
auto rsUICtx = surfaceNode->GetRSUIContext();
if (rsUICtx == nullptr || rsUICtx->GetRSRenderInterface() == nullptr) {
TLOGE(WmsLogTag::WMS_PATTERN, "rsUIContext is null");
ReportPrivacyWindowSnapshotFail(SNAPSHOT_ERROR_RENDER_CONTEXT, "rs ui context is null");
return nullptr;
}
bool ret = false;
if (needBlurSnapshot) {
config.backGroundColor = blurBackgroundColor_ == std::numeric_limits<uint32_t>::max() ?
GetBackgroundColor() : blurBackgroundColor_;
ret = rsUICtx->GetRSRenderInterface()->TakeSurfaceCaptureWithBlur(surfaceNode, callback, config, blurRadius_);
} else {
ret = rsUICtx->GetRSRenderInterface()->TakeSurfaceCapture(surfaceNode, callback, config);
}
if (!ret) {
TLOGE(WmsLogTag::WMS_PATTERN, "TakeSurfaceCapture failed %{public}d", persistentId_);
ReportPrivacyWindowSnapshotFail(SNAPSHOT_ERROR_TAKE_CAPTURE, "take surface capture failed");
return nullptr;
}
constexpr int32_t FFRT_SNAPSHOT_TIMEOUT_MS = 5000;
auto pixelMap = callback->GetResult(options.runInFfrt ? FFRT_SNAPSHOT_TIMEOUT_MS : SNAPSHOT_TIMEOUT_MS);
bool hasCaptureError = callback->GetCaptureErrorCode() != CaptureError::CAPTURE_OK;
if (hasCaptureError) {
TLOGE(WmsLogTag::WMS_PATTERN, "Capture privacy or special layer failed %{public}d", persistentId_);
ReportPrivacyWindowSnapshotFail(SNAPSHOT_ERROR_TAKE_CAPTURE, "capture privacy or special layer failed");
}
if (pixelMap != nullptr) {
bool isCropped = CropSnapshotPixelMap(pixelMap, lastLayoutRect_, scaleValue);
TLOGI(WmsLogTag::WMS_PATTERN, "Save snapshot WxH=%{public}dx%{public}d, "
"id: %{public}d, uniqueId: %{public}d, isValid:%{public}d, isCropped: %{public}d",
pixelMap->GetWidth(), pixelMap->GetHeight(), persistentId_, pixelMap->GetUniqueId(),
pixelMap->GetPixels() != nullptr, isCropped);
if (notifySessionSnapshotFunc_) {
notifySessionSnapshotFunc_(persistentId_);
}
return pixelMap;
}
TLOGE(WmsLogTag::WMS_PATTERN, "Save snapshot failed, id: %{public}d", persistentId_);
if (!hasCaptureError) {
ReportPrivacyWindowSnapshotFail(SNAPSHOT_ERROR_EMPTY_PIXELMAP, "pixelmap is null");
}
return nullptr;
}
void Session::ReportPrivacyWindowSnapshotFail(int32_t errorCode, const std::string& errorMsg) const
{
if (!GetIsPrivacyMode() && !GetSnapshotPrivacyMode()) {
TLOGE(WmsLogTag::WMS_PATTERN, "skip privacy snapshot fail report, privacy: %{public}d, "
"snapshotPrivacy: %{public}d, id: %{public}d",
GetIsPrivacyMode(), GetSnapshotPrivacyMode(), persistentId_);
return;
}
auto sessionRect = GetSessionRect();
PrivacyWindowSnapshotInfo reportInfo;
reportInfo.bundleName = sessionInfo_.bundleName_;
reportInfo.abilityName = sessionInfo_.abilityName_;
reportInfo.windowId = persistentId_;
reportInfo.windowType = GetWindowType();
reportInfo.windowMode = GetWindowMode();
reportInfo.rect.posX_ = sessionRect.posX_;
reportInfo.rect.posY_ = sessionRect.posY_;
reportInfo.rect.width_ = static_cast<uint32_t>(sessionRect.width_ < 0 ? 0 : sessionRect.width_);
reportInfo.rect.height_ = static_cast<uint32_t>(sessionRect.height_ < 0 ? 0 : sessionRect.height_);
reportInfo.errorCode = errorCode;
reportInfo.errorMsg = errorMsg;
int32_t ret = HiSysEventWrite(
HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER, "PRIVACY_WINDOW_SNAPSHOT_FAIL",
HiviewDFX::HiSysEvent::EventType::FAULT,
"BUNDLE_NAME", reportInfo.bundleName,
"ABILITY_NAME", reportInfo.abilityName,
"WINDOW_ID", reportInfo.windowId,
"WINDOW_TYPE", static_cast<int32_t>(reportInfo.windowType),
"WINDOW_MODE", static_cast<int32_t>(reportInfo.windowMode),
"POS_X", reportInfo.rect.posX_,
"POS_Y", reportInfo.rect.posY_,
"WIDTH", static_cast<int32_t>(reportInfo.rect.width_),
"HEIGHT", static_cast<int32_t>(reportInfo.rect.height_),
"ERROR_CODE", reportInfo.errorCode,
"ERROR_MSG", reportInfo.errorMsg);
if (ret != 0) {
TLOGE(WmsLogTag::WMS_PATTERN, "write HiSysEvent error, ret: %{public}d", ret);
}
TLOGE(WmsLogTag::WMS_PATTERN, "write privacy snapshot fail event ret: %{public}d, bundle: %{public}s, "
"ability: %{public}s, windowId: %{public}d, errorCode: %{public}d",
ret, reportInfo.bundleName.c_str(), reportInfo.abilityName.c_str(), reportInfo.windowId, errorCode);
}
bool Session::CropSnapshotPixelMap(const std::shared_ptr<Media::PixelMap>& pixelMap, const WSRect& rect,
float scaleValue) const
{
if (pixelMap == nullptr) {
return false;
}
bool needCropWidth = WSSnapshotHelper::NeedCrop(rect.width_, scaleValue);
bool needCropHeight = WSSnapshotHelper::NeedCrop(rect.height_, scaleValue);
auto width = needCropWidth ? pixelMap->GetWidth() - PIXEL_OFFSET : pixelMap->GetWidth();
auto height = needCropHeight ? pixelMap->GetHeight() - PIXEL_OFFSET : pixelMap->GetHeight();
bool needCrop = needCropWidth || needCropHeight;
if (needCrop) {
pixelMap->crop({ 0, 0, width, height });
return true;
}
return false;
}
bool Session::GetNeedUseBlurSnapshot() const
{
bool isPrivacyMode = GetIsPrivacyMode();
bool snapshotPrivacyMode = GetSnapshotPrivacyMode();
ControlInfo controlInfo;
bool isAppControl = GetAppControlInfo(ControlAppType::APP_LOCK, controlInfo);
bool isAppUseControl = controlInfo.isNeedControl;
bool needUseBlurSnapshot = isPrivacyMode || snapshotPrivacyMode || (isAppControl && isAppUseControl);
if (needUseBlurSnapshot) {
TLOGI(WmsLogTag::WMS_PATTERN, "id: %{public}d, isPrivacyMode: %{public}d, snapshotPrivacyMode: %{public}d, "
"isAppLock: %{public}d", persistentId_, isPrivacyMode, snapshotPrivacyMode, isAppUseControl);
}
return needUseBlurSnapshot;
}
bool Session::CheckSurfaceNodeForSnapshot(std::shared_ptr<RSSurfaceNode> surfaceNode) const
{
if (scenePersistence_ == nullptr) {
return false;
}
if (IsPersistentImageFit()) {
return false;
}
if (!surfaceNode) {
TLOGE(WmsLogTag::WMS_PATTERN, "surfaceNode null id: %{public}d", persistentId_);
return false;
}
if (!surfaceNode->IsBufferAvailable()) {
DeleteHasSnapshot();
scenePersistence_->ClearSnapshot();
return false;
}
return true;
}
void Session::UpdateAppLockSnapshot(ControlAppType type, ControlInfo controlInfo)
{
if (!WindowHelper::IsMainWindow(GetWindowType())) {
return;
}
if (type != ControlAppType::APP_LOCK) {
return;
}
if (!IsSupportAppLockSnapshot()) {
SaveSnapshot(true, true, nullptr);
return;
}
bool isAppUseControl = controlInfo.isNeedControl;
TLOGI(WmsLogTag::WMS_PATTERN, "id: %{public}d, isAppLock: %{public}d", persistentId_, isAppUseControl);
if (isAppLockControl_.load() == isAppUseControl) {
return;
}
isAppLockControl_.store(isAppUseControl);
if (isAppUseControl) {
if (IsPersistentImageFit()) {
NotifyAddSnapshot(false, false, false);
return;
}
if (!controlInfo.isControlRecentOnly) {
NotifyAddSnapshot(true, false, false);
}
SaveSnapshot(true, true, nullptr, true);
return;
}
if (IsLifecycleForeground() || isVisible_.load()) {
NotifyRemoveSnapshot();
return;
}
if (!GetIsPrivacyMode() && !GetSnapshotPrivacyMode()) {
SaveSnapshot(true, true, nullptr, true);
}
}
bool Session::IsSupportAppLockSnapshot() const
{
if (!onGetAppUseControlDisplayMapFunc_) {
TLOGI(WmsLogTag::WMS_PATTERN, "id: %{public}d GetAppUseControlDisplayMap failed", persistentId_);
return true;
}
auto& appUseControlDisplayMap = onGetAppUseControlDisplayMapFunc_();
auto displayId = GetSessionProperty()->GetDisplayId();
if (appUseControlDisplayMap.find(displayId) == appUseControlDisplayMap.end()) {
return true;
}
bool support = appUseControlDisplayMap[displayId];
TLOGI(WmsLogTag::WMS_PATTERN, "id: %{public}d, displayId: %{public}" PRIu64 ", support: %{public}d",
persistentId_, displayId, support);
return support;
}
bool Session::GetSnapshotPrivacyMode() const
{
if (IsLifecycleForeground()) {
return false;
}
return snapshotPrivacyMode_.load();
}
uint32_t Session::GetBackgroundColor() const
{
std::shared_ptr<AbilityRuntime::ApplicationContext> appContext = AbilityRuntime::Context::GetApplicationContext();
if (appContext != nullptr) {
std::shared_ptr<AppExecFwk::Configuration> appConfig = appContext->GetConfiguration();
if (appConfig != nullptr) {
std::string colorMode = appConfig->GetItem(AAFwk::GlobalConfigurationKey::SYSTEM_COLORMODE);
TLOGI(WmsLogTag::WMS_PATTERN, ":%{public}s", colorMode.c_str());
return (colorMode == AppExecFwk::ConfigurationInner::COLOR_MODE_DARK) ? COLOR_BLACK : COLOR_WHITE;
}
} else {
TLOGE(WmsLogTag::WMS_PATTERN, "app context is nullptr, use default backGroundColor WHITE");
}
return COLOR_WHITE;
}
void Session::RenameSnapshotFromOldPersistentId(int32_t oldPersistentId)
{
auto task = [weakThis = wptr(this), oldPersistentId, where = __func__]() {
auto session = weakThis.promote();
if (session == nullptr) {
TLOGNE(WmsLogTag::WMS_PATTERN, "%{public}s session is nullptr", where);
return;
}
std::map<std::string, std::string> renameMap;
auto id = session->GetPersistentId();
renameMap["SetImageForRecent_" + std::to_string(oldPersistentId)] = "SetImageForRecent_" + std::to_string(id);
renameMap[session->GetSnapshotPersistentKey(oldPersistentId)] = session->GetSnapshotPersistentKey(id);
for (int32_t screenStatus = SCREEN_UNKNOWN; screenStatus < SCREEN_COUNT; screenStatus++) {
renameMap[session->GetSnapshotPersistentKey(oldPersistentId, screenStatus)] =
session->GetSnapshotPersistentKey(id, screenStatus);
}
ScenePersistentStorage::RenameKeys(renameMap, ScenePersistentStorageType::MAXIMIZE_STATE);
};
auto snapshotFfrtHelper = scenePersistence_->GetSnapshotFfrtHelper();
std::string taskName = "RenameSnapshotFromOldPersistentId" + std::to_string(persistentId_);
snapshotFfrtHelper->CancelTask(taskName);
snapshotFfrtHelper->SubmitTask(std::move(task), taskName);
}
void Session::ResetSnapshot()
{
TLOGI(WmsLogTag::WMS_PATTERN, "id: %{public}d", persistentId_);
std::lock_guard lock(snapshotMutex_);
snapshot_ = nullptr;
if (scenePersistence_ == nullptr) {
TLOGI(WmsLogTag::WMS_PATTERN, "scenePersistence_ %{public}d nullptr", persistentId_);
return;
}
scenePersistence_->ResetSnapshotCache();
}
void Session::ResetPreloadSnapshot()
{
std::lock_guard<std::mutex> lock(preloadSnapshotMutex_);
preloadSnapshot_ = nullptr;
}
void Session::SetBufferNameForPixelMap(const char* functionName, const std::shared_ptr<Media::PixelMap>& pixelMap)
{
std::string functionNameStr = (functionName != nullptr) ? functionName : "unknown";
pixelMap->SetMemoryName(functionNameStr + '_' + std::to_string(GetPersistentId()));
}
void Session::SetPreloadingStartingWindow(bool preloading)
{
preloadingStartingWindow_.store(preloading);
}
bool Session::GetPreloadingStartingWindow() const
{
return preloadingStartingWindow_.load();
}
void Session::PreloadSnapshot()
{
HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "PreloadSnapshot[%d]", persistentId_);
if (snapshot_ != nullptr) {
std::lock_guard<std::mutex> lock(preloadSnapshotMutex_);
preloadSnapshot_ = snapshot_;
return;
}
if (scenePersistence_ == nullptr) {
TLOGW(WmsLogTag::WMS_PATTERN, "scene persistence is null: %{public}d", GetPersistentId());
return;
}
auto key = GetScreenSnapshotStatus();
auto freeMultiWindow = freeMultiWindow_.load();
auto hasSnapshot = scenePersistence_->HasSnapshot(key, freeMultiWindow);
auto isSavingSnapshot = scenePersistence_->IsSavingSnapshot();
const bool matchSnapshot = isSavingSnapshot || hasSnapshot;
auto filePath = scenePersistence_->GetSnapshotFilePath(key, matchSnapshot, freeMultiWindow);
Media::SourceOptions opts;
uint32_t errorCode = 0;
auto imageSource = Media::ImageSource::CreateImageSource(filePath, opts, errorCode);
if (errorCode != 0 || imageSource == nullptr) {
TLOGE(WmsLogTag::WMS_PATTERN, "image source failed err %{public}d", errorCode);
return;
}
Media::ImageInfo imageInfo;
imageSource->GetImageInfo(imageInfo);
TLOGI(WmsLogTag::WMS_PATTERN, "image size: %{public}d, %{public}d", imageInfo.size.width, imageInfo.size.height);
Media::DecodeOptions decodeOpts;
auto uniquePixelMap = imageSource->CreatePixelMap(decodeOpts, errorCode);
if (errorCode != 0) {
TLOGE(WmsLogTag::WMS_PATTERN, "pixelMap failed err %{public}d", errorCode);
return;
}
std::lock_guard<std::mutex> lock(preloadSnapshotMutex_);
preloadSnapshot_ = std::move(uniquePixelMap);
}
void Session::SetPreloadStartingWindow(std::shared_ptr<Media::PixelMap> pixelMap)
{
std::unique_lock<std::shared_mutex> lock(preloadStartingWindowMutex_);
if (pixelMap == nullptr) {
TLOGE(WmsLogTag::WMS_PATTERN, "pixelMap is nullptr");
return;
}
preloadStartingWindowPixelMap_ = pixelMap;
preloadStartingWindowSvgBufferInfo_ = {nullptr, 0};
TLOGI(WmsLogTag::WMS_PATTERN, "pixelMap %{public}d", GetPersistentId());
}
void Session::SetPreloadStartingWindow(std::pair<std::shared_ptr<uint8_t[]>, size_t> bufferInfo)
{
std::unique_lock<std::shared_mutex> lock(preloadStartingWindowMutex_);
if (bufferInfo.first == nullptr || bufferInfo.second == 0) {
TLOGE(WmsLogTag::WMS_PATTERN, "bufferInfo is invalid, size %{public}zu", bufferInfo.second);
return;
}
preloadStartingWindowSvgBufferInfo_ = bufferInfo;
preloadStartingWindowPixelMap_.reset();
TLOGI(WmsLogTag::WMS_PATTERN, "svgBufferInfo %{public}d", GetPersistentId());
}
void Session::ResetPreloadStartingWindow()
{
std::unique_lock<std::shared_mutex> lock(preloadStartingWindowMutex_);
preloadStartingWindowPixelMap_.reset();
preloadStartingWindowSvgBufferInfo_ = {nullptr, 0};
TLOGI(WmsLogTag::WMS_PATTERN, "%{public}d", GetPersistentId());
}
void Session::GetPreloadStartingWindow(std::shared_ptr<Media::PixelMap>& pixelMap,
std::pair<std::shared_ptr<uint8_t[]>, size_t>& bufferInfo)
{
std::shared_lock<std::shared_mutex> lock(preloadStartingWindowMutex_);
pixelMap = nullptr;
bufferInfo = {nullptr, 0};
if (preloadStartingWindowPixelMap_ != nullptr) {
pixelMap = preloadStartingWindowPixelMap_;
TLOGI(WmsLogTag::WMS_PATTERN, "pixelMap %{public}d", GetPersistentId());
return;
}
if (preloadStartingWindowSvgBufferInfo_.first != nullptr && preloadStartingWindowSvgBufferInfo_.second > 0) {
bufferInfo = preloadStartingWindowSvgBufferInfo_;
TLOGI(WmsLogTag::WMS_PATTERN, "svgBufferInfo %{public}d", GetPersistentId());
return;
}
return;
}
void Session::SaveStartWindow(const std::shared_ptr<Media::PixelMap>& persistentPixelMap,
const std::string& saveStartWindowKey)
{
HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "Session::SaveStartWindow[%d][%s]",
persistentId_, sessionInfo_.bundleName_.c_str());
TLOGI(WmsLogTag::WMS_PATTERN, "%{public}d", GetPersistentId());
if (scenePersistence_ == nullptr) {
TLOGE(WmsLogTag::WMS_PATTERN, "failed %{public}d", GetPersistentId());
return;
}
scenePersistence_->SaveStartWindow(persistentPixelMap, saveStartWindowKey, saveStartWindowCallback_);
}
void Session::SaveSnapshot(bool useFfrt, bool needPersist, std::shared_ptr<Media::PixelMap> persistentPixelMap,
bool updateSnapshot, LifeCycleChangeReason reason, bool windowSync)
{
if (scenePersistence_ == nullptr) {
return;
}
auto key = GetSessionSnapshotStatus(reason);
auto rotation = currentRotation_;
if (WSSnapshotHelper::GetInstance()->IsSnapshotNeedCorrect(key)) {
rotation = (rotation + ROTATION_90) % ROTATION_360;
}
auto rotate = WSSnapshotHelper::GetDisplayOrientation(rotation);
if (persistentPixelMap || !SupportSnapshotAllSessionStatus()) {
key = defaultStatus;
rotate = DisplayOrientation::PORTRAIT;
}
isSnapshotBlur_.store(GetNeedUseBlurSnapshot());
bool needCacheSnapshot = (SupportCacheLockedSessionSnapshot() && (reason == LifeCycleChangeReason::SCREEN_LOCK ||
reason == LifeCycleChangeReason::EXPAND_TO_FOLD_SINGLE_POCKET));
const char* const where = __func__;
auto task = [weakThis = wptr(this), runInFfrt = useFfrt, requirePersist = needPersist, persistentPixelMap,
updateSnapshot, key, rotate, needCacheSnapshot, reason, windowSync, where]() {
auto session = weakThis.promote();
if (session == nullptr) {
TLOGNE(WmsLogTag::WMS_LIFE, "session is null");
return;
}
if (reason == LifeCycleChangeReason::QUICK_BATCH_BACKGROUND && session->snapshotNeedCancel_.load()) {
TLOGNW(WmsLogTag::WMS_LIFE, "snapshot canceled id %{public}d", session->GetPersistentId());
return;
}
session->lastLayoutRect_ = session->layoutRect_;
Session::SnapshotOptions options;
options.runInFfrt = runInFfrt;
options.useCurWindow = updateSnapshot;
options.windowSync = windowSync &&
(session->GetDeviceType() == "phone" || session->GetDeviceType() == "tablet");
auto pixelMap = persistentPixelMap ? persistentPixelMap : session->Snapshot(options);
if (pixelMap == nullptr) {
return;
}
if (session->notifySessionSaveSnapshotCompleteFunc_) {
session->notifySessionSaveSnapshotCompleteFunc_(session->persistentId_);
}
session->SetBufferNameForPixelMap(where, pixelMap);
{
std::lock_guard<std::mutex> lock(session->snapshotMutex_);
session->snapshot_ = pixelMap;
}
{
std::lock_guard<std::mutex> lock(session->addSnapshotCallbackMutex_);
session->addSnapshotCallback_();
}
session->SetAddSnapshotCallback([]() {});
if (!requirePersist) {
return;
}
if (!session->scenePersistence_) {
TLOGNE(WmsLogTag::WMS_PATTERN, "scenePersistence_ is null");
return;
}
if (updateSnapshot) {
session->DeleteHasSnapshot();
session->scenePersistence_->ClearSnapshot();
session->NotifyUpdateSnapshotWindow();
}
session->SetHasSnapshot(key, rotate);
Task saveSnapshotCallback = []() {};
if (!needCacheSnapshot) {
std::lock_guard lock(session->saveSnapshotCallbackMutex_);
saveSnapshotCallback = session->saveSnapshotCallback_;
}
session->scenePersistence_->SaveSnapshot(pixelMap, saveSnapshotCallback, key, rotate,
session->freeMultiWindow_.load());
WindowInfoReporter::GetInstance().ReportWindowIO("ASTC",
pixelMap->GetWidth() * pixelMap->GetHeight() / KILOBYTE);
};
if (!useFfrt) {
task();
return;
}
auto snapshotFfrtHelper = scenePersistence_->GetSnapshotFfrtHelper();
std::string taskName = "Session::SaveSnapshot" + std::to_string(persistentId_);
snapshotFfrtHelper->CancelTask(taskName);
snapshotFfrtHelper->SubmitTask(std::move(task), taskName);
}
std::string Session::GetSnapshotPersistentKey(int32_t id)
{
return "Snapshot_" + sessionInfo_.bundleName_ + "_" + std::to_string(id);
}
std::string Session::GetSnapshotPersistentKey(int32_t id, SnapshotStatus key)
{
return "Snapshot_" + sessionInfo_.bundleName_ + "_"+ std::to_string(id) + "_" + std::to_string(key);
}
void Session::SetHasSnapshot(SnapshotStatus key, DisplayOrientation rotate)
{
if (!scenePersistence_) {
TLOGE(WmsLogTag::WMS_PATTERN, "scenePersistence is null");
return;
}
std::string snapshotPersistentKey;
if (freeMultiWindow_.load()) {
scenePersistence_->SetHasSnapshotFreeMultiWindow(true);
snapshotPersistentKey = GetSnapshotPersistentKey(persistentId_);
ScenePersistentStorage::Insert(snapshotPersistentKey, EncodeSnapShotRecoverValue(rotate),
ScenePersistentStorageType::MAXIMIZE_STATE);
} else {
scenePersistence_->SetHasSnapshot(true, key);
snapshotPersistentKey = GetSnapshotPersistentKey(persistentId_, key);
ScenePersistentStorage::Insert(snapshotPersistentKey,
EncodeSnapShotRecoverValue(rotate), ScenePersistentStorageType::MAXIMIZE_STATE);
}
WindowInfoReporter::GetInstance().ReportWindowIO("session_window_maximize_state",
snapshotPersistentKey.length() / KILOBYTE);
}
int32_t Session::EncodeSnapShotRecoverValue(DisplayOrientation rotate)
{
int32_t snapShotRecoverValue = 0;
snapShotRecoverValue +=
SessionHelper::ShiftDecimalDigit(static_cast<int32_t>(rotate),
static_cast<int32_t>(SnapShotRecoverType::ROTATE));
snapShotRecoverValue +=
SessionHelper::ShiftDecimalDigit(static_cast<int32_t>(IsExitSplitOnBackgroundRecover()),
static_cast<int32_t>(SnapShotRecoverType::EXIT_SPLIT_ON_BACKGROUND));
return snapShotRecoverValue;
}
int32_t Session::DecodeSnapShotRecoverValue(int32_t snapShotRecoverValue, SnapShotRecoverType snapShotRecoverType)
{
return (snapShotRecoverValue / static_cast<int32_t>(std::pow(DECIMAL_BASE,
static_cast<int32_t>(snapShotRecoverType)))) % DECIMAL_BASE;
}
bool Session::IsExitSplitOnBackgroundRecover()
{
return WindowHelper::IsSplitWindowMode(GetWindowMode()) ||
IsExitSplitOnBackground();
}
void Session::ResetLockedCacheSnapshot()
{
if (!SupportCacheLockedSessionSnapshot()) {
return;
}
if (snapshot_) {
ResetSnapshot();
}
}
bool Session::SupportCacheLockedSessionSnapshot() const
{
return systemConfig_.supportCacheLockedSessionSnapshot_;
}
void Session::SetFreeMultiWindow()
{
if (!SupportSnapshotAllSessionStatus()) {
return;
}
if (GetWindowMode() == WindowMode::WINDOW_MODE_FULLSCREEN) {
freeMultiWindow_.store(false);
} else {
freeMultiWindow_.store(true);
}
}
void Session::DeleteHasSnapshot() const
{
for (int32_t screenStatus = SCREEN_UNKNOWN; screenStatus < SCREEN_COUNT; screenStatus++) {
DeleteHasSnapshot(screenStatus);
}
DeleteHasSnapshotFreeMultiWindow();
}
void Session::DeleteHasSnapshot(SnapshotStatus key) const
{
auto hasSnapshot = ScenePersistentStorage::HasKey("Snapshot_" + sessionInfo_.bundleName_ +
"_" + std::to_string(persistentId_) + "_" + std::to_string(key), ScenePersistentStorageType::MAXIMIZE_STATE);
if (hasSnapshot) {
ScenePersistentStorage::Delete("Snapshot_" + sessionInfo_.bundleName_ + "_" + std::to_string(persistentId_) +
"_" + std::to_string(key), ScenePersistentStorageType::MAXIMIZE_STATE);
}
}
void Session::DeleteHasSnapshotFreeMultiWindow() const
{
auto hasSnapshotFreeMultiWindow = ScenePersistentStorage::HasKey("Snapshot_" + sessionInfo_.bundleName_ +
"_" + std::to_string(persistentId_), ScenePersistentStorageType::MAXIMIZE_STATE);
if (hasSnapshotFreeMultiWindow) {
ScenePersistentStorage::Delete("Snapshot_" + sessionInfo_.bundleName_ + "_" + std::to_string(persistentId_),
ScenePersistentStorageType::MAXIMIZE_STATE);
}
}
bool Session::HasSnapshot(SnapshotStatus key)
{
auto hasSnapshot = ScenePersistentStorage::HasKey("Snapshot_" + sessionInfo_.bundleName_ +
"_" + std::to_string(persistentId_) + "_" + std::to_string(key), ScenePersistentStorageType::MAXIMIZE_STATE);
if (hasSnapshot && scenePersistence_) {
scenePersistence_->SetHasSnapshot(true, key);
int32_t snapShotRecoverValue = 0;
ScenePersistentStorage::Get("Snapshot_" + sessionInfo_.bundleName_ +
"_" + std::to_string(persistentId_) + "_" + std::to_string(key),
snapShotRecoverValue, ScenePersistentStorageType::MAXIMIZE_STATE);
scenePersistence_->rotate_[key] = static_cast<DisplayOrientation>(DecodeSnapShotRecoverValue(
snapShotRecoverValue, SnapShotRecoverType::ROTATE));
bool isExitSplitOnBackgroundRecover = static_cast<bool>(DecodeSnapShotRecoverValue(
snapShotRecoverValue, SnapShotRecoverType::EXIT_SPLIT_ON_BACKGROUND));
SetExitSplitOnBackground(isExitSplitOnBackgroundRecover);
}
return hasSnapshot;
}
bool Session::HasSnapshotFreeMultiWindow()
{
auto hasSnapshotFreeMultiWindow = ScenePersistentStorage::HasKey("Snapshot_" + sessionInfo_.bundleName_ +
"_" + std::to_string(persistentId_), ScenePersistentStorageType::MAXIMIZE_STATE);
if (hasSnapshotFreeMultiWindow && scenePersistence_) {
freeMultiWindow_.store(true);
scenePersistence_->SetHasSnapshotFreeMultiWindow(true);
int32_t snapShotRecoverValue = 0;
ScenePersistentStorage::Get("Snapshot_" + sessionInfo_.bundleName_ +
"_" + std::to_string(persistentId_), snapShotRecoverValue, ScenePersistentStorageType::MAXIMIZE_STATE);
bool isExitSplitOnBackgroundRecover = static_cast<bool>(DecodeSnapShotRecoverValue(
snapShotRecoverValue, SnapShotRecoverType::EXIT_SPLIT_ON_BACKGROUND));
SetExitSplitOnBackground(isExitSplitOnBackgroundRecover);
}
return hasSnapshotFreeMultiWindow;
}
bool Session::HasPersistentSnapshot()
{
if (!scenePersistence_) {
return false;
}
return scenePersistence_->IsSavingSnapshot() || scenePersistence_->HasSnapshot();
}
bool Session::HasSnapshot()
{
HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "HasSnapshot[%d][%s]",
persistentId_, sessionInfo_.bundleName_.c_str());
bool hasSnapshot = false;
for (int32_t screenStatus = SCREEN_UNKNOWN; screenStatus < SCREEN_COUNT; screenStatus++) {
hasSnapshot |= HasSnapshot(screenStatus);
}
return hasSnapshot || HasSnapshotFreeMultiWindow();
}
void Session::InitSnapshotCapacity()
{
if (systemConfig_.supportSnapshotAllSessionStatus_) {
capacity_ = maxCapacity;
}
if (scenePersistence_) {
scenePersistence_->SetSnapshotCapacity(capacity_);
}
}
bool Session::SupportSnapshotAllSessionStatus() const
{
return (!IsPersistentImageFit() && (capacity_ != defaultCapacity));
}
SnapshotStatus Session::GetScreenSnapshotStatus() const
{
if (!SupportSnapshotAllSessionStatus()) {
return defaultStatus;
}
return WSSnapshotHelper::GetInstance()->GetScreenStatus();
}
SnapshotStatus Session::GetSessionSnapshotStatus(LifeCycleChangeReason reason) const
{
if (!SupportSnapshotAllSessionStatus()) {
return defaultStatus;
}
int32_t snapshotScreen;
if (state_ == SessionState::STATE_BACKGROUND || state_ == SessionState::STATE_DISCONNECT) {
snapshotScreen = lastSnapshotScreen_;
} else {
snapshotScreen = WSSnapshotHelper::GetInstance()->GetScreenStatus();
}
if (reason == LifeCycleChangeReason::EXPAND_TO_FOLD_SINGLE_POCKET) {
snapshotScreen = SCREEN_EXPAND;
}
return snapshotScreen;
}
uint32_t Session::GetWindowSnapshotOrientation() const
{
if (!SupportSnapshotAllSessionStatus()) {
return 0;
}
return WSSnapshotHelper::GetInstance()->GetWindowRotation();
}
uint32_t Session::GetLastOrientation() const
{
if (!SupportSnapshotAllSessionStatus()) {
return SNAPSHOT_PORTRAIT;
}
if (WSSnapshotHelper::GetInstance()->IsSnapshotNeedCorrect(WSSnapshotHelper::GetInstance()->GetScreenStatus())) {
return static_cast<uint32_t>(
WSSnapshotHelper::GetDisplayOrientation((currentRotation_ + ROTATION_90) % ROTATION_360));
}
if (FoldScreenStateInternel::IsSingleDisplayPocketFoldDevice() &&
WSSnapshotHelper::GetInstance()->GetScreenStatus() == SCREEN_FOLDED) {
return ROTATION_LANDSCAPE_INVERTED;
}
return static_cast<uint32_t>(WSSnapshotHelper::GetDisplayOrientation(currentRotation_));
}
void Session::SetSessionStateChangeListenser(const NotifySessionStateChangeFunc& func)
{
PostTask([weakThis = wptr(this), func]() {
auto session = weakThis.promote();
if (session == nullptr) {
WLOGFE("session is null");
return;
}
session->sessionStateChangeFunc_ = func;
auto changedState = session->GetSessionState();
if (changedState == SessionState::STATE_ACTIVE) {
changedState = SessionState::STATE_FOREGROUND;
} else if (changedState == SessionState::STATE_INACTIVE) {
changedState = SessionState::STATE_BACKGROUND;
} else if (changedState == SessionState::STATE_DISCONNECT) {
return;
}
session->NotifySessionStateChange(changedState);
TLOGNI(WmsLogTag::WMS_LIFE, "id: %{public}d, state_: %{public}d, changedState: %{public}d",
session->GetPersistentId(), session->GetSessionState(), changedState);
}, "SetSessionStateChangeListenser");
}
void Session::SetClearSubSessionCallback(const NotifyClearSubSessionFunc& func)
{
PostTask(
[weakThis = wptr(this), func, where = __func__]() {
auto session = weakThis.promote();
if (session == nullptr) {
TLOGNE(WmsLogTag::WMS_LIFE, "session is null");
return;
}
session->clearSubSessionFunc_ = std::move(func);
}, __func__);
}
bool Session::IsStatusBarVisible() const
{
if (WindowHelper::IsMainWindow(Session::GetWindowType())) {
return isStatusBarVisible_;
} else if (WindowHelper::IsSubWindow(Session::GetWindowType())) {
return GetMainSession() != nullptr ? GetMainSession()->isStatusBarVisible_ : false;
}
return false;
}
void Session::SetBufferAvailableChangeListener(const NotifyBufferAvailableChangeFunc& func)
{
bufferAvailableChangeFunc_ = func;
if (bufferAvailable_ && bufferAvailableChangeFunc_ != nullptr) {
bufferAvailableChangeFunc_(bufferAvailable_, false);
}
WLOGFD("SetBufferAvailableChangeListener, id: %{public}d", GetPersistentId());
}
void Session::SetGetRsCmdBlockingCountFunc(const GetRsCmdBlockingCountFunc& func)
{
getRsCmdBlockingCountFunc_ = func;
}
void Session::SetUpdateAppHookDisplayInfoFunc(const UpdateAppHookDisplayInfoFunc& func)
{
updateAppHookDisplayInfoFunc_ = func;
}
void Session::SetAcquireRotateAnimationConfigFunc(const AcquireRotateAnimationConfigFunc& func)
{
if (func == nullptr) {
TLOGI(WmsLogTag::DEFAULT, "func is nullptr");
return;
}
acquireRotateAnimationConfigFunc_ = func;
}
int32_t Session::GetRotateAnimationDuration()
{
if (acquireRotateAnimationConfigFunc_) {
RotateAnimationConfig rotateAnimationConfig;
acquireRotateAnimationConfigFunc_(rotateAnimationConfig);
return rotateAnimationConfig.duration_;
}
return ROTATE_ANIMATION_DURATION;
}
void Session::UnregisterSessionChangeListeners()
{
sessionStateChangeFunc_ = nullptr;
keyboardStateChangeFunc_ = nullptr;
sessionFocusableChangeFunc_ = nullptr;
sessionTouchableChangeFunc_ = nullptr;
clickFunc_ = nullptr;
jsSceneSessionExceptionFunc_ = nullptr;
sessionExceptionFunc_ = nullptr;
terminateSessionFunc_ = nullptr;
pendingSessionActivationFunc_ = nullptr;
changeSessionVisibilityWithStatusBarFunc_ = nullptr;
bufferAvailableChangeFunc_ = nullptr;
backPressedFunc_ = nullptr;
terminateSessionFuncNew_ = nullptr;
terminateSessionFuncTotal_ = nullptr;
updateSessionLabelFunc_ = nullptr;
updateSessionIconFunc_ = nullptr;
pendingSessionToForegroundFunc_ = nullptr;
pendingSessionToBackgroundForDelegatorFunc_ = nullptr;
raiseToTopForPointDownFunc_ = nullptr;
sessionInfoLockedStateChangeFunc_ = nullptr;
contextTransparentFunc_ = nullptr;
sessionRectChangeFunc_ = nullptr;
sessionWindowLimitsChangeFunc_ = nullptr;
updateSessionLabelAndIconFunc_ = nullptr;
frameLayoutFinishFunc_ = nullptr;
onRaiseMainWindowAboveTarget_ = nullptr;
callingSessionIdChangeFunc_ = nullptr;
WLOGFD("UnregisterSessionChangeListenser, id: %{public}d", GetPersistentId());
}
void Session::SetSessionStateChangeNotifyManagerListener(const NotifySessionStateChangeNotifyManagerFunc& func)
{
sessionStateChangeNotifyManagerFunc_ = func;
if (state_ == SessionState::STATE_DISCONNECT) {
return;
}
NotifySessionStateChange(state_);
}
void Session::SetSessionInfoChangeNotifyManagerListener(const NotifySessionInfoChangeNotifyManagerFunc& func)
{
sessionInfoChangeNotifyManagerFunc_ = func;
}
void Session::SetSessionPropertyChangeNotifyManagerListener(const NotifySessionPropertyChangeNotifyManagerFunc& func)
{
sessionPropertyChangeNotifyManagerFunc_ = func;
}
void Session::SetDisplayIdChangedNotifyManagerListener(const NotifyDisplayIdChangedNotifyManagerFunc& func)
{
displayIdChangedNotifyManagerFunc_ = func;
}
void Session::SetRequestFocusStatusNotifyManagerListener(const NotifyRequestFocusStatusNotifyManagerFunc& func)
{
requestFocusStatusNotifyManagerFunc_ = func;
}
void Session::SetNotifyUIRequestFocusFunc(const NotifyUIRequestFocusFunc& func)
{
std::unique_lock<std::shared_mutex> lock(uiRequestFocusMutex_);
requestFocusFunc_ = func;
}
void Session::SetNotifyUILostFocusFunc(const NotifyUILostFocusFunc& func)
{
std::unique_lock<std::shared_mutex> lock(uiLostFocusMutex_);
lostFocusFunc_ = func;
}
void Session::SetGetStateFromManagerListener(const GetStateFromManagerFunc& func)
{
getStateFromManagerFunc_ = func;
}
void Session::NotifySessionStateChange(const SessionState& state)
{
PostTask([weakThis = wptr(this), state]() {
auto session = weakThis.promote();
if (session == nullptr) {
WLOGFE("session is null");
return;
}
TLOGND(WmsLogTag::WMS_LIFE, "NotifySessionStateChange, [state: %{public}u, persistent: %{public}d]",
static_cast<uint32_t>(state), session->GetPersistentId());
if (session->GetWindowType() == WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT &&
session->keyboardStateChangeFunc_) {
const sptr<WindowSessionProperty>& property = session->GetSessionProperty();
session->keyboardStateChangeFunc_(
state, property->GetKeyboardEffectOption(), property->GetCallingSessionId(),
property->GetKeyboardTargetDisplayId());
} else if (session->sessionStateChangeFunc_) {
session->sessionStateChangeFunc_(state);
} else {
TLOGND(WmsLogTag::WMS_LIFE, "sessionStateChangeFunc is null");
}
if (!session->sessionStateChangeFunc_ && state == SessionState::STATE_DISCONNECT) {
auto parentSession = session->GetParentSession();
if (parentSession && parentSession->clearSubSessionFunc_) {
parentSession->clearSubSessionFunc_(session->GetPersistentId());
TLOGNI(WmsLogTag::WMS_LIFE, "notify clear subSession, parentId: %{public}d, "
"persistentId: %{public}d", parentSession->GetPersistentId(), session->GetPersistentId());
}
}
if (session->sessionStateChangeNotifyManagerFunc_) {
session->sessionStateChangeNotifyManagerFunc_(session->GetPersistentId(), state);
} else {
TLOGND(WmsLogTag::WMS_LIFE, "sessionStateChangeNotifyManagerFunc is null");
}
}, "NotifySessionStateChange");
}
void Session::SetSessionFocusableChangeListener(const NotifySessionFocusableChangeFunc& func)
{
sessionFocusableChangeFunc_ = func;
NotifySessionFocusableChange(GetFocusable());
}
bool Session::GetSkipSelfWhenShowOnVirtualScreen() const
{
return GetSessionProperty()->GetSkipSelfWhenShowOnVirtualScreen();
}
void Session::SetSessionTouchableChangeListener(const NotifySessionTouchableChangeFunc& func)
{
sessionTouchableChangeFunc_ = func;
sessionTouchableChangeFunc_(GetTouchable());
}
void Session::SetClickListener(const NotifyClickFunc& func)
{
clickFunc_ = func;
}
void Session::NotifySessionFocusableChange(bool isFocusable)
{
TLOGI(WmsLogTag::WMS_FOCUS, "id: %{public}d, focusable: %{public}u", GetPersistentId(), isFocusable);
if (sessionFocusableChangeFunc_) {
sessionFocusableChangeFunc_(isFocusable);
}
}
void Session::NotifySessionTouchableChange(bool touchable)
{
WLOGFD("Notify session touchable change: %{public}d", touchable);
if (sessionTouchableChangeFunc_) {
sessionTouchableChangeFunc_(touchable);
}
}
void Session::NotifyClick(bool requestFocus, bool isClick)
{
TLOGD(WmsLogTag::WMS_FOCUS, "id: %{public}d, focus: %{public}u, isClick: %{public}u",
GetPersistentId(), requestFocus, isClick);
if (IsLoosenedWithFreeMultiMode()) {
TLOGD(WmsLogTag::WMS_FOCUS, "raise sub window id: %{public}d", GetPersistentId());
RaiseToAppTopForPointDown();
return;
}
if (clickFunc_) {
clickFunc_(requestFocus, isClick);
}
}
void Session::NotifyRequestFocusStatusNotifyManager(bool isFocused, bool byForeground, FocusChangeReason reason)
{
TLOGD(WmsLogTag::WMS_FOCUS, "NotifyRequestFocusStatusNotifyManager id: %{public}d, focused: %{public}d,\
reason: %{public}d", GetPersistentId(), isFocused, reason);
if (requestFocusStatusNotifyManagerFunc_) {
requestFocusStatusNotifyManagerFunc_(GetPersistentId(), isFocused, byForeground, reason);
}
}
bool Session::GetStateFromManager(const ManagerState key)
{
if (getStateFromManagerFunc_) {
return getStateFromManagerFunc_(key);
}
switch (key) {
case ManagerState::MANAGER_STATE_SCREEN_LOCKED:
return false;
break;
default:
return false;
}
}
void Session::NotifyUIRequestFocus()
{
WLOGFD("NotifyUIRequestFocus id: %{public}d", GetPersistentId());
std::shared_lock<std::shared_mutex> lock(uiRequestFocusMutex_);
if (requestFocusFunc_) {
requestFocusFunc_();
}
}
void Session::NotifyUILostFocus()
{
WLOGFD("NotifyUILostFocus id: %{public}d", GetPersistentId());
std::shared_lock<std::shared_mutex> lock(uiLostFocusMutex_);
if (lostFocusFunc_) {
lostFocusFunc_();
}
}
void Session::PresentFocusIfNeed(int32_t pointerAction, int32_t sourceType)
{
TLOGD(WmsLogTag::WMS_FOCUS, "OnClick down, id: %{public}d", GetPersistentId());
bool isHoverDown = pointerAction == MMI::PointerEvent::POINTER_ACTION_HOVER_ENTER &&
sourceType == MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN;
if (pointerAction == MMI::PointerEvent::POINTER_ACTION_DOWN ||
pointerAction == MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN ||
isHoverDown) {
if (!isFocused_ && GetFocusable()) {
FocusChangeReason reason = FocusChangeReason::CLICK;
NotifyRequestFocusStatusNotifyManager(true, false, reason);
}
NotifyClickIfNeed();
}
}
bool Session::IsNeedRequestToTop() const
{
if (WindowHelper::IsMainWindow(GetWindowType()) || WindowHelper::IsSubWindow(GetWindowType())) {
auto property = GetSessionProperty();
if (property == nullptr) {
TLOGE(WmsLogTag::WMS_FOCUS, "id: %{public}d property is nullptr", persistentId_);
return false;
}
return property->GetRaiseEnabled();
}
return true;
}
void Session::NotifyClickIfNeed()
{
if (IsNeedRequestToTop()) {
NotifyClick(false);
} else {
TLOGI(WmsLogTag::WMS_FOCUS, "do not need to request to top");
}
}
WSError Session::UpdateFocus(bool isFocused)
{
if (isFocused_ == isFocused) {
TLOGD(WmsLogTag::WMS_FOCUS, "Session focus do not change");
return WSError::WS_DO_NOTHING;
}
isFocused_ = isFocused;
UpdateGestureBackEnabled();
if (!isFocused) {
NotifyUILostFocus();
}
return WSError::WS_OK;
}
WSError Session::NotifyFocusStatus(const sptr<FocusNotifyInfo>& focusNotifyInfo, bool isFocused)
{
if (!IsSessionValid()) {
TLOGD(WmsLogTag::WMS_FOCUS, "Session is invalid, id: %{public}d state: %{public}u",
GetPersistentId(), GetSessionState());
return WSError::WS_ERROR_INVALID_SESSION;
}
if (!sessionStage_) {
TLOGD(WmsLogTag::WMS_FOCUS, "Session Stage is invalid, id: %{public}d state: %{public}u",
GetPersistentId(), GetSessionState());
return WSError::WS_ERROR_NULLPTR;
}
NotifyCrossProcessChildrenLifecycle(isFocused ? ParentLifeCycleEvent::ACTIVE : ParentLifeCycleEvent::INACTIVE);
sessionStage_->UpdateFocus(focusNotifyInfo, isFocused);
return WSError::WS_OK;
}
WSError Session::RequestFocus(bool isFocused)
{
if (!SessionPermission::IsSystemCalling()) {
TLOGE(WmsLogTag::WMS_FOCUS, "permission denied!");
return WSError::WS_ERROR_NOT_SYSTEM_APP;
}
FocusChangeReason reason = FocusChangeReason::CLIENT_REQUEST;
NotifyRequestFocusStatusNotifyManager(isFocused, false, reason);
return WSError::WS_OK;
}
void Session::SetExclusivelyHighlighted(bool isExclusivelyHighlighted)
{
auto property = GetSessionProperty();
if (property == nullptr) {
TLOGE(WmsLogTag::WMS_FOCUS, "property is nullptr, windowId: %{public}d", persistentId_);
return;
}
if (isExclusivelyHighlighted == property->GetExclusivelyHighlighted()) {
return;
}
TLOGI(WmsLogTag::WMS_FOCUS, "windowId: %{public}d, isExclusivelyHighlighted: %{public}d", persistentId_,
isExclusivelyHighlighted);
property->SetExclusivelyHighlighted(isExclusivelyHighlighted);
}
WSError Session::UpdateHighlightStatus(const sptr<HighlightNotifyInfo>& highlightNotifyInfo, bool isHighlight,
bool needBlockHighlightNotify)
{
TLOGD(WmsLogTag::WMS_FOCUS,
"windowId: %{public}d, currHighlight: %{public}d, nextHighlight: %{public}d, needBlockNotify:%{public}d",
persistentId_, isHighlighted_.load(), isHighlight, needBlockHighlightNotify);
if (isHighlighted_ == isHighlight) {
return WSError::WS_DO_NOTHING;
}
isHighlighted_ = isHighlight;
if (!needBlockHighlightNotify) {
NotifyHighlightChange(highlightNotifyInfo, isHighlight);
}
std::lock_guard lock(highlightChangeFuncMutex_);
if (highlightChangeFunc_ != nullptr) {
highlightChangeFunc_(isHighlight);
}
return WSError::WS_OK;
}
WSError Session::NotifyHighlightChange(const sptr<HighlightNotifyInfo>& highlightNotifyInfo, bool isHighlight)
{
if (IsSystemSession()) {
TLOGW(WmsLogTag::WMS_FOCUS, "Invalid [%{public}d, %{public}u]", persistentId_, GetSessionState());
return WSError::WS_ERROR_INVALID_SESSION;
}
if (!sessionStage_) {
TLOGE(WmsLogTag::WMS_FOCUS, "sessionStage is null");
return WSError::WS_ERROR_NULLPTR;
}
sessionStage_->NotifyHighlightChange(highlightNotifyInfo, isHighlight);
return WSError::WS_OK;
}
WSError Session::GetIsHighlighted(bool& isHighlighted)
{
isHighlighted = isHighlighted_;
TLOGD(WmsLogTag::WMS_FOCUS, "windowId: %{public}d, isHighlighted: %{public}d",
GetPersistentId(), isHighlighted_.load());
return WSError::WS_OK;
}
WSError Session::SetAppSupportPhoneInPc(bool isSupportPhone)
{
TLOGI(WmsLogTag::WMS_COMPAT, "isSupportPhone: %{public}d", isSupportPhone);
auto property = GetSessionProperty();
if (property == nullptr) {
TLOGE(WmsLogTag::WMS_COMPAT, "id: %{public}d property is nullptr", persistentId_);
return WSError::WS_ERROR_NULLPTR;
}
property->SetIsAppSupportPhoneInPc(isSupportPhone);
return WSError::WS_OK;
}
WSError Session::SetCompatibleModeProperty(const sptr<CompatibleModeProperty> compatibleModeProperty)
{
auto property = GetSessionProperty();
if (property == nullptr) {
TLOGE(WmsLogTag::WMS_COMPAT, "id: %{public}d property is nullptr", persistentId_);
return WSError::WS_ERROR_NULLPTR;
}
property->SetCompatibleModeProperty(compatibleModeProperty);
if (compatibleModeProperty && compatibleModeProperty->IsDragResizeDisabled()) {
property->SetDragEnabled(false);
}
PostSyncTask(
[weakThis = wptr(this), weakProperty = wptr(compatibleModeProperty)] {
auto session = weakThis.promote();
auto property = weakProperty.promote();
if (!session || !session->sessionStage_ || !property) {
TLOGNE(WmsLogTag::WMS_COMPAT, "session, sessionStage or property is null");
return WSError::WS_ERROR_INVALID_SESSION;
}
session->sessionStage_->NotifyCompatibleModePropertyChange(property);
return WSError::WS_OK;
}, __func__);
return WSError::WS_OK;
}
WSError Session::SetIsPcAppInPad(bool enable)
{
TLOGI(WmsLogTag::WMS_COMPAT, "enable: %{public}d", enable);
auto property = GetSessionProperty();
if (property == nullptr) {
TLOGE(WmsLogTag::WMS_COMPAT, "id: %{public}d property is nullptr", persistentId_);
return WSError::WS_ERROR_NULLPTR;
}
property->SetIsPcAppInPad(enable);
return WSError::WS_OK;
}
WSError Session::SetPcAppInpadCompatibleMode(bool enabled)
{
TLOGD(WmsLogTag::WMS_COMPAT, "isPcAppInpadCompatibleMode: %{public}d", enabled);
GetSessionProperty()->SetPcAppInpadCompatibleMode(enabled);
return WSError::WS_OK;
}
WSError Session::SetPcAppInpadSpecificSystemBarInvisible(bool isPcAppInpadSpecificSystemBarInvisible)
{
TLOGD(WmsLogTag::WMS_COMPAT, "isPcAppInpadSpecificSystemBarInvisible: %{public}d",
isPcAppInpadSpecificSystemBarInvisible);
GetSessionProperty()->SetPcAppInpadSpecificSystemBarInvisible(isPcAppInpadSpecificSystemBarInvisible);
return WSError::WS_OK;
}
WSError Session::SetPcAppInpadOrientationLandscape(bool isPcAppInpadOrientationLandscape)
{
TLOGD(WmsLogTag::WMS_COMPAT, "isPcAppInpadOrientationLandscape: %{public}d",
isPcAppInpadOrientationLandscape);
GetSessionProperty()->SetPcAppInpadOrientationLandscape(isPcAppInpadOrientationLandscape);
return WSError::WS_OK;
}
WSError Session::SetMobileAppInPadLayoutFullScreen(bool isMobileAppInPadLayoutFullScreen)
{
TLOGD(WmsLogTag::WMS_COMPAT, "isMobileAppInPadLayoutFullScreen: %{public}d",
isMobileAppInPadLayoutFullScreen);
GetSessionProperty()->SetMobileAppInPadLayoutFullScreen(isMobileAppInPadLayoutFullScreen);
return WSError::WS_OK;
}
WSError Session::PcAppInPadNormalClose()
{
TLOGD(WmsLogTag::WMS_COMPAT, "windowId:%{public}d", GetPersistentId());
if (!IsSessionValid()) {
TLOGD(WmsLogTag::WMS_COMPAT, "Session is invalid, id: %{public}d state: %{public}u",
GetPersistentId(), GetSessionState());
return WSError::WS_ERROR_INVALID_SESSION;
}
if (sessionStage_ == nullptr) {
TLOGE(WmsLogTag::WMS_COMPAT, "session stage is nullptr id: %{public}d state: %{public}u",
GetPersistentId(), GetSessionState());
return WSError::WS_ERROR_NULLPTR;
}
return sessionStage_->PcAppInPadNormalClose();
}
void Session::SetHasRequestedVsyncFunc(HasRequestedVsyncFunc&& func)
{
if (!func) {
TLOGW(WmsLogTag::WMS_LAYOUT, "id:%{public}d, func is null", GetPersistentId());
return;
}
hasRequestedVsyncFunc_ = std::move(func);
}
void Session::SetRequestNextVsyncWhenModeChangeFunc(RequestNextVsyncWhenModeChangeFunc&& func)
{
if (!func) {
TLOGW(WmsLogTag::WMS_LAYOUT, "id:%{public}d, func is null", GetPersistentId());
return;
}
requestNextVsyncWhenModeChangeFunc_ = std::move(func);
}
WSError Session::RequestNextVsyncWhenModeChange()
{
if (!hasRequestedVsyncFunc_) {
TLOGW(WmsLogTag::WMS_LAYOUT,
"[WindowModeUpdate:VsyncWait] skip: hasRequestedVsyncFunc is null, id:%{public}d", GetPersistentId());
return WSError::WS_ERROR_NULLPTR;
}
isWindowModeDirty_.store(true);
bool hasRequestedVsync = false;
hasRequestedVsyncFunc_(hasRequestedVsync);
timesToWaitForVsync_.store(hasRequestedVsync ? TIMES_TO_WAIT_FOR_VSYNC_TWICE : TIMES_TO_WAIT_FOR_VSYNC_ONECE);
TLOGI(WmsLogTag::WMS_LAYOUT,
"[WindowModeUpdate:VsyncWait] start waiting, id:%{public}d, hasRequestedVsync:%{public}d, "
"waitTimes:%{public}d", GetPersistentId(), hasRequestedVsync, timesToWaitForVsync_.load());
InitVsyncCallbackForModeChangeAndRequestNextVsync();
return WSError::WS_OK;
}
void Session::OnVsyncReceivedAfterModeChanged()
{
const char* const funcName = __func__;
PostTask([weakThis = wptr(this), funcName] {
auto session = weakThis.promote();
if (!session) {
TLOGNE(WmsLogTag::WMS_LAYOUT, "%{public}s: session is null", funcName);
return;
}
if (!session->isWindowModeDirty_.load()) {
TLOGND(WmsLogTag::WMS_LAYOUT,
"[WindowModeUpdate:VsyncWait] %{public}s: not dirty, skip, id:%{public}d",
funcName, session->GetPersistentId());
return;
}
session->timesToWaitForVsync_.fetch_sub(1);
TLOGI(WmsLogTag::WMS_LAYOUT,
"[WindowModeUpdate:VsyncWait] %{public}s: id:%{public}d, mode:%{public}d, waitTimes:%{public}d",
funcName, session->GetPersistentId(), static_cast<int32_t>(session->GetWindowMode()),
session->timesToWaitForVsync_.load());
bool isWindowModeDirty = true;
if (session->timesToWaitForVsync_.load() > 0) {
session->InitVsyncCallbackForModeChangeAndRequestNextVsync();
} else if (session->timesToWaitForVsync_.load() < 0) {
TLOGNW(WmsLogTag::WMS_LAYOUT,
"[WindowModeUpdate:VsyncWait] %{public}s: abnormal waitTimes, id:%{public}d, waitTimes:%{public}d",
funcName, session->GetPersistentId(), session->timesToWaitForVsync_.load());
session->timesToWaitForVsync_.store(0);
session->isWindowModeDirty_.store(false);
} else if (session->timesToWaitForVsync_.load() == 0 && session->sessionStage_ &&
session->isWindowModeDirty_.compare_exchange_strong(isWindowModeDirty, false)) {
TLOGI(WmsLogTag::WMS_LAYOUT,
"[WindowModeUpdate:VsyncWait] %{public}s: layout done, notify client, id:%{public}d, mode:%{public}d",
funcName, session->GetPersistentId(), static_cast<int32_t>(session->GetWindowMode()));
session->sessionStage_->NotifyLayoutFinishAfterWindowModeChange(session->GetWindowMode());
session->NotifySubSessionParentStatusChange(session->GetWindowMode());
} else {
TLOGD(WmsLogTag::WMS_LAYOUT,
"[WindowModeUpdate:VsyncWait] %{public}s: skip: stage null or not dirty, id:%{public}d",
funcName, session->GetPersistentId());
session->isWindowModeDirty_.store(false);
}
}, funcName);
}
void Session::InitVsyncCallbackForModeChangeAndRequestNextVsync()
{
if (!requestNextVsyncWhenModeChangeFunc_) {
TLOGW(WmsLogTag::WMS_LAYOUT, "id:%{public}d, func is null", GetPersistentId());
return;
}
std::shared_ptr<VsyncCallback> nextVsyncCallback = std::make_shared<VsyncCallback>();
nextVsyncCallback->onCallback = [weakThis = wptr(this), funcName = __func__](int64_t, int64_t) {
auto session = weakThis.promote();
if (!session) {
TLOGNE(WmsLogTag::WMS_LAYOUT, "%{public}s: session is null", funcName);
return;
}
session->OnVsyncReceivedAfterModeChanged();
};
requestNextVsyncWhenModeChangeFunc_(nextVsyncCallback);
}
WSError Session::UpdateWindowMode(const WindowModeInfo& windowModeInfo)
{
WindowMode mode = windowModeInfo.windowMode;
auto preMode = GetWindowMode();
TLOGI(WmsLogTag::WMS_LAYOUT,
"[WindowModeUpdate:ServerRecv] id:%{public}d, preMode:%{public}d, mode:%{public}d, "
"splitStyle:%{public}d, splitIndex:%{public}d",
GetPersistentId(), static_cast<int32_t>(preMode), static_cast<int32_t>(mode),
static_cast<int32_t>(windowModeInfo.splitStyle), windowModeInfo.splitIndex);
auto property = GetSessionProperty();
if (property == nullptr) {
TLOGE(WmsLogTag::WMS_LAYOUT,
"[WindowModeUpdate:ServerRecv] skip: property is null, id:%{public}d", GetPersistentId());
return WSError::WS_ERROR_NULLPTR;
}
if (state_ == SessionState::STATE_END) {
TLOGW(WmsLogTag::WMS_LAYOUT,
"[WindowModeUpdate:ServerRecv] skip: session destroyed, id:%{public}d, state:%{public}u",
GetPersistentId(), static_cast<uint32_t>(GetSessionState()));
return WSError::WS_ERROR_INVALID_SESSION;
} else if (state_ == SessionState::STATE_DISCONNECT) {
TLOGI(WmsLogTag::WMS_LAYOUT,
"[WindowModeUpdate:ServerRecv] state=DISCONNECT, pending update, id:%{public}d, mode:%{public}d",
GetPersistentId(), static_cast<int32_t>(mode));
property->SetWindowModeInfo(windowModeInfo);
NotifySessionPropertyChange(WindowInfoKey::WINDOW_MODE);
NotifySessionPropertyChange(WindowInfoKey::WINDOW_MODE_INFO);
property->SetIsNeedUpdateWindowMode(true);
UpdateGestureBackEnabled();
} else {
property->SetWindowModeInfo(windowModeInfo);
NotifySessionPropertyChange(WindowInfoKey::WINDOW_MODE);
NotifySessionPropertyChange(WindowInfoKey::WINDOW_MODE_INFO);
RequestNextVsyncWhenModeChange();
if (WindowHelper::IsSplitWindowMode(mode)) {
property->SetMaximizeMode(MaximizeMode::MODE_RECOVER);
}
UpdateGestureBackEnabled();
UpdateGravityWhenUpdateWindowMode(windowModeInfo);
if (!sessionStage_) {
TLOGE(WmsLogTag::WMS_LAYOUT,
"[WindowModeUpdate:ServerRecv] skip: sessionStage is null, id:%{public}d", GetPersistentId());
return WSError::WS_ERROR_NULLPTR;
}
TLOGI(WmsLogTag::WMS_LAYOUT,
"[WindowModeUpdate:ServerRecv] send to client, id:%{public}d, mode:%{public}d",
GetPersistentId(), static_cast<int32_t>(mode));
return sessionStage_->UpdateWindowMode(windowModeInfo);
}
return WSError::WS_OK;
}
void Session::UpdateGravityWhenUpdateWindowMode(const WindowModeInfo& windowModeInfo)
{
WindowMode mode = windowModeInfo.windowMode;
auto surfaceNode = GetSurfaceNode();
if ((systemConfig_.IsPcWindow() || systemConfig_.IsFreeMultiWindowMode()) && surfaceNode != nullptr) {
if (mode == WindowMode::WINDOW_MODE_SPLIT_PRIMARY) {
surfaceNode->SetFrameGravity(Gravity::LEFT);
} else if (mode == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) {
surfaceNode->SetFrameGravity(Gravity::RIGHT);
} else if (mode == WindowMode::WINDOW_MODE_FLOATING || mode == WindowMode::WINDOW_MODE_FULLSCREEN) {
surfaceNode->SetFrameGravity(Gravity::RESIZE);
} else if (mode == WindowMode::WINDOW_MODE_SPLIT) {
surfaceNode->SetFrameGravity(Gravity::LEFT);
}
}
}
WSError Session::SetSystemSceneBlockingFocus(bool blocking)
{
TLOGW(WmsLogTag::WMS_FOCUS, "Session set blocking focus, id: %{public}d, mode: %{public}d, Session is not system.",
GetPersistentId(), blocking);
return WSError::WS_ERROR_INVALID_SESSION;
}
bool Session::GetBlockingFocus() const
{
return blockingFocus_;
}
WSError Session::SetSessionProperty(const sptr<WindowSessionProperty>& property)
{
property_->CopyFrom(property);
NotifySessionInfoChange();
return WSError::WS_OK;
}
WSError Session::SetSessionPropertyForReconnect(const sptr<WindowSessionProperty>& property)
{
property_->CopyFrom(property);
auto hotAreasChangeCallback = [weakThis = wptr(this)]() {
auto session = weakThis.promote();
if (session == nullptr) {
TLOGNE(WmsLogTag::WMS_EVENT, "session is nullptr");
return;
}
session->NotifySessionInfoChange();
};
property_->SetSessionPropertyChangeCallback(hotAreasChangeCallback);
NotifySessionInfoChange();
return WSError::WS_OK;
}
void Session::RectSizeCheckProcess(float curWidth, float curHeight, uint32_t minWidth,
uint32_t minHeight, const ScreenMetrics& screenMetrics)
{
constexpr uint32_t MARGIN_OF_ERROR = 2;
constexpr float DEFAULT_DENSITY = 1.0f;
const auto& systemConfig = GetSystemConfig();
const uint32_t maxFloatingWindowSize = systemConfig.maxFloatingWindowSize_;
const bool isSizeBelowMin = (curWidth + MARGIN_OF_ERROR < minWidth) ||
(curHeight + MARGIN_OF_ERROR < minHeight);
const bool isSizeAboveMax = (curWidth > maxFloatingWindowSize + MARGIN_OF_ERROR) ||
(curHeight > maxFloatingWindowSize + MARGIN_OF_ERROR);
const WindowType winType = GetWindowType();
const bool isSystemWindowButNotDialog = WindowHelper::IsSystemWindowButNotDialog(winType);
const uint32_t screenWidth = screenMetrics.widthPx;
const uint32_t screenHeight = screenMetrics.heightPx;
const float density = screenMetrics.density;
const float safeDensity = (!NearZero(density)) ? density : DEFAULT_DENSITY;
const float screenWidthVp = screenWidth / safeDensity;
const float screenHeightVp = screenHeight / safeDensity;
const bool isSizeBelowScreen = (curWidth + MARGIN_OF_ERROR < screenWidthVp) ||
(curHeight + MARGIN_OF_ERROR < screenHeightVp);
const bool needReportException = isSizeAboveMax ||
(!isSystemWindowButNotDialog && isSizeBelowMin && isSizeBelowScreen);
TLOGD(WmsLogTag::WMS_LAYOUT, "RectCheck sessionID: %{public}d rect %{public}s isReportException %{public}d",
GetPersistentId(), GetSessionRect().ToString().c_str(), needReportException);
if (needReportException) {
TLOGE(WmsLogTag::WMS_LAYOUT, "RectCheck err sessionID: %{public}d rect %{public}s",
GetPersistentId(), GetSessionRect().ToString().c_str());
std::ostringstream oss;
oss << " RectCheck err size ";
oss << " cur persistentId: " << GetPersistentId() << ",";
oss << " windowType: " << static_cast<uint32_t>(winType) << ",";
auto property = GetSessionProperty();
if (property) {
oss << " windowName: " << property->GetWindowName() << ",";
oss << " windowState: " << static_cast<uint32_t>(property->GetWindowState()) << ",";
}
oss << " curWidth: " << curWidth << ",";
oss << " curHeight: " << curHeight << ",";
oss << " minWidth: " << minWidth << ",";
oss << " minHeight: " << minHeight << ",";
oss << " screenWidth: " << screenWidth << ",";
oss << " screenHeight: " << screenHeight << ",";
oss << " maxFloatingWindowSize: " << maxFloatingWindowSize << ",";
oss << " sessionRect: " << GetSessionRect().ToString() << ";";
WindowInfoReporter::GetInstance().ReportWindowFrozen(WindowDFXHelperType::WINDOW_RECT_CHECK, oss.str());
}
}
void Session::RectCheckProcess()
{
if (!(IsLifecycleForeground() || isVisible_.load())) {
return;
}
auto property = GetSessionProperty();
if (!property) {
TLOGE(WmsLogTag::WMS_LAYOUT, "property is null");
return;
}
auto displayId = property->GetDisplayId();
std::map<ScreenId, ScreenProperty> screensProperties =
Rosen::ScreenSessionManagerClient::GetInstance().GetAllScreensProperties();
if (screensProperties.find(displayId) == screensProperties.end()) {
return;
}
auto screenProperty = screensProperties[displayId];
float density = screenProperty.GetDensity();
ScreenMetrics screenMetrics{
.widthPx = static_cast<uint32_t>(screenProperty.GetBounds().rect_.width_),
.heightPx = static_cast<uint32_t>(screenProperty.GetBounds().rect_.height_),
.density = screenProperty.GetDensity()};
if (!NearZero(density) && !NearZero(GetSessionRect().height_)) {
float curWidth = GetSessionRect().width_ / density;
float curHeight = GetSessionRect().height_ / density;
float ratio = GetAspectRatio();
float actRatio = curWidth / curHeight;
if (!NearZero(ratio) && !NearEqual(ratio, actRatio)) {
TLOGE(WmsLogTag::WMS_LAYOUT, "RectCheck err ratio %{public}f != actRatio: %{public}f", ratio, actRatio);
std::ostringstream oss;
oss << " RectCheck err ratio ";
oss << " cur persistentId: " << GetPersistentId() << ",";
oss << " windowType: " << static_cast<uint32_t>(GetWindowType()) << ",";
oss << " windowName: " << property->GetWindowName() << ",";
oss << " windowState: " << static_cast<uint32_t>(property->GetWindowState()) << ",";
oss << " curWidth: " << curWidth << ",";
oss << " curHeight: " << curHeight << ",";
oss << " setting ratio: " << ratio << ",";
oss << " sessionRect: " << GetSessionRect().ToString() << ";";
WindowInfoReporter::GetInstance().ReportWindowException(
static_cast<int32_t>(WindowDFXHelperType::WINDOW_RECT_CHECK), getpid(), oss.str());
}
RectCheck(curWidth, curHeight, screenMetrics);
}
}
void Session::SetSessionRect(const WSRect& rect)
{
if (GetSessionRect() == rect) {
TLOGW(WmsLogTag::WMS_LAYOUT, "id: %{public}d skip same rect", persistentId_);
return;
}
layoutController_->SetSessionRect(rect);
dirtyFlags_ |= static_cast<uint32_t>(SessionUIDirtyFlag::RECT);
RectCheckProcess();
}
void Session::SetLastClientParentSize(const WSRect& rect)
{
if (GetLastClientParentSize() == rect) {
TLOGI(WmsLogTag::WMS_LAYOUT, "id: %{public}d skip same rect", persistentId_);
return;
}
layoutController_->SetLastClientParentSize(rect);
}
WSRect Session::GetSessionRect() const
{
return layoutController_->GetSessionRect();
}
WSRect Session::GetLastClientParentSize() const
{
return layoutController_->GetLastClientParentSize();
}
WSRect Session::GetSessionScreenRelativeRect() const
{
if (GetSizeChangeReason() == SizeChangeReason::DRAG_MOVE) {
return GetLayoutController()->ConvertGlobalRectToRelative(GetSessionRect(), GetDisplayId());
}
return GetSessionRect();
}
WMError Session::GetGlobalScaledRect(Rect& globalScaledRect)
{
auto task = [weakThis = wptr(this), &globalScaledRect] {
auto session = weakThis.promote();
if (!session) {
TLOGNE(WmsLogTag::WMS_LAYOUT, "session is null");
return WMError::WM_ERROR_DESTROYED_OBJECT;
}
session->GetLayoutController()->GetGlobalScaledRect(globalScaledRect);
TLOGND(WmsLogTag::WMS_LAYOUT, "Id:%{public}d globalScaledRect:%{public}s",
session->GetPersistentId(), globalScaledRect.ToString().c_str());
return WMError::WM_OK;
};
return PostSyncTask(task, __func__);
}
WSRect Session::GetSessionGlobalRect() const
{
return layoutController_->GetSessionGlobalRect();
}
WSRect Session::GetSessionGlobalRectInMultiScreen() const
{
if (IsDragMoving()) {
return GetLayoutController()->ConvertGlobalRectToRelative(GetSessionRect(), GetDisplayId());
}
return GetSessionGlobalRect();
}
void Session::SetSessionGlobalRect(const WSRect& rect)
{
if (layoutController_->SetSessionGlobalRect(rect)) {
dirtyFlags_ |= static_cast<uint32_t>(SessionUIDirtyFlag::GLOBAL_RECT);
AddPropertyDirtyFlags(static_cast<uint32_t>(SessionPropertyFlag::WINDOW_GLOBAL_RECT));
}
}
WSRect Session::GetLastLayoutRect() const
{
return lastLayoutRect_;
}
WSRect Session::GetLayoutRect() const
{
return layoutRect_;
}
void Session::SetSessionRequestRect(const WSRect& rect)
{
auto property = GetSessionProperty();
if (property == nullptr) {
WLOGFD("id: %{public}d property is nullptr", persistentId_);
return;
}
property->SetRequestRect(SessionHelper::TransferToRect(rect));
WLOGFD("is: %{public}d, rect: [%{public}d, %{public}d, %{public}u, %{public}u]", persistentId_,
rect.posX_, rect.posY_, rect.width_, rect.height_);
}
WSRect Session::GetSessionRequestRect() const
{
WSRect rect;
auto property = GetSessionProperty();
if (property == nullptr) {
WLOGFD("id: %{public}d property is nullptr", persistentId_);
return rect;
}
rect = SessionHelper::TransferToWSRect(property->GetRequestRect());
WLOGFD("id: %{public}d, rect: %{public}s", persistentId_, rect.ToString().c_str());
return rect;
}
void Session::SetLayerPartRender(bool isLayerPartRender)
{
HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "SetLayerPartRender id[%d] flag[%d]",
persistentId_, isLayerPartRender);
isLayerPartRender_ = isLayerPartRender;
TLOGI(WmsLogTag::WMS_PATTERN, "id: %{public}d, flag: %{public}d", persistentId_, isLayerPartRender);
auto surfaceNode = GetSurfaceNode();
if (surfaceNode != nullptr) {
surfaceNode->MarkLayerPartRender(isLayerPartRender_);
} else {
TLOGE(WmsLogTag::WMS_PATTERN, "id: %{public}d, surfaceNode nullptr", persistentId_);
}
}
bool Session::GetLayerPartRender() const
{
return isLayerPartRender_;
}
void Session::SetClientRect(const WSRect& rect)
{
layoutController_->SetClientRect(rect);
}
WSRect Session::GetClientRect() const
{
return layoutController_->GetClientRect();
}
void Session::SetHidingStartingWindow(bool hidingStartWindow)
{
hidingStartWindow_ = hidingStartWindow;
}
bool Session::GetHidingStartingWindow() const
{
return hidingStartWindow_;
}
void Session::SetRestartApp(bool restartApp)
{
sessionInfo_.isRestartApp_ = restartApp;
}
bool Session::GetRestartApp() const
{
return sessionInfo_.isRestartApp_;
}
void Session::SetRestartInSameProcess(bool restartInSameProcess)
{
sessionInfo_.isRestartInSameProcess_ = restartInSameProcess;
}
bool Session::GetRestartInSameProcess() const
{
return sessionInfo_.isRestartInSameProcess_;
}
void Session::SetRestartCallerPersistentId(int32_t restartCallerPersistentId)
{
sessionInfo_.restartCallerPersistentId_ = restartCallerPersistentId;
}
int32_t Session::GetRestartCallerPersistentId() const
{
return sessionInfo_.restartCallerPersistentId_;
}
void Session::SetNativeHideWindow(bool nativeHideWindow)
{
sessionInfo_.nativeHideWindow_ = nativeHideWindow;
}
bool Session::GetNativeHideWindow() const
{
return sessionInfo_.nativeHideWindow_;
}
WSError Session::SetLeashWindowAlpha(bool hidingStartWindow)
{
auto leashSurfaceNode = GetLeashWinSurfaceNode();
if (leashSurfaceNode == nullptr) {
TLOGI(WmsLogTag::WMS_PATTERN, "no leashWindow: %{public}d", hidingStartWindow);
return WSError::WS_ERROR_NULLPTR;
}
TLOGI(WmsLogTag::WMS_PATTERN, "hidingStartWindow: %{public}d", hidingStartWindow);
hidingStartWindow ? leashSurfaceNode->SetAlpha(0) : leashSurfaceNode->SetAlpha(1);
SetTouchable(!hidingStartWindow);
return WSError::WS_OK;
}
void Session::SetEnableRemoveStartingWindow(bool enableRemoveStartingWindow)
{
enableRemoveStartingWindow_ = enableRemoveStartingWindow;
}
bool Session::GetEnableRemoveStartingWindow() const
{
return enableRemoveStartingWindow_;
}
void Session::SetAppBufferReady(bool appBufferReady)
{
appBufferReady_ = appBufferReady;
}
bool Session::GetAppBufferReady() const
{
return appBufferReady_;
}
void Session::SetUseStartingWindowAboveLocked(bool useStartingWindowAboveLocked)
{
useStartingWindowAboveLocked_ = useStartingWindowAboveLocked;
}
bool Session::UseStartingWindowAboveLocked() const
{
return useStartingWindowAboveLocked_;
}
WindowType Session::GetWindowType() const
{
auto property = GetSessionProperty();
if (property) {
return property->GetWindowType();
}
return WindowType::WINDOW_TYPE_APP_MAIN_WINDOW;
}
std::string Session::GetWindowName() const
{
if (GetSessionInfo().isSystem_) {
return GetSessionInfo().abilityName_;
} else {
auto property = GetSessionProperty();
return property ? property->GetWindowName() : "";
}
}
void Session::SetSystemConfig(const SystemSessionConfig& systemConfig)
{
systemConfig_ = systemConfig;
}
SystemSessionConfig Session::GetSystemConfig() const
{
return systemConfig_;
}
void Session::SetBlurRadius(const float blurRadius)
{
blurRadius_ = blurRadius;
}
float Session::GetBlurRadius() const
{
return blurRadius_;
}
void Session::SetBlurBackgroundColor(const float blurBackgroundColor)
{
blurBackgroundColor_ = blurBackgroundColor;
}
uint32_t Session::GetBlurBackgroundColor() const
{
return blurBackgroundColor_;
}
void Session::SetSnapshotScale(const float snapshotScale)
{
snapshotScale_ = snapshotScale;
if (scenePersistence_) {
scenePersistence_->SetSnapshotScale(snapshotScale);
}
}
void Session::InitPersistentScaledSnapshotParam(bool enabled)
{
enablePersistentScaledSnapshot_ = enabled;
if (scenePersistence_) {
scenePersistence_->InitPersistentScaledSnapshotParam(enabled);
}
}
void Session::LoadSnapshotToMem()
{
auto task = [weakThis = wptr(this), where = __func__]() {
auto session = weakThis.promote();
if (session == nullptr) {
TLOGNE(WmsLogTag::WMS_PATTERN, "%{public}s session is nullptr", where);
return;
}
if (session->scenePersistence_ == nullptr) {
TLOGNE(WmsLogTag::WMS_PATTERN, "%{public}s scenePersistence is nullptr id: %{public}d",
where, session->GetPersistentId());
return;
}
auto pixelMap = session->scenePersistence_->GetLocalSnapshotPixelMap(1, 1);
if (pixelMap == nullptr) {
TLOGNW(WmsLogTag::WMS_PATTERN, "%{public}s pixelMap is nullptr id: %{public}d",
where, session->GetPersistentId());
return;
}
std::lock_guard<std::mutex> lock(session->snapshotMutex_);
session->snapshot_ = pixelMap;
session->scenePersistence_->SetIsSavingSnapshot(true);
session->saveSnapshotCallback_();
TLOGNI(WmsLogTag::WMS_PATTERN, "%{public}s done, id: %{public}d", where, session->GetPersistentId());
};
auto snapshotFfrtHelper = scenePersistence_->GetSnapshotFfrtHelper();
std::string taskName = "Session::LoadSnapshotToMem" + std::to_string(GetPersistentId());
snapshotFfrtHelper->CancelTask(taskName);
snapshotFfrtHelper->SubmitTask(std::move(task), taskName);
}
WSError Session::ProcessBackEvent()
{
if (!IsSessionValid()) {
TLOGW(WmsLogTag::WMS_EVENT, "Session is invalid, id: %{public}d state: %{public}u",
GetPersistentId(), GetSessionState());
return WSError::WS_ERROR_INVALID_SESSION;
}
if (!sessionStage_) {
TLOGE(WmsLogTag::WMS_EVENT, "session stage is nullptr");
return WSError::WS_ERROR_NULLPTR;
}
if (auto remoteObject = sessionStage_->AsObject();
remoteObject && !remoteObject->IsProxyObject()) {
PostExportTask([sessionStage = sessionStage_] {
sessionStage->HandleBackEvent();
});
return WSError::WS_OK;
}
return sessionStage_->HandleBackEvent();
}
void Session::GeneratePersistentId(bool isExtension, int32_t persistentId)
{
std::lock_guard lock(g_persistentIdSetMutex);
if (persistentId != INVALID_SESSION_ID && !g_persistentIdSet.count(persistentId)) {
g_persistentIdSet.insert(persistentId);
persistentId_ = persistentId;
return;
}
if (g_persistentId == INVALID_SESSION_ID) {
g_persistentId++;
}
g_persistentId++;
while (g_persistentIdSet.count(g_persistentId)) {
g_persistentId++;
}
if (isExtension) {
constexpr uint32_t pidLength = 18;
constexpr uint32_t pidMask = (1 << pidLength) - 1;
constexpr uint32_t persistentIdLength = 12;
constexpr uint32_t persistentIdMask = (1 << persistentIdLength) - 1;
uint32_t assembledPersistentId = ((static_cast<uint32_t>(getpid()) & pidMask) << persistentIdLength) |
(static_cast<uint32_t>(g_persistentId.load()) & persistentIdMask);
persistentId_ = assembledPersistentId | 0x40000000;
} else {
persistentId_ = static_cast<uint32_t>(g_persistentId.load()) & 0x3fffffff;
}
g_persistentIdSet.insert(g_persistentId);
TLOGI(WmsLogTag::WMS_LIFE,
"persistentId: %{public}d, persistentId_: %{public}d", persistentId, persistentId_);
}
sptr<ScenePersistence> Session::GetScenePersistence() const
{
return scenePersistence_;
}
bool Session::CheckEmptyKeyboardAvoidAreaIfNeeded() const
{
bool isMainFloating =
GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING && WindowHelper::IsMainWindow(GetWindowType());
bool isParentFloating = (SessionHelper::IsNonSecureToUIExtension(GetWindowType()) &&
GetParentSession() != nullptr &&
GetParentSession()->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING);
bool isMidScene = GetIsMidScene();
bool isPhoneNotFreeMultiWindow = systemConfig_.IsPhoneWindow() && !systemConfig_.IsFreeMultiWindowMode();
bool isPadNotFreeMultiWindow = systemConfig_.IsPadWindow() && !systemConfig_.IsFreeMultiWindowMode();
bool isPhoneOrPadNotFreeMultiWindow = isPhoneNotFreeMultiWindow || isPadNotFreeMultiWindow;
TLOGI(WmsLogTag::WMS_KEYBOARD, "check keyboard avoid area, isPhoneNotFreeMultiWindow: %{public}d, "
"isPadNotFreeMultiWindow: %{public}d", isPhoneNotFreeMultiWindow, isPadNotFreeMultiWindow);
auto screen = ScreenManager::GetInstance().GetScreenById(property_->GetDisplayId());
if (screen != nullptr && screen->GetName() == APP_CAST_SCREEN_NAME) {
TLOGI(WmsLogTag::WMS_KEYBOARD, "app cast screen");
return true;
}
return (isMainFloating || isParentFloating) && !isMidScene && isPhoneOrPadNotFreeMultiWindow;
}
void Session::SetKeyboardStateChangeListener(const NotifyKeyboardStateChangeFunc& func)
{
PostTask([weakThis = wptr(this), func, where = __func__]() {
auto session = weakThis.promote();
if (session == nullptr || func == nullptr) {
TLOGNE(WmsLogTag::WMS_KEYBOARD, "%{public}s session or func is null", where);
return;
}
session->keyboardStateChangeFunc_ = func;
auto newState = session->GetSessionState();
if (newState == SessionState::STATE_ACTIVE) {
newState = SessionState::STATE_FOREGROUND;
} else if (newState == SessionState::STATE_INACTIVE) {
newState = SessionState::STATE_BACKGROUND;
} else if (newState == SessionState::STATE_DISCONNECT) {
return;
}
session->NotifySessionStateChange(newState);
TLOGNI(WmsLogTag::WMS_KEYBOARD, "%{public}s id: %{public}d, state_: %{public}d, newState: %{public}d",
where, session->GetPersistentId(), session->GetSessionState(), newState);
}, __func__);
}
void Session::SetCallingSessionIdSessionListenser(const ProcessCallingSessionIdChangeFunc&& func)
{
TLOGD(WmsLogTag::DEFAULT, "in");
PostTask([weakThis = wptr(this), func = std::move(func), where = __func__]() {
auto session = weakThis.promote();
if (session == nullptr || func == nullptr) {
TLOGNE(WmsLogTag::WMS_KEYBOARD, "%{public}s session or func is null", where);
return;
}
session->callingSessionIdChangeFunc_ = std::move(func);
}, __func__);
}
void Session::NotifyOccupiedAreaChangeInfo(sptr<OccupiedAreaChangeInfo> info,
const std::shared_ptr<RSTransaction>& rsTransaction, const Rect& callingSessionRect,
const std::map<AvoidAreaType, AvoidArea>& avoidAreas)
{
if (!sessionStage_) {
TLOGD(WmsLogTag::WMS_KEYBOARD, "session stage is nullptr");
return;
}
if (CheckEmptyKeyboardAvoidAreaIfNeeded()) {
info = sptr<OccupiedAreaChangeInfo>::MakeSptr();
TLOGD(WmsLogTag::WMS_KEYBOARD, "Occupied area need to empty when in floating mode");
}
if (info != nullptr) {
TLOGI(WmsLogTag::WMS_KEYBOARD, "Calling id: %{public}d, callingSessionRect: %{public}s"
", safeRect: %{public}s, textFieldPositionY_: %{public}f, textFieldHeight_: %{public}f"
", size of avoidAreas: %{public}d", GetPersistentId(),
callingSessionRect.ToString().c_str(), info->rect_.ToString().c_str(),
info->textFieldPositionY_, info->textFieldHeight_, static_cast<int32_t>(avoidAreas.size()));
for (const auto& [type, avoidArea] : avoidAreas) {
TLOGI(WmsLogTag::WMS_KEYBOARD, "avoidAreaType: %{public}u, avoidArea: %{public}s",
type, avoidArea.ToString().c_str());
}
} else {
TLOGI(WmsLogTag::WMS_KEYBOARD, "occupied area info is nullptr, id: %{public}d", GetPersistentId());
}
sessionStage_->NotifyOccupiedAreaChangeInfo(info, rsTransaction, callingSessionRect, avoidAreas);
}
WindowMode Session::GetWindowMode() const
{
auto property = GetSessionProperty();
if (property == nullptr) {
WLOGFW("null property.");
return WindowMode::WINDOW_MODE_UNDEFINED;
}
return property->GetWindowMode();
}
WindowModeInfo Session::GetWindowModeInfo() const
{
auto property = GetSessionProperty();
if (property == nullptr) {
WLOGFW("null property.");
return WindowModeInfo {};
}
return property->GetWindowModeInfo();
}
WindowMode Session::GetWindowModeCompat() const
{
auto property = GetSessionProperty();
if (property == nullptr) {
WLOGFW("null property.");
return WindowMode::WINDOW_MODE_UNDEFINED;
}
return property->GetWindowModeCompat();
}
WSError Session::UpdateMaximizeMode(bool isMaximize)
{
WLOGFD("Session update maximize mode, isMaximize: %{public}d", isMaximize);
if (!IsSessionValid()) {
TLOGW(WmsLogTag::WMS_LAYOUT, "Session is invalid, id: %{public}d state: %{public}u",
GetPersistentId(), GetSessionState());
return WSError::WS_ERROR_INVALID_SESSION;
}
MaximizeMode mode = MaximizeMode::MODE_RECOVER;
if (isMaximize) {
mode = MaximizeMode::MODE_AVOID_SYSTEM_BAR;
} else if (GetWindowMode() == WindowMode::WINDOW_MODE_FULLSCREEN) {
mode = MaximizeMode::MODE_FULL_FILL;
}
auto property = GetSessionProperty();
if (property == nullptr) {
TLOGE(WmsLogTag::WMS_EVENT, "property is null");
return WSError::WS_ERROR_NULLPTR;
}
property->SetMaximizeMode(mode);
if (!sessionStage_) {
TLOGE(WmsLogTag::WMS_MAIN, "sessionStage_ is null");
return WSError::WS_ERROR_NULLPTR;
}
return sessionStage_->UpdateMaximizeMode(mode);
}
void Session::SetZOrder(uint32_t zOrder)
{
lastZOrder_ = zOrder_;
zOrder_ = zOrder;
NotifySessionInfoChange();
}
uint32_t Session::GetZOrder() const
{
return zOrder_;
}
uint32_t Session::GetLastZOrder() const
{
return lastZOrder_;
}
void Session::SetUINodeId(uint32_t uiNodeId)
{
if (uiNodeId_ != 0 && uiNodeId != 0 && !IsSystemSession() && SessionPermission::IsBetaVersion()) {
int32_t eventRet = HiSysEventWrite(
OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER,
"REPEAT_SET_UI_NODE_ID",
OHOS::HiviewDFX::HiSysEvent::EventType::STATISTIC,
"PID", getpid(),
"UID", getuid());
TLOGE(WmsLogTag::WMS_LIFE, " SetUINodeId: Repeat set UINodeId ret:%{public}d", eventRet);
return;
}
uiNodeId_ = uiNodeId;
}
uint32_t Session::GetUINodeId() const
{
return uiNodeId_;
}
void Session::SetShowRecent(bool showRecent)
{
TLOGI(WmsLogTag::WMS_MAIN, "in recents: %{public}d, id: %{public}d", showRecent, persistentId_);
bool isAttach = GetAttachState();
if (!IsSupportDetectWindow(isAttach) ||
!ShouldCreateDetectTaskInRecent(showRecent, showRecent_, isAttach)) {
showRecent_ = showRecent;
return;
}
showRecent_ = showRecent;
WindowMode windowMode = GetWindowMode();
if (!showRecent_ && ShouldCreateDetectTask(isAttach, windowMode)) {
CreateWindowStateDetectTask(isAttach, windowMode);
}
}
bool Session::GetShowRecent() const
{
return showRecent_;
}
bool Session::GetAttachState() const
{
return isAttach_;
}
DetectTaskInfo Session::GetDetectTaskInfo() const
{
std::shared_lock<std::shared_mutex> lock(detectTaskInfoMutex_);
return detectTaskInfo_;
}
void Session::SetDetectTaskInfo(const DetectTaskInfo& detectTaskInfo)
{
std::unique_lock<std::shared_mutex> lock(detectTaskInfoMutex_);
detectTaskInfo_ = detectTaskInfo;
}
bool Session::IsStateMatch(bool isAttach) const
{
return isAttach ? ATTACH_MAP.at(GetSessionState()) : DETACH_MAP.at(GetSessionState());
}
bool Session::IsSupportDetectWindow(bool isAttach)
{
if (!systemConfig_.IsPcWindow() && !systemConfig_.IsPhoneWindow()) {
TLOGD(WmsLogTag::WMS_LIFE, "device type not support, id:%{public}d", persistentId_);
return false;
}
if (isScreenLockedCallback_ && isScreenLockedCallback_()) {
TLOGD(WmsLogTag::WMS_LIFE, "screen locked, id:%{public}d", persistentId_);
return false;
}
if (!SessionHelper::IsMainWindow(GetWindowType())) {
TLOGD(WmsLogTag::WMS_LIFE, "only support main window, id:%{public}d", persistentId_);
return false;
}
if (systemConfig_.IsPcWindow() && (!isAttach || state_ != SessionState::STATE_DISCONNECT)) {
TLOGD(WmsLogTag::WMS_LIFE, "pc only support cold start, id:%{public}d", persistentId_);
RemoveWindowDetectTask();
return false;
}
return true;
}
void Session::RemoveWindowDetectTask()
{
if (handler_) {
handler_->RemoveTask(GetWindowDetectTaskName());
}
}
bool Session::ShouldCreateDetectTask(bool isAttach, WindowMode windowMode) const
{
if (GetDetectTaskInfo().taskState == DetectTaskState::NO_TASK) {
return true;
}
if ((GetDetectTaskInfo().taskState == DetectTaskState::ATTACH_TASK && isAttach) ||
(GetDetectTaskInfo().taskState == DetectTaskState::DETACH_TASK && !isAttach)) {
return true;
} else {
return GetDetectTaskInfo().taskWindowMode == windowMode;
}
}
bool Session::ShouldCreateDetectTaskInRecent(bool newShowRecent, bool oldShowRecent, bool isAttach) const
{
if (newShowRecent) {
return false;
}
return oldShowRecent ? isAttach : false;
}
void Session::RegisterIsScreenLockedCallback(const std::function<bool()>& callback)
{
isScreenLockedCallback_ = callback;
}
std::string Session::GetWindowDetectTaskName() const
{
return "wms:WindowStateDetect" + std::to_string(persistentId_);
}
void Session::RecordWindowStateAttachExceptionEvent(bool isAttached)
{
int32_t ret = HiSysEventWrite(
OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER,
"WINDOW_STATE_ERROR",
OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
"TYPE", "WINDOW_STATE_ATTACH_EXCEPTION",
"PERSISTENT_ID", GetPersistentId(),
"WINDOW_NAME", GetWindowName().c_str(),
"ATTACH_STATE", isAttached,
"SESSION_STATE", static_cast<uint32_t>(GetSessionState()));
if (ret != 0) {
TLOGE(WmsLogTag::WMS_LIFE, "write HiSysEvent error, ret: %{public}d", ret);
}
}
void Session::CreateWindowStateDetectTask(bool isAttach, WindowMode windowMode)
{
if (!handler_) {
return;
}
std::string taskName = GetWindowDetectTaskName();
RemoveWindowDetectTask();
auto detectTask = [weakThis = wptr(this), isAttach]() {
auto session = weakThis.promote();
if (session == nullptr) {
if (isAttach) {
TLOGNE(WmsLogTag::WMS_LIFE, "Window attach state and session"
"state mismatch, session is nullptr, attach:%{public}d", isAttach);
}
return;
}
if (session->isScreenLockedCallback_ && !session->isScreenLockedCallback_()) {
if (!session->IsStateMatch(isAttach)) {
TLOGNE(WmsLogTag::WMS_LIFE, "Window attach state and session state mismatch, "
"attach:%{public}d, sessioniState:%{public}d, persistenId:%{public}d, bundleName:%{public}s",
isAttach, static_cast<uint32_t>(session->GetSessionState()),
session->GetPersistentId(), session->GetSessionInfo().bundleName_.c_str());
session->RecordWindowStateAttachExceptionEvent(isAttach);
}
}
DetectTaskInfo detectTaskInfo;
session->SetDetectTaskInfo(detectTaskInfo);
};
handler_->PostTask(detectTask, taskName, STATE_DETECT_DELAYTIME);
DetectTaskInfo detectTaskInfo;
detectTaskInfo.taskWindowMode = windowMode;
detectTaskInfo.taskState = isAttach ? DetectTaskState::ATTACH_TASK : DetectTaskState::DETACH_TASK;
SetDetectTaskInfo(detectTaskInfo);
}
void Session::SetBufferAvailable(bool bufferAvailable, bool startWindowInvisible)
{
TLOGD(WmsLogTag::DEFAULT, "Set:%{public}d %{public}d", bufferAvailable, startWindowInvisible);
if (bufferAvailableChangeFunc_) {
bufferAvailableChangeFunc_(bufferAvailable, startWindowInvisible);
}
bufferAvailable_ = bufferAvailable;
}
bool Session::GetBufferAvailable() const
{
return bufferAvailable_;
}
void Session::SetNeedSnapshot(bool needSnapshot)
{
needSnapshot_ = needSnapshot;
}
void Session::SetExitSplitOnBackground(bool isExitSplitOnBackground)
{
TLOGW(WmsLogTag::WMS_MULTI_WINDOW, "id: %{public}d, SetExitSplitOnBackground not implement", persistentId_);
}
bool Session::IsExitSplitOnBackground() const
{
TLOGW(WmsLogTag::WMS_MULTI_WINDOW, "id: %{public}d, IsExitSplitOnBackground not implement", persistentId_);
return false;
}
void Session::SetFloatingScale(float floatingScale)
{
floatingScale_ = floatingScale;
}
float Session::GetFloatingScale() const
{
return floatingScale_;
}
void Session::SetScale(float scaleX, float scaleY, float pivotX, float pivotY)
{
layoutController_->SetScale(scaleX, scaleY, pivotX, pivotY);
}
void Session::SetIgnoreRotateScale(float ignoreRotateScaleX, float ignoreRotateScaleY)
{
layoutController_->SetIgnoreRotateScale(ignoreRotateScaleX, ignoreRotateScaleY);
}
void Session::SetClientScale(float scaleX, float scaleY, float pivotX, float pivotY)
{
layoutController_->SetClientScale(scaleX, scaleY, pivotX, pivotY);
}
float Session::GetScaleX() const
{
return layoutController_->GetScaleX();
}
float Session::GetScaleY() const
{
return layoutController_->GetScaleY();
}
float Session::GetIgnoreRotateScaleX() const
{
return layoutController_->GetIgnoreRotateScaleX();
}
float Session::GetIgnoreRotateScaleY() const
{
return layoutController_->GetIgnoreRotateScaleY();
}
float Session::GetPivotX() const
{
return layoutController_->GetPivotX();
}
float Session::GetPivotY() const
{
return layoutController_->GetPivotY();
}
void Session::SetSCBKeepKeyboard(bool scbKeepKeyboardFlag)
{
scbKeepKeyboardFlag_ = scbKeepKeyboardFlag;
}
bool Session::GetSCBKeepKeyboardFlag() const
{
return scbKeepKeyboardFlag_;
}
void Session::SetOffset(float x, float y)
{
offsetX_ = x;
offsetY_ = y;
WSRect newRect {
.posX_ = std::round(bounds_.posX_ + x),
.posY_ = std::round(bounds_.posY_ + y),
.width_ = std::round(bounds_.width_),
.height_ = std::round(bounds_.height_),
};
if (newRect != GetSessionRect()) {
UpdateRect(newRect, SizeChangeReason::UNDEFINED, "SetOffset");
}
}
float Session::GetOffsetX() const
{
return offsetX_;
}
float Session::GetOffsetY() const
{
return offsetY_;
}
void Session::SetBounds(const WSRectF& bounds)
{
bounds_ = bounds;
}
WSRectF Session::GetBounds()
{
return bounds_;
}
void Session::SetRotation(Rotation rotation)
{
rotation_ = rotation;
}
Rotation Session::GetRotation() const
{
return rotation_;
}
WSError Session::UpdateTitleInTargetPos(bool isShow, int32_t height)
{
WLOGFD("Session update title in target position, id: %{public}d, isShow: %{public}d, height: %{public}d",
GetPersistentId(), isShow, height);
if (!IsSessionValid()) {
TLOGW(WmsLogTag::WMS_MAIN, "Session is invalid, id: %{public}d state: %{public}u",
GetPersistentId(), GetSessionState());
return WSError::WS_ERROR_INVALID_SESSION;
}
if (!sessionStage_) {
TLOGE(WmsLogTag::WMS_MAIN, "sessionStage_ is null");
return WSError::WS_ERROR_NULLPTR;
}
return sessionStage_->UpdateTitleInTargetPos(isShow, height);
}
void Session::SetSessionInfoLockedStateChangeListener(const NotifySessionInfoLockedStateChangeFunc& func)
{
sessionInfoLockedStateChangeFunc_ = func;
}
void Session::NotifySessionInfoLockedStateChange(bool lockedState)
{
WLOGFD("Notify sessioninfo lockedstate change: %{public}u", lockedState);
if (sessionInfoLockedStateChangeFunc_) {
sessionInfoLockedStateChangeFunc_(lockedState);
}
}
std::vector<AppExecFwk::SupportWindowMode> Session::ExtractSupportWindowModeFromMetaData(
const std::shared_ptr<AppExecFwk::AbilityInfo>& abilityInfo)
{
std::vector<AppExecFwk::SupportWindowMode> updateWindowModes = {};
if (IsPcWindow() || systemConfig_.IsFreeMultiWindowMode()) {
auto metadata = abilityInfo->metadata;
for (const auto& item : metadata) {
if (item.name == "ohos.ability.window.supportWindowModeInFreeMultiWindow") {
updateWindowModes = ParseWindowModeFromMetaData(item.value);
}
}
}
if (updateWindowModes.empty()) {
updateWindowModes = abilityInfo->windowModes;
}
return updateWindowModes;
}
std::vector<AppExecFwk::SupportWindowMode> Session::ParseWindowModeFromMetaData(
const std::string& supportModesInFreeMultiWindow)
{
std::vector<AppExecFwk::SupportWindowMode> updateWindowModes = {};
std::stringstream supportModes(supportModesInFreeMultiWindow);
std::string supportWindowMode;
while (getline(supportModes, supportWindowMode, ',')) {
if (supportWindowMode == "fullscreen") {
updateWindowModes.push_back(AppExecFwk::SupportWindowMode::FULLSCREEN);
} else if (supportWindowMode == "split") {
updateWindowModes.push_back(AppExecFwk::SupportWindowMode::SPLIT);
} else if (supportWindowMode == "floating") {
updateWindowModes.push_back(AppExecFwk::SupportWindowMode::FLOATING);
} else {
TLOGW(WmsLogTag::WMS_LAYOUT, "invalid input");
}
}
return updateWindowModes;
}
WSError Session::SwitchFreeMultiWindow(const SystemSessionConfig& config)
{
bool enable = config.freeMultiWindowEnable_;
systemConfig_.defaultWindowMode_ = config.defaultWindowMode_;
systemConfig_.freeMultiWindowEnable_ = enable;
if (!IsSessionValid()) {
TLOGW(WmsLogTag::WMS_LAYOUT_PC, "Session is invalid, id: %{public}d state: %{public}u",
GetPersistentId(), GetSessionState());
return WSError::WS_ERROR_INVALID_SESSION;
}
if (!sessionStage_) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "sessionStage_ is null");
return WSError::WS_ERROR_NULLPTR;
}
auto property = GetSessionProperty();
if (property == nullptr) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "property is null");
return WSError::WS_ERROR_NULLPTR;
}
if (sessionInfo_.abilityInfo == nullptr) {
TLOGE(WmsLogTag::DEFAULT, "abilityInfo is nullptr!");
return WSError::WS_ERROR_NULLPTR;
}
if (haveSetSupportedWindowModes_ && enable) {
std::vector<AppExecFwk::SupportWindowMode> supportedWindowModes;
property->GetSupportedWindowModes(supportedWindowModes);
auto windowModeSupportType = WindowHelper::ConvertSupportModesToSupportType(supportedWindowModes);
property->SetWindowModeSupportType(windowModeSupportType);
} else {
std::vector<AppExecFwk::SupportWindowMode> updateWindowModes =
ExtractSupportWindowModeFromMetaData(sessionInfo_.abilityInfo);
auto windowModeSupportType = WindowHelper::ConvertSupportModesToSupportType(updateWindowModes);
property->SetWindowModeSupportType(windowModeSupportType);
}
TLOGI(WmsLogTag::WMS_LAYOUT_PC, "windowId: %{public}d enable: %{public}d defaultWindowMode: %{public}d",
GetPersistentId(), enable, systemConfig_.defaultWindowMode_);
return sessionStage_->SwitchFreeMultiWindow(enable, systemConfig_.supportMultiWindowScreenSet_);
}
WSError Session::GetIsMidScene(bool& isMidScene)
{
isMidScene = GetIsMidScene();
return WSError::WS_OK;
}
WSError Session::GetUIContentRemoteObj(sptr<IRemoteObject>& uiContentRemoteObj)
{
if (!IsSessionValid()) {
TLOGE(WmsLogTag::DEFAULT, "session %{public}d is invalid. Failed to get UIContentRemoteObj", GetPersistentId());
return WSError::WS_ERROR_INVALID_SESSION;
}
if (sessionStage_ == nullptr) {
TLOGE(WmsLogTag::DEFAULT, "sessionStage_ is nullptr");
return WSError::WS_ERROR_NULLPTR;
}
return sessionStage_->GetUIContentRemoteObj(uiContentRemoteObj);
}
void Session::SetNotifySystemSessionPointerEventFunc(const NotifySystemSessionPointerEventFunc& func)
{
std::lock_guard<std::mutex> lock(pointerEventMutex_);
systemSessionPointerEventFunc_ = func;
}
void Session::SetNotifySystemSessionKeyEventFunc(const NotifySystemSessionKeyEventFunc& func)
{
std::unique_lock<std::shared_mutex> lock(keyEventMutex_);
systemSessionKeyEventFunc_ = func;
}
void Session::NotifySessionInfoChange()
{
if (sessionInfoChangeNotifyManagerFunc_) {
sessionInfoChangeNotifyManagerFunc_(GetPersistentId());
} else {
TLOGD(WmsLogTag::WMS_EVENT, "sessionInfoChangeNotifyManagerFunc is nullptr");
}
}
void Session::NotifySessionPropertyChange(WindowInfoKey windowInfoKey)
{
if (sessionPropertyChangeNotifyManagerFunc_) {
sessionPropertyChangeNotifyManagerFunc_(GetPersistentId(), windowInfoKey);
} else {
TLOGE(WmsLogTag::WMS_ATTRIBUTE, "Func is invalid");
}
}
void Session::NotifyDisplayIdChanged(int32_t persistentId, uint64_t displayId)
{
if (displayIdChangedNotifyManagerFunc_) {
displayIdChangedNotifyManagerFunc_(persistentId, displayId);
} else {
TLOGE(WmsLogTag::WMS_KEYBOARD, "displayIdChangedNotifyManagerFunc is nullptr");
}
}
bool Session::NeedCheckContextTransparent() const
{
return contextTransparentFunc_ != nullptr;
}
void Session::SetContextTransparentFunc(const NotifyContextTransparentFunc& func)
{
contextTransparentFunc_ = func;
}
void Session::NotifyContextTransparent()
{
if (contextTransparentFunc_) {
int32_t eventRet = HiSysEventWrite(
OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER,
"SESSION_IS_TRANSPARENT",
OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
"PERSISTENT_ID", GetPersistentId(),
"BUNDLE_NAME", sessionInfo_.bundleName_);
WLOGFE("Session context is transparent, persistentId:%{public}d, eventRet:%{public}d",
GetPersistentId(), eventRet);
contextTransparentFunc_();
}
}
bool Session::IsSystemInput()
{
return sessionInfo_.sceneType_ == SceneType::INPUT_SCENE;
}
void Session::SetIsMidScene(bool isMidScene)
{
PostTask([weakThis = wptr(this), isMidScene] {
auto session = weakThis.promote();
if (session == nullptr) {
TLOGI(WmsLogTag::WMS_MULTI_WINDOW, "session is null");
return;
}
if (session->isMidScene_ != isMidScene) {
TLOGI(WmsLogTag::WMS_MULTI_WINDOW, "persistentId:%{public}d, isMidScene:%{public}d",
session->GetPersistentId(), isMidScene);
session->isMidScene_ = isMidScene;
if (!session->isMidScene_) {
session->SetIsNeedRemoveSnapShot(true);
}
session->NotifySessionPropertyChange(WindowInfoKey::MID_SCENE);
}
}, "SetIsMidScene");
}
void Session::SetIsNeedRemoveSnapShot(bool isNeedRemoveSnapShot)
{
PostTask([weakThis = wptr(this), isNeedRemoveSnapShot] {
auto session = weakThis.promote();
if (session == nullptr) {
TLOGW(WmsLogTag::WMS_MULTI_WINDOW, "session is null");
return;
}
if (session->isNeedRemoveSnapShot_ != isNeedRemoveSnapShot) {
TLOGW(WmsLogTag::WMS_MULTI_WINDOW, "persistentId:%{public}d, isNeedRemoveSnapShot:%{public}d",
session->GetPersistentId(), isNeedRemoveSnapShot);
session->isNeedRemoveSnapShot_ = isNeedRemoveSnapShot;
}
}, __func__);
}
bool Session::GetIsMidScene() const
{
if (isMidScene_) {
return true;
}
if (GetParentSession() == nullptr) {
return false;
}
return GetParentSession()->GetIsMidScene();
}
bool Session::GetIsNeedRemoveSnapShot() const
{
return isNeedRemoveSnapShot_;
}
void Session::SetTouchHotAreas(const std::vector<Rect>& touchHotAreas)
{
auto property = GetSessionProperty();
if (property == nullptr) {
return;
}
std::vector<Rect> lastTouchHotAreas;
property->GetTouchHotAreas(lastTouchHotAreas);
if (touchHotAreas == lastTouchHotAreas) {
return;
}
dirtyFlags_ |= static_cast<uint32_t>(SessionUIDirtyFlag::TOUCH_HOT_AREA);
std::string rectStr;
for (const auto& rect : touchHotAreas) {
rectStr = rectStr + " " + rect.ToString();
}
GetSessionProperty()->SetTouchHotAreas(touchHotAreas);
}
std::shared_ptr<Media::PixelMap> Session::GetSnapshotPixelMap(const float oriScale, const float newScale)
{
TLOGI(WmsLogTag::WMS_MAIN, "id %{public}d", GetPersistentId());
if (scenePersistence_ == nullptr) {
return nullptr;
}
auto key = GetScreenSnapshotStatus();
return scenePersistence_->IsSavingSnapshot() ? GetSnapshot() :
scenePersistence_->GetLocalSnapshotPixelMap(oriScale, newScale, key, freeMultiWindow_.load());
}
bool Session::IsVisibleForeground() const
{
return isVisible_.load() && IsLifecycleForeground();
}
bool Session::IsVisibleNotBackground() const
{
return isVisible_.load() && IsSessionNotBackground();
}
void Session::SetIsStarting(bool isStarting)
{
isStarting_ = isStarting;
}
void Session::ResetDirtyFlags()
{
if (!isVisible_.load()) {
dirtyFlags_ &= static_cast<uint32_t>(SessionUIDirtyFlag::AVOID_AREA);
} else {
dirtyFlags_ = 0;
}
}
void Session::SetUIStateDirty(bool dirty)
{
mainUIStateDirty_.store(dirty);
}
bool Session::GetUIStateDirty() const
{
return mainUIStateDirty_.load();
}
void Session::SetMainSessionUIStateDirty(bool dirty)
{
if (GetParentSession() && WindowHelper::IsMainWindow(GetParentSession()->GetWindowType())) {
GetParentSession()->SetUIStateDirty(dirty);
}
}
bool Session::IsScbCoreEnabled()
{
return isScbCoreEnabled_;
}
void Session::SetScbCoreEnabled(bool enabled)
{
TLOGI(WmsLogTag::WMS_PIPELINE, "%{public}d", enabled);
isScbCoreEnabled_ = enabled;
}
bool Session::IsVisible() const
{
return isVisible_.load();
}
std::shared_ptr<AppExecFwk::EventHandler> Session::GetEventHandler() const
{
return handler_;
}
std::shared_ptr<Media::PixelMap> Session::SetFreezeImmediately(float scale, bool isFreeze, float blur) const
{
HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "GetSnapshotWithFreeze[%d][%s]",
persistentId_, sessionInfo_.bundleName_.c_str());
auto surfaceNode = GetSurfaceNode();
if (!surfaceNode || !surfaceNode->IsBufferAvailable()) {
return nullptr;
}
auto callback = std::make_shared<SurfaceCaptureFuture>();
auto scaleValue = (!MathHelper::GreatNotEqual(scale, 0.0f) ||
!MathHelper::GreatNotEqual(scale, std::numeric_limits<float>::min())) ? snapshotScale_ : scale;
bool isNeedF16WindowShot = system::GetBoolParameter("persist.sys.graphic.scrgb.enabled", false);
RSSurfaceCaptureConfig config = {
.scaleX = scaleValue,
.scaleY = scaleValue,
.useDma = true,
.useCurWindow = true,
.isHdrCapture = true,
.needF16WindowCaptureForScRGB = isNeedF16WindowShot,
};
auto rsUICtx = surfaceNode->GetRSUIContext();
if (rsUICtx == nullptr || rsUICtx->GetRSRenderInterface() == nullptr) {
TLOGE(WmsLogTag::WMS_PATTERN, "rsUIContext is null");
return nullptr;
}
bool ret = rsUICtx->GetRSRenderInterface()->SetWindowFreezeImmediately(
surfaceNode, isFreeze, callback, config, blur);
if (!ret) {
TLOGE(WmsLogTag::WMS_PATTERN, "failed");
return nullptr;
}
if (isFreeze) {
auto pixelMap = callback->GetResult(SNAPSHOT_TIMEOUT_MS);
TLOGI(WmsLogTag::WMS_PATTERN, "get result: %{public}d, id: %{public}d", pixelMap != nullptr, persistentId_);
return pixelMap;
}
return nullptr;
}
bool Session::IsPcWindow() const
{
return systemConfig_.IsPcWindow();
}
WindowUIInfo Session::GetWindowUIInfoForWindowInfo() const
{
WindowUIInfo windowUIInfo;
windowUIInfo.visibilityState = GetVisibilityState();
return windowUIInfo;
}
WindowDisplayInfo Session::GetWindowDisplayInfoForWindowInfo() const
{
WindowDisplayInfo windowDisplayInfo;
if (PcFoldScreenManager::GetInstance().IsHalfFoldedOnMainDisplay(GetSessionProperty()->GetDisplayId())) {
WSRect sessionGlobalRect = GetSessionGlobalRect();
windowDisplayInfo.displayId = TransformGlobalRectToRelativeRect(sessionGlobalRect);
} else {
windowDisplayInfo.displayId = GetSessionProperty()->GetDisplayId();
}
return windowDisplayInfo;
}
WindowLayoutInfo Session::GetWindowLayoutInfoForWindowInfo() const
{
WindowLayoutInfo windowLayoutInfo;
WSRect sessionGlobalRect = GetSessionGlobalRect();
sessionGlobalRect.width_ *= GetScaleX();
sessionGlobalRect.height_ *= GetScaleY();
if (PcFoldScreenManager::GetInstance().IsHalfFoldedOnMainDisplay(GetSessionProperty()->GetDisplayId())) {
TransformGlobalRectToRelativeRect(sessionGlobalRect);
}
windowLayoutInfo.rect = { sessionGlobalRect.posX_, sessionGlobalRect.posY_,
sessionGlobalRect.width_, sessionGlobalRect.height_};
windowLayoutInfo.zOrder = GetZOrder();
return windowLayoutInfo;
}
WindowMetaInfo Session::GetWindowMetaInfoForWindowInfo() const
{
WindowMetaInfo windowMetaInfo;
windowMetaInfo.windowId = GetWindowId();
if (GetSessionInfo().isSystem_) {
windowMetaInfo.windowName = GetSessionInfo().abilityName_;
} else {
windowMetaInfo.windowName = GetSessionProperty()->GetWindowName();
}
windowMetaInfo.bundleName = GetSessionInfo().bundleName_;
windowMetaInfo.abilityName = GetSessionInfo().abilityName_;
windowMetaInfo.appIndex = GetSessionInfo().appIndex_;
windowMetaInfo.pid = GetCallingPid();
windowMetaInfo.windowType = GetWindowType();
windowMetaInfo.isMidScene = GetIsMidScene();
windowMetaInfo.windowMode = GetWindowModeCompat();
windowMetaInfo.windowModeInfo = GetWindowModeInfo();
windowMetaInfo.isFocused = IsFocused();
if (auto parentSession = GetParentSession()) {
windowMetaInfo.parentWindowId = static_cast<uint32_t>(parentSession->GetWindowId());
}
if (auto surfaceNode = GetSurfaceNode()) {
windowMetaInfo.surfaceNodeId = static_cast<uint64_t>(surfaceNode->GetId());
}
if (auto leashWinSurfaceNode = GetLeashWinSurfaceNode()) {
windowMetaInfo.leashWinSurfaceNodeId = static_cast<uint64_t>(leashWinSurfaceNode->GetId());
}
auto property = GetSessionProperty();
windowMetaInfo.isPrivacyMode = property->GetPrivacyMode() || property->GetSystemPrivacyMode();
auto displayId = property->GetDisplayId();
windowMetaInfo.isTouchable = GetWindowTouchableForMMI(displayId);
TLOGD(WmsLogTag::WMS_EVENT, "id:%{public}d, %{public}d", windowMetaInfo.windowId,
windowMetaInfo.isTouchable);
return windowMetaInfo;
}
DisplayId Session::GetClientDisplayId() const
{
return clientDisplayId_;
}
void Session::SetClientDisplayId(DisplayId displayid)
{
clientDisplayId_ = displayid;
}
void Session::SetDragStart(bool isDragStart)
{
isDragStart_ = isDragStart;
}
void Session::SetBorderUnoccupied(bool borderUnoccupied)
{
TLOGI(WmsLogTag::WMS_PATTERN, "borderUnoccupied: %{public}d", borderUnoccupied);
borderUnoccupied_ = borderUnoccupied;
}
bool Session::GetBorderUnoccupied() const
{
return borderUnoccupied_;
}
void Session::SetWindowAnimationDuration(int32_t duration)
{
windowAnimationDuration_ = duration;
}
bool Session::IsNeedReportTimeout() const
{
WindowType type = GetWindowType();
return WindowHelper::IsSubWindow(type) || (WindowHelper::IsAboveSystemWindow(type) &&
type != WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT && type != WindowType::WINDOW_TYPE_PANEL);
}
void Session::PostSpecificSessionLifeCycleTimeoutTask(const std::string& eventName)
{
const int32_t THRESHOLD = 20;
if (!IsNeedReportTimeout()) {
TLOGD(WmsLogTag::DEFAULT, "not specific window");
return;
}
if (windowAnimationDuration_) {
TLOGD(WmsLogTag::DEFAULT, "window configured animation, don't report");
return;
}
if (!handler_) {
TLOGE(WmsLogTag::DEFAULT, "handler is null");
return;
}
handler_->RemoveTask(eventName == ATTACH_EVENT_NAME ?
DETACH_EVENT_NAME : ATTACH_EVENT_NAME);
auto task = [weakThis = wptr(this), eventName, where = __func__]() {
auto session = weakThis.promote();
if (!session) {
TLOGNI(WmsLogTag::DEFAULT, "%{public}s, session is null.", where);
return;
}
bool isAttach = session->GetAttachState();
if ((isAttach && eventName == ATTACH_EVENT_NAME) ||
(!isAttach && eventName == DETACH_EVENT_NAME)) {
TLOGND(WmsLogTag::DEFAULT, "%{public}s, detached or attached in time", where);
return;
}
WindowLifeCycleReportInfo reportInfo {
session->GetSessionInfo().bundleName_,
static_cast<int32_t>(session->GetPersistentId()),
static_cast<int32_t>(session->GetWindowType()),
static_cast<int32_t>(session->GetWindowMode()),
static_cast<int32_t>(session->GetSessionProperty()->GetWindowFlags()),
eventName
};
TLOGNI(WmsLogTag::DEFAULT, "%{public}s report msg: %{public}s", where, reportInfo.ToString().c_str());
WindowInfoReporter::GetInstance().ReportSpecWindowLifeCycleChange(reportInfo);
};
handler_->PostTask(task, "wms:" + eventName, THRESHOLD, AppExecFwk::EventQueue::Priority::IMMEDIATE);
}
void Session::DeletePersistentImageFit()
{
auto isPersistentImageFit = Rosen::ScenePersistentStorage::HasKey(
"SetImageForRecent_" + std::to_string(GetPersistentId()), Rosen::ScenePersistentStorageType::MAXIMIZE_STATE);
if (isPersistentImageFit) {
TLOGI(WmsLogTag::WMS_PATTERN, "delete persistent ImageFit");
isPersistentImageFit_.store(false);
Rosen::ScenePersistentStorage::Delete("SetImageForRecent_" + std::to_string(GetPersistentId()),
Rosen::ScenePersistentStorageType::MAXIMIZE_STATE);
}
}
void Session::RecoverImageForRecent()
{
auto isPersistentImageFit = ScenePersistentStorage::HasKey("SetImageForRecent_" +
std::to_string(persistentId_), ScenePersistentStorageType::MAXIMIZE_STATE);
if (isPersistentImageFit) {
TLOGI(WmsLogTag::WMS_PATTERN, "%{public}d", persistentId_);
isPersistentImageFit_.store(true);
ScenePersistentStorage::Get("SetImageForRecent_" + std::to_string(persistentId_),
persistentImageFit_, ScenePersistentStorageType::MAXIMIZE_STATE);
}
}
void Session::SetPersistentImageFit(int32_t imageFit)
{
persistentImageFit_ = imageFit;
isPersistentImageFit_.store(true);
}
void Session::SetGlobalDisplayRect(const WSRect& rect)
{
TLOGD(WmsLogTag::WMS_LAYOUT, "windowId: %{public}d, rect: %{public}s", GetPersistentId(), rect.ToString().c_str());
GetSessionProperty()->SetGlobalDisplayRect(SessionHelper::TransferToRect(rect));
}
WSRect Session::GetGlobalDisplayRect() const
{
WSRect rect = SessionHelper::TransferToWSRect(GetSessionProperty()->GetGlobalDisplayRect());
TLOGD(WmsLogTag::WMS_LAYOUT, "windowId: %{public}d, rect: %{public}s", GetPersistentId(), rect.ToString().c_str());
return rect;
}
WSError Session::UpdateGlobalDisplayRect(const WSRect& rect, SizeChangeReason reason)
{
const int32_t windowId = GetWindowId();
TLOGD(WmsLogTag::WMS_LAYOUT, "windowId: %{public}d, rect: %{public}s, reason: %{public}u",
windowId, rect.ToString().c_str(), reason);
if (rect == GetGlobalDisplayRect() && reason == globalDisplayRectSizeChangeReason_) {
TLOGD(WmsLogTag::WMS_LAYOUT,
"No change in rect or reason, windowId: %{public}d, rect: %{public}s, reason: %{public}u",
windowId, rect.ToString().c_str(), reason);
return WSError::WS_DO_NOTHING;
}
SetGlobalDisplayRect(rect);
globalDisplayRectSizeChangeReason_ = reason;
NotifyClientToUpdateGlobalDisplayRect(rect, reason);
return WSError::WS_OK;
}
WSError Session::UpdateClientRectInfo(const WSRect& rect, SizeChangeReason reason,
const std::map<AvoidAreaType, AvoidArea>& avoidAreas,
const std::shared_ptr<RSTransaction>& rsTransaction)
{
if (!sessionStage_) {
return WSError::WS_DO_NOTHING;
}
SceneAnimationConfig config;
if (reason == SizeChangeReason::SCENE_WITH_ANIMATION) {
config = sceneAnimationConfig_;
} else {
config.rsTransaction_ = rsTransaction;
config.animationDuration_ = GetRotateAnimationDuration();
}
return sessionStage_->UpdateRect(rect, reason, config, avoidAreas);
}
WSError Session::NotifyClientToUpdateGlobalDisplayRect(const WSRect& rect, SizeChangeReason reason)
{
if (!sessionStage_ || !IsLifecycleForeground()) {
return WSError::WS_DO_NOTHING;
}
return sessionStage_->UpdateGlobalDisplayRectFromServer(rect, reason);
}
void Session::SetOutlineParamsChangeCallback(OutlineParamsChangeCallbackFunc&& func)
{
PostTask([weakThis = wptr(this), where = __func__, func = std::move(func)] {
auto session = weakThis.promote();
if (!session || !func) {
TLOGNE(WmsLogTag::WMS_ANIMATION, "session or onOutlineParamsChangeCallback is null.");
return;
}
session->outlineParamsChangeCallback_ = std::move(func);
session->outlineParamsChangeCallback_(session->isOutlineEnabled_, session->outlineStyleParams_);
}, __func__);
}
void Session::UpdateSessionOutline(bool enabled, const OutlineStyleParams& params)
{
if (enabled == isOutlineEnabled_ && params == outlineStyleParams_) {
TLOGD(WmsLogTag::WMS_ANIMATION, "Same outline params.");
return;
}
TLOGI(WmsLogTag::WMS_ANIMATION, "id: %{public}d, oldEnabled: %{public}d, oldParams: %{public}s, "
"newEnabled: %{public}d, newParams: %{public}s", GetPersistentId(), isOutlineEnabled_,
outlineStyleParams_.ToString().c_str(), enabled, params.ToString().c_str());
isOutlineEnabled_ = enabled;
outlineStyleParams_.outlineColor_ = params.outlineColor_;
outlineStyleParams_.outlineWidth_ = params.outlineWidth_;
outlineStyleParams_.outlineShape_ = params.outlineShape_;
if (outlineParamsChangeCallback_) {
outlineParamsChangeCallback_(isOutlineEnabled_, outlineStyleParams_);
} else {
TLOGI(WmsLogTag::WMS_ANIMATION, "Outline params change callback is null.");
}
}
std::shared_ptr<RSUIContext> Session::GetRSUIContext(const char* caller)
{
RETURN_IF_RS_CLIENT_MULTI_INSTANCE_DISABLED(nullptr);
auto screenId = GetScreenId();
std::lock_guard<std::mutex> lock(rsUIContextMutex_);
if (screenIdOfRSUIContext_ != screenId || screenIdOfRSUIContext_ == SCREEN_ID_INVALID) {
rsUIContext_ = ScreenSessionManagerClient::GetInstance().GetRSUIContext(screenId);
if (rsUIContext_ != nullptr) {
screenIdOfRSUIContext_ = screenId;
TLOGI(WmsLogTag::WMS_SCB,
"SetSessionRSUIContext: %{public}s: %{public}s, sessionId: %{public}d, screenId:%{public}" PRIu64,
caller, RSAdapterUtil::RSUIContextToStr(rsUIContext_).c_str(), GetPersistentId(), screenId);
}
}
if (rsUIContext_ == nullptr && GetSessionType() == SessionType::SceneSession) {
TLOGI(WmsLogTag::WMS_SCB, "%{public}s: %{public}s, sessionId: %{public}d, screenId:%{public}" PRIu64,
caller, RSAdapterUtil::RSUIContextToStr(rsUIContext_).c_str(), GetPersistentId(), screenId);
rsUIContext_ = RSUIContextContainer::GetRSUIContext();
}
return rsUIContext_;
}
std::shared_ptr<RSUIContext> Session::GetRSShadowContext()
{
std::lock_guard<std::mutex> lock(surfaceNodeMutex_);
if (RSAdapterUtil::IsClientMultiInstanceEnabled()) {
if (!shadowSurfaceNode_) {
TLOGE(WmsLogTag::WMS_SCB, "Shadow surface node is nullptr, id: %{public}d.", GetPersistentId());
return nullptr;
}
return shadowSurfaceNode_->GetRSUIContext();
}
return GetRSUIContext();
}
std::shared_ptr<RSUIContext> Session::GetRSLeashWinShadowContext()
{
std::lock_guard<std::mutex> lock(leashWinSurfaceNodeMutex_);
if (RSAdapterUtil::IsClientMultiInstanceEnabled()) {
if (!leashWinShadowSurfaceNode_) {
TLOGE(WmsLogTag::WMS_SCB, "Leash win shadow surface node is nullptr, id: %{public}d.", GetPersistentId());
return nullptr;
}
return leashWinShadowSurfaceNode_->GetRSUIContext();
}
return GetRSUIContext();
}
WSError Session::SetIsShowDecorInFreeMultiWindow(bool isShow)
{
property_->SetIsNeedUpdateShowDecor(true);
property_->SetIsShowDecorInFreeMultiWindow(isShow);
if (!IsSessionValid()) {
TLOGE(WmsLogTag::WMS_DECOR, "Session is invalid, id: %{public}d state: %{public}u",
GetPersistentId(), GetSessionState());
return WSError::WS_ERROR_INVALID_SESSION;
}
if (!sessionStage_) {
TLOGE(WmsLogTag::WMS_DECOR, "sessionStage_ is null");
return WSError::WS_ERROR_NULLPTR;
}
if (WindowHelper::IsMainWindow(GetWindowType())) {
TLOGI(WmsLogTag::WMS_DECOR, "id: %{public}d isShow: %{public}d",
GetPersistentId(), isShow);
return sessionStage_->UpdateIsShowDecorInFreeMultiWindow(isShow);
}
return WSError::WS_OK;
}
PrelayoutContext Session::GetPrelayoutContext()
{
PrelayoutContext ctx;
ctx.enable = sessionInfo_.isGamePrelaunch_;
if (!ctx.enable) {
return ctx;
}
const auto preCalc = PreCalcWindowProperty();
ctx.winRect = {
0, 0,
static_cast<int32_t>(preCalc.width),
static_cast<int32_t>(preCalc.height)
};
auto sessionProperty = GetSessionProperty();
if (sessionProperty == nullptr) {
return ctx;
}
const auto displayId = sessionProperty->GetDisplayId();
auto screenSession = ScreenSessionManagerClient::GetInstance()
.GetScreenSession(displayId);
const float density = screenSession ?
screenSession->GetScreenProperty().GetDensity() : 1.0f;
ctx.display = {
.width = preCalc.width,
.height = preCalc.height,
.density = density,
.rotation = preCalc.rotation
};
TLOGD(WmsLogTag::WMS_LAYOUT, "id: %{public}d, ctx: %{public}s",
GetPersistentId(), ctx.ToString().c_str());
return ctx;
}
void Session::HandleInitialRect(const PrelayoutContext& ctx)
{
if (WindowHelper::IsUIExtensionWindow(GetWindowType())) {
UpdateRect(GetSessionRect(), SizeChangeReason::UNDEFINED, "Connect");
return;
}
const std::optional<WSRect> rect =
ctx.enable ? std::make_optional(ctx.winRect) : std::nullopt;
NotifyClientToUpdateRect("Connect", rect, nullptr);
}
void Session::HandleHookDisplay(const PrelayoutContext& ctx)
{
if (!ctx.enable || !updateAppHookDisplayInfoFunc_) {
return;
}
const HookInfo hookInfo = {
.width_ = ctx.display.width,
.height_ = ctx.display.height,
.density_ = ctx.display.density,
.rotation_ = ctx.display.rotation,
.enableHookRotation_ = true
};
const auto ret = updateAppHookDisplayInfoFunc_(callingUid_, hookInfo, true);
if (ret != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_LAYOUT,
"Failed to update app hook display info. id: %{public}d, uid: %{public}d, ret: %{public}d",
GetPersistentId(), callingUid_, ret);
return;
}
}
WSError Session::UpdateLSStateInfo(bool isLSState)
{
TLOGD(WmsLogTag::WMS_LAYOUT, "windowId: %{public}d, isLSState: %{public}d", GetPersistentId(), isLSState);
if (!sessionStage_) {
TLOGE(WmsLogTag::WMS_LAYOUT, "session stage is nullptr");
return WSError::WS_DO_NOTHING;
}
return sessionStage_->UpdateLSState(isLSState);
}
}