1/*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "session/host/include/session.h"
17
18#include "ability_info.h"
19#include "ability_start_setting.h"
20#include "input_manager.h"
21#include "ipc_skeleton.h"
22#include "key_event.h"
23#include "pointer_event.h"
24#include <transaction/rs_interfaces.h>
25#include <transaction/rs_transaction.h>
26#include <ui/rs_surface_node.h>
27#include "proxy/include/window_info.h"
28
29#include "common/include/session_permission.h"
30#include "session_helper.h"
31#include "surface_capture_future.h"
32#include "util.h"
33#include "window_helper.h"
34#include "window_manager_hilog.h"
35#include "parameters.h"
36#include <hisysevent.h>
37#include "hitrace_meter.h"
38#include "screen_session_manager_client/include/screen_session_manager_client.h"
39#include "session/host/include/ws_ffrt_helper.h"
40#include "singleton_container.h"
41#include "perform_reporter.h"
42
43namespace OHOS::Rosen {
44namespace {
45constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, HILOG_DOMAIN_WINDOW, "Session" };
46std::atomic<int32_t> g_persistentId = INVALID_SESSION_ID;
47std::set<int32_t> g_persistentIdSet;
48constexpr float INNER_BORDER_VP = 5.0f;
49constexpr float OUTSIDE_BORDER_VP = 4.0f;
50constexpr float INNER_ANGLE_VP = 16.0f;
51constexpr uint32_t MAX_LIFE_CYCLE_TASK_IN_QUEUE = 15;
52constexpr int64_t LIFE_CYCLE_TASK_EXPIRED_TIME_LIMIT = 350;
53static bool g_enableForceUIFirst = system::GetParameter("window.forceUIFirst.enabled", "1") == "1";
54constexpr int64_t STATE_DETECT_DELAYTIME = 3 * 1000;
55const std::string SHELL_BUNDLE_NAME = "com.huawei.shell_assistant";
56const std::string SHELL_APP_IDENTIFIER = "5765880207854632823";
57const std::map<SessionState, bool> ATTACH_MAP = {
58    { SessionState::STATE_DISCONNECT, false },
59    { SessionState::STATE_CONNECT, false },
60    { SessionState::STATE_FOREGROUND, true },
61    { SessionState::STATE_ACTIVE, true },
62    { SessionState::STATE_INACTIVE, false },
63    { SessionState::STATE_BACKGROUND, false },
64};
65const std::map<SessionState, bool> DETACH_MAP = {
66    { SessionState::STATE_DISCONNECT, true },
67    { SessionState::STATE_CONNECT, false },
68    { SessionState::STATE_FOREGROUND, false },
69    { SessionState::STATE_ACTIVE, false },
70    { SessionState::STATE_INACTIVE, true },
71    { SessionState::STATE_BACKGROUND, true },
72};
73} // namespace
74
75std::shared_ptr<AppExecFwk::EventHandler> Session::mainHandler_;
76bool Session::isScbCoreEnabled_ = false;
77
78Session::Session(const SessionInfo& info) : sessionInfo_(info)
79{
80    property_ = sptr<WindowSessionProperty>::MakeSptr();
81    property_->SetWindowType(static_cast<WindowType>(info.windowType_));
82
83    if (!mainHandler_) {
84        auto runner = AppExecFwk::EventRunner::GetMainEventRunner();
85        mainHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner);
86    }
87
88    using type = std::underlying_type_t<MMI::WindowArea>;
89    for (type area = static_cast<type>(MMI::WindowArea::FOCUS_ON_TOP);
90        area <= static_cast<type>(MMI::WindowArea::FOCUS_ON_BOTTOM_RIGHT); ++area) {
91        auto ret = windowAreas_.insert(
92            std::pair<MMI::WindowArea, WSRectF>(static_cast<MMI::WindowArea>(area), WSRectF()));
93        if (!ret.second) {
94            WLOGFE("Failed to insert area:%{public}d", area);
95        }
96    }
97
98    if (info.want != nullptr) {
99        auto focusedOnShow = info.want->GetBoolParam(AAFwk::Want::PARAM_RESV_WINDOW_FOCUSED, true);
100        TLOGI(WmsLogTag::WMS_FOCUS, "focusedOnShow:%{public}d", focusedOnShow);
101        SetFocusedOnShow(focusedOnShow);
102    }
103}
104
105void Session::SetEventHandler(const std::shared_ptr<AppExecFwk::EventHandler>& handler,
106    const std::shared_ptr<AppExecFwk::EventHandler>& exportHandler)
107{
108    handler_ = handler;
109    exportHandler_ = exportHandler;
110}
111
112void Session::PostTask(Task&& task, const std::string& name, int64_t delayTime)
113{
114    if (!handler_ || handler_->GetEventRunner()->IsCurrentRunnerThread()) {
115        HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "s:%s", name.c_str());
116        return task();
117    }
118    auto localTask = [task = std::move(task), name]() {
119        HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "s:%s", name.c_str());
120        task();
121    };
122    handler_->PostTask(std::move(localTask), "wms:" + name, delayTime, AppExecFwk::EventQueue::Priority::IMMEDIATE);
123}
124
125void Session::PostExportTask(Task&& task, const std::string& name, int64_t delayTime)
126{
127    if (!exportHandler_ || exportHandler_->GetEventRunner()->IsCurrentRunnerThread()) {
128        HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "s:%s", name.c_str());
129        return task();
130    }
131    auto localTask = [task = std::move(task), name]() {
132        HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "s:%s", name.c_str());
133        task();
134    };
135    exportHandler_->PostTask(std::move(localTask), "wms:" + name, delayTime,
136        AppExecFwk::EventQueue::Priority::IMMEDIATE);
137}
138
139int32_t Session::GetPersistentId() const
140{
141    return persistentId_;
142}
143
144std::shared_ptr<RSSurfaceNode> Session::GetSurfaceNode() const
145{
146    return surfaceNode_;
147}
148
149void Session::SetLeashWinSurfaceNode(std::shared_ptr<RSSurfaceNode> leashWinSurfaceNode)
150{
151    if (g_enableForceUIFirst) {
152        auto rsTransaction = RSTransactionProxy::GetInstance();
153        if (rsTransaction) {
154            rsTransaction->Begin();
155        }
156        if (!leashWinSurfaceNode && leashWinSurfaceNode_) {
157            leashWinSurfaceNode_->SetForceUIFirst(false);
158        }
159        if (rsTransaction) {
160            rsTransaction->Commit();
161        }
162    }
163    std::lock_guard<std::mutex> lock(leashWinSurfaceNodeMutex_);
164    leashWinSurfaceNode_ = leashWinSurfaceNode;
165    if (leashWindowSurfaceNodeChangedFunc_) {
166        leashWindowSurfaceNodeChangedFunc_();
167    }
168}
169
170void Session::SetFrameLayoutFinishListener(const NotifyFrameLayoutFinishFunc& func)
171{
172    frameLayoutFinishFunc_ = func;
173}
174
175std::shared_ptr<RSSurfaceNode> Session::GetLeashWinSurfaceNode() const
176{
177    std::lock_guard<std::mutex> lock(leashWinSurfaceNodeMutex_);
178    return leashWinSurfaceNode_;
179}
180
181std::shared_ptr<RSSurfaceNode> Session::GetSurfaceNodeForMoveDrag() const
182{
183    auto movedSurfaceNode = GetLeashWinSurfaceNode();
184    if (!movedSurfaceNode) {
185        movedSurfaceNode = surfaceNode_;
186    }
187    return movedSurfaceNode;
188}
189
190std::shared_ptr<Media::PixelMap> Session::GetSnapshot() const
191{
192    std::lock_guard<std::mutex> lock(snapshotMutex_);
193    return snapshot_;
194}
195
196void Session::SetSessionInfoAncoSceneState(int32_t ancoSceneState)
197{
198    std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
199    sessionInfo_.ancoSceneState = ancoSceneState;
200}
201
202void Session::SetSessionInfoTime(const std::string& time)
203{
204    std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
205    sessionInfo_.time = time;
206}
207
208void Session::SetSessionInfoAbilityInfo(const std::shared_ptr<AppExecFwk::AbilityInfo>& abilityInfo)
209{
210    std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
211    sessionInfo_.abilityInfo = abilityInfo;
212}
213
214void Session::SetSessionInfoWant(const std::shared_ptr<AAFwk::Want>& want)
215{
216    std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
217    sessionInfo_.want = want;
218}
219
220void Session::SetSessionInfoProcessOptions(const std::shared_ptr<AAFwk::ProcessOptions>& processOptions)
221{
222    std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
223    sessionInfo_.processOptions = processOptions;
224}
225
226void Session::ResetSessionInfoResultCode()
227{
228    std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
229    sessionInfo_.resultCode = -1; // -1: initial result code
230}
231
232void Session::SetSessionInfoPersistentId(int32_t persistentId)
233{
234    std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
235    sessionInfo_.persistentId_ = persistentId;
236}
237
238void Session::SetSessionInfoCallerPersistentId(int32_t callerPersistentId)
239{
240    std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
241    sessionInfo_.callerPersistentId_ = callerPersistentId;
242}
243
244void Session::SetSessionInfoContinueState(ContinueState state)
245{
246    std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
247    sessionInfo_.continueState = state;
248}
249
250void Session::SetSessionInfoLockedState(bool lockedState)
251{
252    std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
253    sessionInfo_.lockedState = lockedState;
254    NotifySessionInfoLockedStateChange(lockedState);
255}
256
257void Session::SetSessionInfoIsClearSession(bool isClearSession)
258{
259    std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
260    sessionInfo_.isClearSession = isClearSession;
261}
262
263void Session::SetSessionInfoAffinity(std::string affinity)
264{
265    std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
266    sessionInfo_.sessionAffinity = affinity;
267}
268
269void Session::GetCloseAbilityWantAndClean(AAFwk::Want& outWant)
270{
271    std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
272    if (sessionInfo_.closeAbilityWant != nullptr) {
273        outWant = *sessionInfo_.closeAbilityWant;
274        sessionInfo_.closeAbilityWant = nullptr;
275    }
276}
277
278void Session::SetSessionInfo(const SessionInfo& info)
279{
280    std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
281    sessionInfo_.want = info.want;
282    sessionInfo_.callerToken_ = info.callerToken_;
283    sessionInfo_.requestCode = info.requestCode;
284    sessionInfo_.callerPersistentId_ = info.callerPersistentId_;
285    sessionInfo_.callingTokenId_ = info.callingTokenId_;
286    sessionInfo_.uiAbilityId_ = info.uiAbilityId_;
287    sessionInfo_.startSetting = info.startSetting;
288    sessionInfo_.continueSessionId_ = info.continueSessionId_;
289    sessionInfo_.isAtomicService_ = info.isAtomicService_;
290}
291
292void Session::SetScreenId(uint64_t screenId)
293{
294    sessionInfo_.screenId_ = screenId;
295    if (sessionStage_) {
296        sessionStage_->UpdateDisplayId(screenId);
297    }
298}
299
300void Session::SetAppInstanceKey(const std::string& appInstanceKey)
301{
302    sessionInfo_.appInstanceKey_ = appInstanceKey;
303}
304
305std::string Session::GetAppInstanceKey() const
306{
307    return sessionInfo_.appInstanceKey_;
308}
309
310const SessionInfo& Session::GetSessionInfo() const
311{
312    return sessionInfo_;
313}
314
315bool Session::RegisterLifecycleListener(const std::shared_ptr<ILifecycleListener>& listener)
316{
317    return RegisterListenerLocked(lifecycleListeners_, listener);
318}
319
320bool Session::UnregisterLifecycleListener(const std::shared_ptr<ILifecycleListener>& listener)
321{
322    return UnregisterListenerLocked(lifecycleListeners_, listener);
323}
324
325template<typename T>
326bool Session::RegisterListenerLocked(std::vector<std::shared_ptr<T>>& holder, const std::shared_ptr<T>& listener)
327{
328    if (listener == nullptr) {
329        WLOGFE("listener is nullptr");
330        return false;
331    }
332    std::lock_guard<std::recursive_mutex> lock(lifecycleListenersMutex_);
333    if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
334        WLOGFE("Listener already registered");
335        return false;
336    }
337    holder.emplace_back(listener);
338    return true;
339}
340
341template<typename T>
342bool Session::UnregisterListenerLocked(std::vector<std::shared_ptr<T>>& holder, const std::shared_ptr<T>& listener)
343{
344    if (listener == nullptr) {
345        WLOGFE("listener could not be null");
346        return false;
347    }
348    std::lock_guard<std::recursive_mutex> lock(lifecycleListenersMutex_);
349    holder.erase(std::remove_if(holder.begin(), holder.end(),
350        [listener](std::shared_ptr<T> registeredListener) { return registeredListener == listener; }),
351        holder.end());
352    return true;
353}
354
355void Session::NotifyActivation()
356{
357    auto lifecycleListeners = GetListeners<ILifecycleListener>();
358    for (auto& listener : lifecycleListeners) {
359        if (auto listenerPtr = listener.lock()) {
360            listenerPtr->OnActivation();
361        }
362    }
363}
364
365void Session::NotifyConnect()
366{
367    auto lifecycleListeners = GetListeners<ILifecycleListener>();
368    for (auto& listener : lifecycleListeners) {
369        if (auto listenerPtr = listener.lock()) {
370            listenerPtr->OnConnect();
371        }
372    }
373}
374
375void Session::NotifyForeground()
376{
377    auto lifecycleListeners = GetListeners<ILifecycleListener>();
378    for (auto& listener : lifecycleListeners) {
379        if (auto listenerPtr = listener.lock()) {
380            listenerPtr->OnForeground();
381        }
382    }
383}
384
385void Session::NotifyBackground()
386{
387    auto lifecycleListeners = GetListeners<ILifecycleListener>();
388    for (auto& listener : lifecycleListeners) {
389        if (auto listenerPtr = listener.lock()) {
390            listenerPtr->OnBackground();
391        }
392    }
393}
394
395void Session::NotifyDisconnect()
396{
397    auto lifecycleListeners = GetListeners<ILifecycleListener>();
398    for (auto& listener : lifecycleListeners) {
399        if (auto listenerPtr = listener.lock()) {
400            listenerPtr->OnDisconnect();
401        }
402    }
403}
404
405void Session::NotifyLayoutFinished()
406{
407    auto lifecycleListeners = GetListeners<ILifecycleListener>();
408    for (auto& listener : lifecycleListeners) {
409        if (auto listenerPtr = listener.lock()) {
410            listenerPtr->OnLayoutFinished();
411        }
412    }
413}
414
415void Session::NotifyExtensionDied()
416{
417    if (!SessionPermission::IsSystemCalling()) {
418        TLOGE(WmsLogTag::WMS_UIEXT, "permission denied!");
419        return;
420    }
421    TLOGI(WmsLogTag::WMS_UIEXT, "NotifyExtensionDied called in session(persistentId:%{public}d).", persistentId_);
422    auto lifecycleListeners = GetListeners<ILifecycleListener>();
423    for (auto& listener : lifecycleListeners) {
424        if (auto listenerPtr = listener.lock()) {
425            listenerPtr->OnExtensionDied();
426        }
427    }
428}
429
430void Session::NotifyExtensionTimeout(int32_t errorCode)
431{
432    if (!SessionPermission::IsSystemCalling()) {
433        TLOGE(WmsLogTag::WMS_UIEXT, "permission denied!");
434        return;
435    }
436    TLOGI(WmsLogTag::WMS_UIEXT, "NotifyExtensionTimeout(errorCode:%{public}d) in session(persistentId:%{public}d).",
437        errorCode, persistentId_);
438    auto lifecycleListeners = GetListeners<ILifecycleListener>();
439    for (auto& listener : lifecycleListeners) {
440        if (auto listenerPtr = listener.lock()) {
441            listenerPtr->OnExtensionTimeout(errorCode);
442        }
443    }
444}
445
446void Session::NotifyTransferAccessibilityEvent(const Accessibility::AccessibilityEventInfo& info,
447    int64_t uiExtensionIdLevel)
448{
449    auto lifecycleListeners = GetListeners<ILifecycleListener>();
450    for (auto& listener : lifecycleListeners) {
451        if (auto listenerPtr = listener.lock()) {
452            listenerPtr->OnAccessibilityEvent(info, uiExtensionIdLevel);
453        }
454    }
455}
456
457float Session::GetAspectRatio() const
458{
459    return aspectRatio_;
460}
461
462WSError Session::SetAspectRatio(float ratio)
463{
464    aspectRatio_ = ratio;
465    return WSError::WS_OK;
466}
467
468SessionState Session::GetSessionState() const
469{
470    return state_;
471}
472
473void Session::SetSessionState(SessionState state)
474{
475    if (state < SessionState::STATE_DISCONNECT || state > SessionState::STATE_END) {
476        WLOGFD("Invalid session state: %{public}u", state);
477        return;
478    }
479    state_ = state;
480    SetMainSessionUIStateDirty(true);
481}
482
483void Session::UpdateSessionState(SessionState state)
484{
485    // Remove unexecuted detection tasks when the window state changes to background or destroyed.
486    if (state == SessionState::STATE_DISCONNECT ||
487        state == SessionState::STATE_INACTIVE ||
488        state == SessionState::STATE_BACKGROUND) {
489        RemoveWindowDetectTask();
490    }
491    /* The state will be set background first when destroy keyboard, there is no need to notify scb if the state is
492     * already background, which may cause performance deterioration.
493     */
494    if (GetWindowType() == WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT && state == state_ &&
495        state == SessionState::STATE_BACKGROUND) {
496        TLOGI(WmsLogTag::WMS_KEYBOARD, "Keyboard is already hide");
497        return;
498    }
499    state_ = state;
500    SetMainSessionUIStateDirty(true);
501    NotifySessionStateChange(state);
502}
503
504void Session::UpdateSessionTouchable(bool touchable)
505{
506    auto property = GetSessionProperty();
507    if (property == nullptr) {
508        TLOGE(WmsLogTag::WMS_EVENT, "property is null");
509        return;
510    }
511    property->SetTouchable(touchable);
512    NotifySessionTouchableChange(touchable);
513}
514
515WSError Session::SetFocusable(bool isFocusable)
516{
517    WLOGFI("SetFocusable id: %{public}d, focusable: %{public}d", GetPersistentId(), isFocusable);
518    auto property = GetSessionProperty();
519    if (property == nullptr) {
520        TLOGE(WmsLogTag::WMS_EVENT, "property is null");
521        return WSError::WS_ERROR_NULLPTR;
522    }
523    property->SetFocusable(isFocusable);
524    if (isFocused_ && !GetFocusable()) {
525        FocusChangeReason reason = FocusChangeReason::FOCUSABLE;
526        NotifyRequestFocusStatusNotifyManager(false, true, reason);
527    }
528    return WSError::WS_OK;
529}
530
531void Session::SetSystemFocusable(bool systemFocusable)
532{
533    TLOGI(WmsLogTag::WMS_FOCUS, "id: %{public}d, systemFocusable: %{public}d", GetPersistentId(), systemFocusable);
534    systemFocusable_ = systemFocusable;
535    if (isFocused_ && !systemFocusable) {
536        FocusChangeReason reason = FocusChangeReason::FOCUSABLE;
537        NotifyRequestFocusStatusNotifyManager(false, true, reason);
538    }
539}
540
541WSError Session::SetFocusableOnShow(bool isFocusableOnShow)
542{
543    auto task = [weakThis = wptr(this), isFocusableOnShow]() {
544        auto session = weakThis.promote();
545        if (session == nullptr) {
546            TLOGNE(WmsLogTag::WMS_FOCUS, "session is null");
547            return;
548        }
549        TLOGNI(WmsLogTag::WMS_FOCUS, "id: %{public}d, focusableOnShow: %{public}d",
550            session->GetPersistentId(), isFocusableOnShow);
551        session->focusableOnShow_ = isFocusableOnShow;
552    };
553    PostTask(task, __func__);
554    return WSError::WS_OK;
555}
556
557bool Session::GetFocusable() const
558{
559    auto property = GetSessionProperty();
560    if (property) {
561        return property->GetFocusable();
562    }
563    WLOGFD("property is null");
564    return true;
565}
566
567bool Session::GetSystemFocusable() const
568{
569    if (parentSession_) {
570        return systemFocusable_ && parentSession_->GetSystemFocusable();
571    }
572    return systemFocusable_;
573}
574
575bool Session::CheckFocusable() const
576{
577    return GetFocusable() && GetSystemFocusable();
578}
579
580bool Session::IsFocusableOnShow() const
581{
582    return focusableOnShow_;
583}
584
585bool Session::IsFocused() const
586{
587    return isFocused_;
588}
589
590void Session::SetNeedNotify(bool needNotify)
591{
592    needNotify_ = needNotify;
593}
594
595bool Session::NeedNotify() const
596{
597    return needNotify_;
598}
599
600void Session::SetFocusedOnShow(bool focusedOnShow)
601{
602    if (focusedOnShow == focusedOnShow_) {
603        return;
604    }
605    TLOGI(WmsLogTag::WMS_FOCUS, "SetFocusedOnShow:%{public}d, id: %{public}d", focusedOnShow, GetPersistentId());
606    focusedOnShow_ = focusedOnShow;
607}
608
609bool Session::IsFocusedOnShow() const
610{
611    TLOGD(WmsLogTag::WMS_FOCUS, "IsFocusedOnShow:%{public}d, id: %{public}d", focusedOnShow_, GetPersistentId());
612    return focusedOnShow_;
613}
614
615WSError Session::SetTouchable(bool touchable)
616{
617    SetSystemTouchable(touchable);
618    if (!IsSessionValid()) {
619        TLOGW(WmsLogTag::WMS_MAIN, "Session is invalid, id: %{public}d state: %{public}u",
620            GetPersistentId(), GetSessionState());
621        return WSError::WS_ERROR_INVALID_SESSION;
622    }
623    if (touchable != GetSessionProperty()->GetTouchable()) {
624        TLOGI(WmsLogTag::WMS_EVENT, "id:%{public}d touchable:%{public}d", GetPersistentId(),
625            static_cast<int>(touchable));
626    }
627    UpdateSessionTouchable(touchable);
628    return WSError::WS_OK;
629}
630
631bool Session::GetTouchable() const
632{
633    auto property = GetSessionProperty();
634    if (property) {
635        return property->GetTouchable();
636    }
637    TLOGE(WmsLogTag::WMS_EVENT, "property is null");
638    return true;
639}
640
641void Session::SetForceTouchable(bool forceTouchable)
642{
643    if (forceTouchable != forceTouchable_) {
644        TLOGI(WmsLogTag::WMS_EVENT, "id:%{public}d forceTouchable:%{public}d", GetPersistentId(),
645            static_cast<int>(forceTouchable));
646    }
647    forceTouchable_ = forceTouchable;
648}
649
650void Session::SetSystemTouchable(bool touchable)
651{
652    if (touchable != systemTouchable_) {
653        TLOGI(WmsLogTag::WMS_EVENT, "id:%{public}d systemTouchable_:%{public}d", GetPersistentId(),
654            static_cast<int>(touchable));
655    }
656    systemTouchable_ = touchable;
657    NotifySessionInfoChange();
658}
659
660bool Session::GetSystemTouchable() const
661{
662    return forceTouchable_ && systemTouchable_ && GetTouchable();
663}
664
665bool Session::GetRectChangeBySystem() const
666{
667    return rectChangeBySystem_.load();
668}
669
670void Session::SetRectChangeBySystem(bool rectChangeBySystem)
671{
672    if (rectChangeBySystem_.load() != rectChangeBySystem) {
673        rectChangeBySystem_.store(rectChangeBySystem);
674        TLOGI(WmsLogTag::WMS_EVENT, "id:%{public}d rectChangeBySystem_:%{public}d", GetPersistentId(),
675            rectChangeBySystem);
676    }
677}
678
679bool Session::IsSystemActive() const
680{
681    return isSystemActive_;
682}
683
684void Session::SetSystemActive(bool systemActive)
685{
686    isSystemActive_ = systemActive;
687    NotifySessionInfoChange();
688}
689
690WSError Session::SetRSVisible(bool isVisible)
691{
692    isRSVisible_ = isVisible;
693    return WSError::WS_OK;
694}
695
696bool Session::GetRSVisible() const
697{
698    return isRSVisible_;
699}
700
701bool Session::GetFocused() const
702{
703    return isFocused_;
704}
705
706WSError Session::SetVisibilityState(WindowVisibilityState state)
707{
708    visibilityState_ = state;
709    return WSError::WS_OK;
710}
711
712WindowVisibilityState Session::GetVisibilityState() const
713{
714    return visibilityState_;
715}
716
717WSError Session::SetDrawingContentState(bool isRSDrawing)
718{
719    isRSDrawing_ = isRSDrawing;
720    return WSError::WS_OK;
721}
722
723bool Session::GetDrawingContentState() const
724{
725    return isRSDrawing_;
726}
727
728int32_t Session::GetWindowId() const
729{
730    return GetPersistentId();
731}
732
733void Session::SetCallingPid(int32_t id)
734{
735    TLOGI(WmsLogTag::WMS_EVENT, "id:%{public}d, callingPid:%{public}u", persistentId_, id);
736    callingPid_ = id;
737    if (isVisible_) {
738        visibilityChangedDetectFunc_(callingPid_, false, isVisible_);
739    }
740}
741
742void Session::SetCallingUid(int32_t id)
743{
744    callingUid_ = id;
745}
746
747int32_t Session::GetCallingPid() const
748{
749    return callingPid_;
750}
751
752int32_t Session::GetCallingUid() const
753{
754    return callingUid_;
755}
756
757void Session::SetAbilityToken(sptr<IRemoteObject> token)
758{
759    abilityToken_ = token;
760}
761
762sptr<IRemoteObject> Session::GetAbilityToken() const
763{
764    return abilityToken_;
765}
766
767WSError Session::SetBrightness(float brightness)
768{
769    auto property = GetSessionProperty();
770    if (!property) {
771        return WSError::WS_ERROR_NULLPTR;
772    }
773    property->SetBrightness(brightness);
774    return WSError::WS_OK;
775}
776
777float Session::GetBrightness() const
778{
779    auto property = GetSessionProperty();
780    if (!property) {
781        return UNDEFINED_BRIGHTNESS;
782    }
783    return property->GetBrightness();
784}
785
786bool Session::IsSessionValid() const
787{
788    if (sessionInfo_.isSystem_) {
789        WLOGFD("session is system, id: %{public}d, name: %{public}s, state: %{public}u",
790            GetPersistentId(), sessionInfo_.bundleName_.c_str(), GetSessionState());
791        return false;
792    }
793    bool res = state_ > SessionState::STATE_DISCONNECT && state_ < SessionState::STATE_END;
794    return res;
795}
796
797bool Session::IsActive() const
798{
799    return isActive_;
800}
801
802bool Session::IsSystemSession() const
803{
804    return sessionInfo_.isSystem_;
805}
806
807bool Session::IsTerminated() const
808{
809    return (GetSessionState() == SessionState::STATE_DISCONNECT || isTerminating_);
810}
811
812bool Session::IsSessionForeground() const
813{
814    return state_ == SessionState::STATE_FOREGROUND || state_ == SessionState::STATE_ACTIVE;
815}
816
817WSError Session::SetPointerStyle(MMI::WindowArea area)
818{
819    WLOGFI("Information to be set: pid:%{public}d, windowId:%{public}d, MMI::WindowArea:%{public}s",
820        callingPid_, persistentId_, DumpPointerWindowArea(area));
821    MMI::InputManager::GetInstance()->SetWindowPointerStyle(area, callingPid_, persistentId_);
822    return WSError::WS_OK;
823}
824
825WSRectF Session::UpdateTopBottomArea(const WSRectF& rect, MMI::WindowArea area)
826{
827    const float innerBorder = INNER_BORDER_VP * vpr_;
828    const float outsideBorder = OUTSIDE_BORDER_VP * vpr_;
829    const float innerAngle = INNER_ANGLE_VP * vpr_;
830    const float horizontalBorderLength = outsideBorder + innerAngle;
831    const float verticalBorderLength = outsideBorder + innerBorder;
832    const size_t innerAngleCount = 2;
833    WSRectF tbRect;
834    tbRect.posX_ = rect.posX_ + horizontalBorderLength;
835    tbRect.width_ = rect.width_ - horizontalBorderLength * innerAngleCount;
836    tbRect.height_ = verticalBorderLength;
837    if (area == MMI::WindowArea::FOCUS_ON_TOP) {
838        tbRect.posY_ = rect.posY_;
839    } else if (area == MMI::WindowArea::FOCUS_ON_BOTTOM) {
840        tbRect.posY_ = rect.posY_ + rect.height_ - verticalBorderLength;
841    } else {
842        return WSRectF();
843    }
844    return tbRect;
845}
846
847WSRectF Session::UpdateLeftRightArea(const WSRectF& rect, MMI::WindowArea area)
848{
849    const float innerBorder = INNER_BORDER_VP * vpr_;
850    const float outsideBorder = OUTSIDE_BORDER_VP * vpr_;
851    const float innerAngle = INNER_ANGLE_VP * vpr_;
852    const float verticalBorderLength = outsideBorder + innerAngle;
853    const float horizontalBorderLength = outsideBorder + innerBorder;
854    const size_t innerAngleCount = 2;
855    WSRectF lrRect;
856    lrRect.posY_ = rect.posY_ + verticalBorderLength;
857    lrRect.width_ = horizontalBorderLength;
858    lrRect.height_ = rect.height_ - verticalBorderLength * innerAngleCount;
859    if (area == MMI::WindowArea::FOCUS_ON_LEFT) {
860        lrRect.posX_ = rect.posX_;
861    } else if (area == MMI::WindowArea::FOCUS_ON_RIGHT) {
862        lrRect.posX_ = rect.posX_ + rect.width_ - horizontalBorderLength;
863    } else {
864        return WSRectF();
865    }
866    return lrRect;
867}
868
869WSRectF Session::UpdateInnerAngleArea(const WSRectF& rect, MMI::WindowArea area)
870{
871    const float outsideBorder = OUTSIDE_BORDER_VP * vpr_;
872    const float innerAngle = INNER_ANGLE_VP * vpr_;
873    WSRectF iaRect;
874    iaRect.width_ = outsideBorder + innerAngle;
875    iaRect.height_ = outsideBorder + innerAngle;
876    if (area == MMI::WindowArea::FOCUS_ON_TOP_LEFT) {
877        iaRect.posX_ = rect.posX_;
878        iaRect.posY_ = rect.posY_;
879    } else if (area == MMI::WindowArea::FOCUS_ON_TOP_RIGHT) {
880        iaRect.posX_ = rect.posX_ + rect.width_ - iaRect.width_;
881        iaRect.posY_ = rect.posY_;
882    } else if (area == MMI::WindowArea::FOCUS_ON_BOTTOM_LEFT) {
883        iaRect.posX_ = rect.posX_;
884        iaRect.posY_ = rect.posY_ + rect.height_ - iaRect.height_;
885    } else if (area == MMI::WindowArea::FOCUS_ON_BOTTOM_RIGHT) {
886        iaRect.posX_ = rect.posX_ + rect.width_ - iaRect.width_;
887        iaRect.posY_ = rect.posY_ + rect.height_ - iaRect.height_;
888    } else {
889        return WSRectF();
890    }
891    return iaRect;
892}
893
894WSRectF Session::UpdateHotRect(const WSRect& rect)
895{
896    WSRectF newRect;
897    const float outsideBorder = OUTSIDE_BORDER_VP * vpr_;
898    const size_t outsideBorderCount = 2;
899    newRect.posX_ = rect.posX_ - outsideBorder;
900    newRect.posY_ = rect.posY_ - outsideBorder;
901    newRect.width_ = rect.width_ + outsideBorder * outsideBorderCount;
902    newRect.height_ = rect.height_ + outsideBorder * outsideBorderCount;
903    return newRect;
904}
905
906void Session::UpdatePointerArea(const WSRect& rect)
907{
908    if (preRect_ == rect) {
909        WLOGFD("The window area does not change");
910        return;
911    }
912    WSRectF hotRect = UpdateHotRect(rect);
913    for (const auto &[area, _] : windowAreas_) {
914        if (area == MMI::WindowArea::FOCUS_ON_TOP || area == MMI::WindowArea::FOCUS_ON_BOTTOM) {
915            windowAreas_[area] = UpdateTopBottomArea(hotRect, area);
916        } else if (area == MMI::WindowArea::FOCUS_ON_RIGHT || area == MMI::WindowArea::FOCUS_ON_LEFT) {
917            windowAreas_[area] = UpdateLeftRightArea(hotRect, area);
918        } else if (area == MMI::WindowArea::FOCUS_ON_TOP_LEFT || area == MMI::WindowArea::FOCUS_ON_TOP_RIGHT ||
919            area == MMI::WindowArea::FOCUS_ON_BOTTOM_LEFT || area == MMI::WindowArea::FOCUS_ON_BOTTOM_RIGHT) {
920            windowAreas_[area] = UpdateInnerAngleArea(hotRect, area);
921        }
922    }
923    preRect_ = rect;
924}
925
926WSError Session::UpdateSizeChangeReason(SizeChangeReason reason)
927{
928    if (reason_ == reason) {
929        return WSError::WS_DO_NOTHING;
930    }
931    reason_ = reason;
932    return WSError::WS_OK;
933}
934
935WSError Session::UpdateRect(const WSRect& rect, SizeChangeReason reason,
936    const std::string& updateReason, const std::shared_ptr<RSTransaction>& rsTransaction)
937{
938    TLOGD(WmsLogTag::WMS_LAYOUT, "session update rect: id: %{public}d, rect:%{public}s, "
939        "reason:%{public}u %{public}s", GetPersistentId(), rect.ToString().c_str(), reason, updateReason.c_str());
940    if (!IsSessionValid()) {
941        winRect_ = rect;
942        TLOGD(WmsLogTag::WMS_MAIN, "Session is invalid, id: %{public}d state: %{public}u",
943            GetPersistentId(), GetSessionState());
944        return WSError::WS_ERROR_INVALID_SESSION;
945    }
946    winRect_ = rect;
947    if (sessionStage_ != nullptr) {
948        int32_t rotateAnimationDuration = GetRotateAnimationDuration();
949        SceneAnimationConfig config { .rsTransaction_ = rsTransaction, .animationDuration_ = rotateAnimationDuration };
950        sessionStage_->UpdateRect(rect, reason, config);
951        SetClientRect(rect);
952        RectCheckProcess();
953    } else {
954        WLOGFE("sessionStage_ is nullptr");
955    }
956    UpdatePointerArea(winRect_);
957    return WSError::WS_OK;
958}
959
960WSError Session::UpdateDensity()
961{
962    WLOGFI("session update density: id: %{public}d.", GetPersistentId());
963    if (!IsSessionValid()) {
964        TLOGW(WmsLogTag::WMS_MAIN, "Session is invalid, id: %{public}d state: %{public}u",
965            GetPersistentId(), GetSessionState());
966        return WSError::WS_ERROR_INVALID_SESSION;
967    }
968    if (sessionStage_ != nullptr) {
969        sessionStage_->UpdateDensity();
970    } else {
971        WLOGFE("Session::UpdateDensity sessionStage_ is nullptr");
972        return WSError::WS_ERROR_NULLPTR;
973    }
974    return WSError::WS_OK;
975}
976
977WSError Session::UpdateOrientation()
978{
979    TLOGD(WmsLogTag::DMS, "update orientation: id: %{public}d.", GetPersistentId());
980    if (!IsSessionValid()) {
981        TLOGE(WmsLogTag::DMS, "update orientation failed because of session is invalid, id = %{public}d.",
982            GetPersistentId());
983        return WSError::WS_ERROR_INVALID_SESSION;
984    }
985    if (sessionStage_ == nullptr) {
986        TLOGE(WmsLogTag::DMS, "update orientation failed because of sessionStage_ is nullptr, id = %{public}d.",
987            GetPersistentId());
988        return WSError::WS_ERROR_NULLPTR;
989    }
990    return sessionStage_->UpdateOrientation();
991}
992
993__attribute__((no_sanitize("cfi"))) WSError Session::ConnectInner(const sptr<ISessionStage>& sessionStage,
994    const sptr<IWindowEventChannel>& eventChannel,
995    const std::shared_ptr<RSSurfaceNode>& surfaceNode,
996    SystemSessionConfig& systemConfig, sptr<WindowSessionProperty> property,
997    sptr<IRemoteObject> token, int32_t pid, int32_t uid, const std::string& identityToken)
998{
999    TLOGI(WmsLogTag::WMS_LIFE, "ConnectInner session, id: %{public}d, state: %{public}u,"
1000        "isTerminating:%{public}d, callingPid:%{public}d", GetPersistentId(),
1001        static_cast<uint32_t>(GetSessionState()), isTerminating_, pid);
1002    if (GetSessionState() != SessionState::STATE_DISCONNECT && !isTerminating_) {
1003        TLOGE(WmsLogTag::WMS_LIFE, "state is not disconnect state:%{public}u id:%{public}u!",
1004            GetSessionState(), GetPersistentId());
1005        return WSError::WS_ERROR_INVALID_SESSION;
1006    }
1007    if (sessionStage == nullptr || eventChannel == nullptr) {
1008        TLOGE(WmsLogTag::WMS_LIFE, "session stage or eventChannel is nullptr");
1009        return WSError::WS_ERROR_NULLPTR;
1010    }
1011    sessionStage_ = sessionStage;
1012    windowEventChannel_ = eventChannel;
1013    surfaceNode_ = surfaceNode;
1014    abilityToken_ = token;
1015    systemConfig = systemConfig_;
1016    InitSessionPropertyWhenConnect(property);
1017    SetCallingPid(pid);
1018    callingUid_ = uid;
1019    UpdateSessionState(SessionState::STATE_CONNECT);
1020    WindowHelper::IsUIExtensionWindow(GetWindowType()) ? UpdateRect(winRect_, SizeChangeReason::UNDEFINED, "Connect") :
1021        NotifyClientToUpdateRect("Connect", nullptr);
1022    NotifyConnect();
1023    return WSError::WS_OK;
1024}
1025
1026void Session::InitSessionPropertyWhenConnect(const sptr<WindowSessionProperty>& property)
1027{
1028    if (property == nullptr) {
1029        return;
1030    }
1031    auto sessionProperty = GetSessionProperty();
1032    if (sessionProperty && sessionProperty->GetIsNeedUpdateWindowMode() && property) {
1033        property->SetIsNeedUpdateWindowMode(true);
1034        property->SetWindowMode(sessionProperty->GetWindowMode());
1035    }
1036    if (SessionHelper::IsMainWindow(GetWindowType()) && GetSessionInfo().screenId_ != -1 && property) {
1037        property->SetDisplayId(GetSessionInfo().screenId_);
1038    }
1039    InitSystemSessionDragEnable(property);
1040    SetSessionProperty(property);
1041    if (property) {
1042        Rect rect = {winRect_.posX_, winRect_.posY_, static_cast<uint32_t>(winRect_.width_),
1043            static_cast<uint32_t>(winRect_.height_)};
1044        property->SetWindowRect(rect);
1045        property->SetPersistentId(GetPersistentId());
1046        property->SetFullScreenStart(GetSessionInfo().fullScreenStart_);
1047    }
1048    if (sessionProperty && property) {
1049        property->SetRequestedOrientation(sessionProperty->GetRequestedOrientation());
1050        property->SetDefaultRequestedOrientation(sessionProperty->GetDefaultRequestedOrientation());
1051        TLOGI(WmsLogTag::DEFAULT, "windId: %{public}d, requestedOrientation: %{public}u,"
1052            " defaultRequestedOrientation: %{public}u", GetPersistentId(),
1053            static_cast<uint32_t>(sessionProperty->GetRequestedOrientation()),
1054            static_cast<uint32_t>(sessionProperty->GetDefaultRequestedOrientation()));
1055        property->SetCompatibleModeInPc(sessionProperty->GetCompatibleModeInPc());
1056        property->SetIsSupportDragInPcCompatibleMode(sessionProperty->GetIsSupportDragInPcCompatibleMode());
1057        if (sessionProperty->GetCompatibleModeInPc()) {
1058            property->SetDragEnabled(sessionProperty->GetIsSupportDragInPcCompatibleMode());
1059        }
1060        property->SetIsAppSupportPhoneInPc(sessionProperty->GetIsAppSupportPhoneInPc());
1061        property->SetCompatibleModeEnableInPad(sessionProperty->GetCompatibleModeEnableInPad());
1062        property->SetCompatibleWindowSizeInPc(sessionProperty->GetCompatibleInPcPortraitWidth(),
1063            sessionProperty->GetCompatibleInPcPortraitHeight(), sessionProperty->GetCompatibleInPcLandscapeWidth(),
1064            sessionProperty->GetCompatibleInPcLandscapeHeight());
1065    }
1066    if (sessionProperty && SessionHelper::IsMainWindow(GetWindowType())) {
1067        property->SetIsPcAppInPad(sessionProperty->GetIsPcAppInPad());
1068    }
1069}
1070
1071void Session::InitSystemSessionDragEnable(const sptr<WindowSessionProperty>& property)
1072{
1073    auto defaultDragEnable = false;
1074    auto isSystemWindow = WindowHelper::IsSystemWindow(property->GetWindowType());
1075    bool isDialog = WindowHelper::IsDialogWindow(property->GetWindowType());
1076    bool isSubWindow = WindowHelper::IsSubWindow(property->GetWindowType());
1077    bool isSystemCalling = property->GetSystemCalling();
1078    TLOGI(WmsLogTag::WMS_LAYOUT, "windId: %{public}d, defaultDragEnable: %{public}d, isSystemWindow: %{public}d, "
1079        "isDialog: %{public}d, isSubWindow: %{public}d, isSystemCalling: %{public}d", GetPersistentId(),
1080        defaultDragEnable, isSystemWindow, isDialog, isSubWindow, isSystemCalling);
1081    if (isSystemWindow && !isSubWindow && !isDialog && !isSystemCalling) {
1082        property->SetDragEnabled(defaultDragEnable);
1083    }
1084}
1085
1086WSError Session::Reconnect(const sptr<ISessionStage>& sessionStage, const sptr<IWindowEventChannel>& eventChannel,
1087    const std::shared_ptr<RSSurfaceNode>& surfaceNode, sptr<WindowSessionProperty> property, sptr<IRemoteObject> token,
1088    int32_t pid, int32_t uid)
1089{
1090    if (property == nullptr) {
1091        TLOGE(WmsLogTag::WMS_RECOVER, "property is nullptr");
1092        return WSError::WS_ERROR_NULLPTR;
1093    }
1094    TLOGI(WmsLogTag::WMS_RECOVER, "id:%{public}d, state:%{public}u, pid:%{public}d",
1095        property->GetPersistentId(), static_cast<uint32_t>(property->GetWindowState()), pid);
1096    if (sessionStage == nullptr || eventChannel == nullptr) {
1097        TLOGE(WmsLogTag::WMS_RECOVER, "session stage or eventChannel is nullptr");
1098        return WSError::WS_ERROR_NULLPTR;
1099    }
1100    sessionStage_ = sessionStage;
1101    surfaceNode_ = surfaceNode;
1102    windowEventChannel_ = eventChannel;
1103    abilityToken_ = token;
1104    SetSessionProperty(property);
1105    persistentId_ = property->GetPersistentId();
1106    SetCallingPid(pid);
1107    callingUid_ = uid;
1108    bufferAvailable_ = true;
1109    auto windowRect = property->GetWindowRect();
1110    layoutRect_ = { windowRect.posX_, windowRect.posY_,
1111        static_cast<int32_t>(windowRect.width_), static_cast<int32_t>(windowRect.height_) };
1112    UpdateSessionState(SessionState::STATE_CONNECT);
1113    return WSError::WS_OK;
1114}
1115
1116WSError Session::Foreground(sptr<WindowSessionProperty> property, bool isFromClient, const std::string& identityToken)
1117{
1118    HandleDialogForeground();
1119    SessionState state = GetSessionState();
1120    TLOGI(WmsLogTag::WMS_LIFE, "id:%{public}d, state:%{public}u, isTerminating:%{public}d",
1121        GetPersistentId(), static_cast<uint32_t>(state), isTerminating_);
1122    if (state != SessionState::STATE_CONNECT && state != SessionState::STATE_BACKGROUND &&
1123        state != SessionState::STATE_INACTIVE) {
1124        TLOGE(WmsLogTag::WMS_LIFE, "Foreground state invalid! state:%{public}u", state);
1125        return WSError::WS_ERROR_INVALID_SESSION;
1126    }
1127
1128    UpdateSessionState(SessionState::STATE_FOREGROUND);
1129    if (!isActive_) {
1130        SetActive(true);
1131    }
1132    isStarting_ = false;
1133
1134    if (GetWindowType() == WindowType::WINDOW_TYPE_DIALOG && GetParentSession() &&
1135        !GetParentSession()->IsSessionForeground()) {
1136        TLOGD(WmsLogTag::WMS_DIALOG, "parent is not foreground");
1137        SetSessionState(SessionState::STATE_BACKGROUND);
1138    }
1139
1140    NotifyForeground();
1141
1142    isTerminating_ = false;
1143    return WSError::WS_OK;
1144}
1145
1146void Session::HandleDialogBackground()
1147{
1148    const auto& type = GetWindowType();
1149    if (type < WindowType::APP_MAIN_WINDOW_BASE || type >= WindowType::APP_MAIN_WINDOW_END) {
1150        TLOGD(WmsLogTag::WMS_DIALOG, "Current session is not main window, id: %{public}d, type: %{public}d",
1151            GetPersistentId(), type);
1152        return;
1153    }
1154
1155    auto dialogVec = GetDialogVector();
1156    for (const auto& dialog : dialogVec) {
1157        if (dialog == nullptr) {
1158            continue;
1159        }
1160        TLOGI(WmsLogTag::WMS_DIALOG, "Background dialog, id: %{public}d, dialogId: %{public}d",
1161            GetPersistentId(), dialog->GetPersistentId());
1162        dialog->SetSessionState(SessionState::STATE_BACKGROUND);
1163        if (!dialog->sessionStage_) {
1164            TLOGE(WmsLogTag::WMS_DIALOG, "dialog session stage is nullptr");
1165            return;
1166        }
1167        dialog->sessionStage_->NotifyDialogStateChange(false);
1168    }
1169}
1170
1171void Session::HandleDialogForeground()
1172{
1173    const auto& type = GetWindowType();
1174    if (type < WindowType::APP_MAIN_WINDOW_BASE || type >= WindowType::APP_MAIN_WINDOW_END) {
1175        TLOGD(WmsLogTag::WMS_DIALOG, "Current session is not main window, id: %{public}d, type: %{public}d",
1176            GetPersistentId(), type);
1177        return;
1178    }
1179
1180    auto dialogVec = GetDialogVector();
1181    for (const auto& dialog : dialogVec) {
1182        if (dialog == nullptr) {
1183            continue;
1184        }
1185        TLOGI(WmsLogTag::WMS_DIALOG, "Foreground dialog, id: %{public}d, dialogId: %{public}d",
1186            GetPersistentId(), dialog->GetPersistentId());
1187        dialog->SetSessionState(SessionState::STATE_ACTIVE);
1188        if (!dialog->sessionStage_) {
1189            TLOGE(WmsLogTag::WMS_DIALOG, "dialog session stage is nullptr");
1190            return;
1191        }
1192        dialog->sessionStage_->NotifyDialogStateChange(true);
1193    }
1194}
1195
1196WSError Session::Background(bool isFromClient, const std::string& identityToken)
1197{
1198    HandleDialogBackground();
1199    SessionState state = GetSessionState();
1200    TLOGI(WmsLogTag::WMS_LIFE, "Background session, id: %{public}d, state: %{public}" PRIu32, GetPersistentId(),
1201        static_cast<uint32_t>(state));
1202    if (state == SessionState::STATE_ACTIVE && GetWindowType() == WindowType::WINDOW_TYPE_APP_MAIN_WINDOW) {
1203        UpdateSessionState(SessionState::STATE_INACTIVE);
1204        state = SessionState::STATE_INACTIVE;
1205        isActive_ = false;
1206    }
1207    isStarting_ = false;
1208    if (state != SessionState::STATE_INACTIVE) {
1209        TLOGW(WmsLogTag::WMS_LIFE, "Background state invalid! id: %{public}d, state: %{public}u",
1210            GetPersistentId(), state);
1211        return WSError::WS_ERROR_INVALID_SESSION;
1212    }
1213    UpdateSessionState(SessionState::STATE_BACKGROUND);
1214    NotifyBackground();
1215    return WSError::WS_OK;
1216}
1217
1218void Session::ResetSessionConnectState()
1219{
1220    TLOGI(WmsLogTag::WMS_LIFE, "ResetSessionState, id: %{public}d, state: %{public}u",
1221        GetPersistentId(), GetSessionState());
1222    SetSessionState(SessionState::STATE_DISCONNECT);
1223    SetCallingPid(-1);
1224}
1225
1226void Session::ResetIsActive()
1227{
1228    TLOGI(WmsLogTag::WMS_LIFE, "id: %{public}d, isActive: %{public}u",
1229        GetPersistentId(), IsActive());
1230    isActive_ = false;
1231}
1232
1233WSError Session::Disconnect(bool isFromClient, const std::string& identityToken)
1234{
1235    auto state = GetSessionState();
1236    TLOGI(WmsLogTag::WMS_LIFE, "Disconnect session, id: %{public}d, state: %{public}u", GetPersistentId(), state);
1237    isActive_ = false;
1238    isStarting_ = false;
1239    bufferAvailable_ = false;
1240    if (mainHandler_) {
1241        mainHandler_->PostTask([surfaceNode = std::move(surfaceNode_)]() mutable {
1242            surfaceNode.reset();
1243        });
1244    }
1245    UpdateSessionState(SessionState::STATE_BACKGROUND);
1246    UpdateSessionState(SessionState::STATE_DISCONNECT);
1247    NotifyDisconnect();
1248    if (visibilityChangedDetectFunc_) {
1249        visibilityChangedDetectFunc_(GetCallingPid(), isVisible_, false);
1250    }
1251    return WSError::WS_OK;
1252}
1253
1254WSError Session::Show(sptr<WindowSessionProperty> property)
1255{
1256    TLOGD(WmsLogTag::WMS_LIFE, "Show session, id: %{public}d", GetPersistentId());
1257    return WSError::WS_OK;
1258}
1259
1260WSError Session::Hide()
1261{
1262    TLOGD(WmsLogTag::WMS_LIFE, "Hide session, id: %{public}d", GetPersistentId());
1263    return WSError::WS_OK;
1264}
1265
1266WSError Session::DrawingCompleted()
1267{
1268    TLOGD(WmsLogTag::WMS_LIFE, "id: %{public}d", GetPersistentId());
1269    if (!SessionPermission::IsSameAppAsCalling(SHELL_BUNDLE_NAME, SHELL_APP_IDENTIFIER)) {
1270        TLOGE(WmsLogTag::WMS_LIFE, "permission denied!");
1271        return WSError::WS_ERROR_INVALID_PERMISSION;
1272    }
1273    auto lifecycleListeners = GetListeners<ILifecycleListener>();
1274    for (auto& listener : lifecycleListeners) {
1275        if (auto listenerPtr = listener.lock()) {
1276            listenerPtr->OnDrawingCompleted();
1277        }
1278    }
1279    return WSError::WS_OK;
1280}
1281
1282WSError Session::SetActive(bool active)
1283{
1284    SessionState state = GetSessionState();
1285    TLOGI(WmsLogTag::WMS_LIFE, "new active:%{public}d, id:%{public}d, state:%{public}u",
1286        active, GetPersistentId(), static_cast<uint32_t>(state));
1287    if (!IsSessionValid()) {
1288        TLOGW(WmsLogTag::WMS_LIFE, "Session is invalid, id: %{public}d state: %{public}u",
1289            GetPersistentId(), GetSessionState());
1290        return WSError::WS_ERROR_INVALID_SESSION;
1291    }
1292    if (active == isActive_) {
1293        TLOGD(WmsLogTag::WMS_LIFE, "Session active do not change: [%{public}d]", active);
1294        return WSError::WS_DO_NOTHING;
1295    }
1296    if (!sessionStage_) {
1297        TLOGE(WmsLogTag::WMS_LIFE, "session stage is nullptr");
1298        return WSError::WS_ERROR_NULLPTR;
1299    }
1300    if (active && GetSessionState() == SessionState::STATE_FOREGROUND) {
1301        sessionStage_->SetActive(true);
1302        UpdateSessionState(SessionState::STATE_ACTIVE);
1303        isActive_ = active;
1304    }
1305    if (!active && GetSessionState() == SessionState::STATE_ACTIVE) {
1306        sessionStage_->SetActive(false);
1307        UpdateSessionState(SessionState::STATE_INACTIVE);
1308        isActive_ = active;
1309    }
1310    return WSError::WS_OK;
1311}
1312
1313void Session::ProcessClickModalSpecificWindowOutside(int32_t posX, int32_t posY)
1314{
1315    if (clickModalSpecificWindowOutsideFunc_ && !winRect_.IsInRegion(posX, posY)) {
1316        clickModalSpecificWindowOutsideFunc_();
1317    }
1318}
1319
1320void Session::SetClickModalSpecificWindowOutsideListener(const NotifyClickModalSpecificWindowOutsideFunc& func)
1321{
1322    clickModalSpecificWindowOutsideFunc_ = func;
1323}
1324
1325void Session::NotifyForegroundInteractiveStatus(bool interactive)
1326{
1327    SetForegroundInteractiveStatus(interactive);
1328}
1329
1330void Session::SetForegroundInteractiveStatus(bool interactive)
1331{
1332    if (interactive != GetForegroundInteractiveStatus()) {
1333        TLOGI(WmsLogTag::WMS_EVENT, "id:%{public}d interactive:%{public}d", GetPersistentId(),
1334            static_cast<int>(interactive));
1335    }
1336    foregroundInteractiveStatus_.store(interactive);
1337    if (Session::IsScbCoreEnabled()) {
1338        return;
1339    }
1340    NotifySessionInfoChange();
1341}
1342
1343bool Session::GetForegroundInteractiveStatus() const
1344{
1345    return foregroundInteractiveStatus_.load();
1346}
1347
1348void Session::SetAttachState(bool isAttach, WindowMode windowMode)
1349{
1350    isAttach_ = isAttach;
1351    auto task = [weakThis = wptr(this), isAttach]() {
1352        auto session = weakThis.promote();
1353        if (session == nullptr) {
1354            TLOGD(WmsLogTag::WMS_LIFE, "session is null");
1355            return;
1356        }
1357        TLOGD(WmsLogTag::WMS_LIFE, "isAttach:%{public}d persistentId:%{public}d", isAttach,
1358            session->GetPersistentId());
1359        if (!isAttach && session->detachCallback_ != nullptr) {
1360            TLOGI(WmsLogTag::WMS_LIFE, "Session detach, persistentId:%{public}d", session->GetPersistentId());
1361            session->detachCallback_->OnPatternDetach(session->GetPersistentId());
1362            session->detachCallback_ = nullptr;
1363        }
1364    };
1365    PostTask(task, "SetAttachState");
1366    CreateDetectStateTask(isAttach, windowMode);
1367}
1368
1369void Session::CreateDetectStateTask(bool isAttach, WindowMode windowMode)
1370{
1371    if (!IsSupportDetectWindow(isAttach)) {
1372        return;
1373    }
1374    if (showRecent_) {
1375        return;
1376    }
1377    if (!ShouldCreateDetectTask(isAttach, windowMode)) {
1378        RemoveWindowDetectTask();
1379        DetectTaskInfo detectTaskInfo;
1380        SetDetectTaskInfo(detectTaskInfo);
1381        return;
1382    }
1383    CreateWindowStateDetectTask(isAttach, windowMode);
1384}
1385
1386void Session::RegisterDetachCallback(const sptr<IPatternDetachCallback>& callback)
1387{
1388    detachCallback_ = callback;
1389    if (!isAttach_ && detachCallback_ != nullptr) {
1390        TLOGI(WmsLogTag::WMS_LIFE, "Session detach before register, persistentId:%{public}d", GetPersistentId());
1391        detachCallback_->OnPatternDetach(GetPersistentId());
1392        detachCallback_ = nullptr;
1393    }
1394}
1395
1396void Session::SetChangeSessionVisibilityWithStatusBarEventListener(
1397    const NotifyChangeSessionVisibilityWithStatusBarFunc& func)
1398{
1399    changeSessionVisibilityWithStatusBarFunc_ = func;
1400}
1401
1402void Session::SetPendingSessionActivationEventListener(const NotifyPendingSessionActivationFunc& func)
1403{
1404    pendingSessionActivationFunc_ = func;
1405}
1406
1407void Session::SetBackPressedListenser(const NotifyBackPressedFunc& func)
1408{
1409    backPressedFunc_ = func;
1410}
1411
1412void Session::SetTerminateSessionListener(const NotifyTerminateSessionFunc& func)
1413{
1414    terminateSessionFunc_ = func;
1415}
1416
1417void Session::RemoveLifeCycleTask(const LifeCycleTaskType& taskType)
1418{
1419    std::lock_guard<std::mutex> lock(lifeCycleTaskQueueMutex_);
1420    if (lifeCycleTaskQueue_.empty()) {
1421        return;
1422    }
1423    sptr<SessionLifeCycleTask> currLifeCycleTask = lifeCycleTaskQueue_.front();
1424    if (currLifeCycleTask->type != taskType) {
1425        TLOGW(WmsLogTag::WMS_LIFE, "not match, current running taskName=%{public}s, PersistentId=%{public}d",
1426            currLifeCycleTask->name.c_str(), persistentId_);
1427        return;
1428    }
1429    TLOGI(WmsLogTag::WMS_LIFE, "Removed lifeCyleTask %{public}s. PersistentId=%{public}d",
1430        currLifeCycleTask->name.c_str(), persistentId_);
1431    lifeCycleTaskQueue_.pop_front();
1432    if (lifeCycleTaskQueue_.empty()) {
1433        return;
1434    }
1435    StartLifeCycleTask(lifeCycleTaskQueue_.front());
1436}
1437
1438void Session::PostLifeCycleTask(Task&& task, const std::string& name, const LifeCycleTaskType& taskType)
1439{
1440    std::lock_guard<std::mutex> lock(lifeCycleTaskQueueMutex_);
1441    if (!lifeCycleTaskQueue_.empty()) {
1442        // remove current running task if expired
1443        sptr<SessionLifeCycleTask> currLifeCycleTask = lifeCycleTaskQueue_.front();
1444        std::chrono::steady_clock::time_point currentTime = std::chrono::steady_clock::now();
1445        bool isCurrentTaskExpired =
1446            std::chrono::duration_cast<std::chrono::milliseconds>(currentTime - currLifeCycleTask->startTime).count() >
1447            LIFE_CYCLE_TASK_EXPIRED_TIME_LIMIT;
1448        if (isCurrentTaskExpired) {
1449            TLOGE(WmsLogTag::WMS_LIFE, "Remove expired LifeCycleTask %{public}s. PersistentId=%{public}d",
1450                currLifeCycleTask->name.c_str(), persistentId_);
1451            lifeCycleTaskQueue_.pop_front();
1452        }
1453    }
1454
1455    if (lifeCycleTaskQueue_.size() == MAX_LIFE_CYCLE_TASK_IN_QUEUE) {
1456        TLOGE(WmsLogTag::WMS_LIFE, "Failed to add task %{public}s to life cycle queue", name.c_str());
1457        return;
1458    }
1459    sptr<SessionLifeCycleTask> lifeCycleTask = sptr<SessionLifeCycleTask>::MakeSptr(std::move(task), name, taskType);
1460    lifeCycleTaskQueue_.push_back(lifeCycleTask);
1461    TLOGI(WmsLogTag::WMS_LIFE, "Add task %{public}s to life cycle queue, PersistentId=%{public}d",
1462        name.c_str(), persistentId_);
1463    if (lifeCycleTaskQueue_.size() == 1) {
1464        StartLifeCycleTask(lifeCycleTask);
1465        return;
1466    }
1467
1468    StartLifeCycleTask(lifeCycleTaskQueue_.front());
1469}
1470
1471void Session::StartLifeCycleTask(sptr<SessionLifeCycleTask> lifeCycleTask)
1472{
1473    if (lifeCycleTask->running) {
1474        return;
1475    }
1476    TLOGI(WmsLogTag::WMS_LIFE, "Execute LifeCycleTask %{public}s. PersistentId: %{public}d",
1477        lifeCycleTask->name.c_str(), persistentId_);
1478    lifeCycleTask->running = true;
1479    lifeCycleTask->startTime = std::chrono::steady_clock::now();
1480    PostTask(std::move(lifeCycleTask->task), lifeCycleTask->name);
1481}
1482
1483WSError Session::TerminateSessionNew(
1484    const sptr<AAFwk::SessionInfo> abilitySessionInfo, bool needStartCaller, bool isFromBroker)
1485{
1486    if (abilitySessionInfo == nullptr) {
1487        TLOGE(WmsLogTag::WMS_LIFE, "abilitySessionInfo is null");
1488        return WSError::WS_ERROR_INVALID_SESSION;
1489    }
1490    auto task = [weakThis = wptr(this), abilitySessionInfo, needStartCaller, isFromBroker]() {
1491        auto session = weakThis.promote();
1492        if (session == nullptr) {
1493            TLOGI(WmsLogTag::WMS_LIFE, "session is null.");
1494            return;
1495        }
1496        session->isTerminating_ = true;
1497        SessionInfo info;
1498        info.abilityName_ = abilitySessionInfo->want.GetElement().GetAbilityName();
1499        info.bundleName_ = abilitySessionInfo->want.GetElement().GetBundleName();
1500        info.callerToken_ = abilitySessionInfo->callerToken;
1501        info.persistentId_ = static_cast<int32_t>(abilitySessionInfo->persistentId);
1502        {
1503            std::lock_guard<std::recursive_mutex> lock(session->sessionInfoMutex_);
1504            session->sessionInfo_.closeAbilityWant = std::make_shared<AAFwk::Want>(abilitySessionInfo->want);
1505            session->sessionInfo_.resultCode = abilitySessionInfo->resultCode;
1506        }
1507        if (session->terminateSessionFuncNew_) {
1508            session->terminateSessionFuncNew_(info, needStartCaller, isFromBroker);
1509        }
1510        TLOGI(WmsLogTag::WMS_LIFE,
1511            "TerminateSessionNew, id: %{public}d, needStartCaller: %{public}d, isFromBroker: %{public}d",
1512            session->GetPersistentId(), needStartCaller, isFromBroker);
1513    };
1514    PostLifeCycleTask(task, "TerminateSessionNew", LifeCycleTaskType::STOP);
1515    return WSError::WS_OK;
1516}
1517
1518void Session::SetTerminateSessionListenerNew(const NotifyTerminateSessionFuncNew& func)
1519{
1520    terminateSessionFuncNew_ = func;
1521}
1522
1523WSError Session::TerminateSessionTotal(const sptr<AAFwk::SessionInfo> abilitySessionInfo, TerminateType terminateType)
1524{
1525    if (abilitySessionInfo == nullptr) {
1526        TLOGE(WmsLogTag::WMS_LIFE, "abilitySessionInfo is null");
1527        return WSError::WS_ERROR_INVALID_SESSION;
1528    }
1529    if (isTerminating_) {
1530        TLOGE(WmsLogTag::WMS_LIFE, "is terminating, return!");
1531        return WSError::WS_ERROR_INVALID_OPERATION;
1532    }
1533    isTerminating_ = true;
1534    SessionInfo info;
1535    info.abilityName_ = abilitySessionInfo->want.GetElement().GetAbilityName();
1536    info.bundleName_ = abilitySessionInfo->want.GetElement().GetBundleName();
1537    info.callerToken_ = abilitySessionInfo->callerToken;
1538    info.persistentId_ = static_cast<int32_t>(abilitySessionInfo->persistentId);
1539    {
1540        std::lock_guard<std::recursive_mutex> lock(sessionInfoMutex_);
1541        sessionInfo_.closeAbilityWant = std::make_shared<AAFwk::Want>(abilitySessionInfo->want);
1542        sessionInfo_.resultCode = abilitySessionInfo->resultCode;
1543    }
1544    if (terminateSessionFuncTotal_) {
1545        terminateSessionFuncTotal_(info, terminateType);
1546    }
1547    return WSError::WS_OK;
1548}
1549
1550void Session::SetTerminateSessionListenerTotal(const NotifyTerminateSessionFuncTotal& func)
1551{
1552    terminateSessionFuncTotal_ = func;
1553}
1554
1555WSError Session::SetSessionLabel(const std::string& label)
1556{
1557    WLOGFI("run Session::SetSessionLabel");
1558    if (updateSessionLabelFunc_) {
1559        updateSessionLabelFunc_(label);
1560    }
1561    return WSError::WS_OK;
1562}
1563
1564void Session::SetUpdateSessionLabelListener(const NofitySessionLabelUpdatedFunc& func)
1565{
1566    updateSessionLabelFunc_ = func;
1567}
1568
1569WSError Session::SetSessionIcon(const std::shared_ptr<Media::PixelMap>& icon)
1570{
1571    WLOGFD("run Session::SetSessionIcon, id: %{public}d", GetPersistentId());
1572    if (scenePersistence_ == nullptr) {
1573        WLOGFE("scenePersistence_ is nullptr.");
1574        return WSError::WS_ERROR_INVALID_OPERATION;
1575    }
1576    scenePersistence_->SaveUpdatedIcon(icon);
1577    std::string updatedIconPath = scenePersistence_->GetUpdatedIconPath();
1578    if (updateSessionIconFunc_) {
1579        updateSessionIconFunc_(updatedIconPath);
1580    }
1581    return WSError::WS_OK;
1582}
1583
1584void Session::SetUpdateSessionIconListener(const NofitySessionIconUpdatedFunc& func)
1585{
1586    updateSessionIconFunc_ = func;
1587}
1588
1589WSError Session::Clear(bool needStartCaller)
1590{
1591    TLOGI(WmsLogTag::WMS_LIFE, "id:%{public}d, needStartCaller:%{public}u", GetPersistentId(), needStartCaller);
1592    auto task = [weakThis = wptr(this), needStartCaller]() {
1593        auto session = weakThis.promote();
1594        if (session == nullptr) {
1595            TLOGNE(WmsLogTag::WMS_LIFE, "session is null");
1596            return;
1597        }
1598        session->isTerminating_ = true;
1599        SessionInfo info = session->GetSessionInfo();
1600        if (session->terminateSessionFuncNew_) {
1601            session->terminateSessionFuncNew_(info, needStartCaller, false);
1602        }
1603    };
1604    PostLifeCycleTask(task, "Clear", LifeCycleTaskType::STOP);
1605    return WSError::WS_OK;
1606}
1607
1608void Session::SetSessionExceptionListener(const NotifySessionExceptionFunc& func, bool fromJsScene)
1609{
1610    if (func == nullptr) {
1611        WLOGFE("func is nullptr");
1612        return;
1613    }
1614    std::shared_ptr<NotifySessionExceptionFunc> funcSptr = std::make_shared<NotifySessionExceptionFunc>(func);
1615    if (fromJsScene) {
1616        jsSceneSessionExceptionFunc_ = funcSptr;
1617    } else {
1618        sessionExceptionFunc_ = funcSptr;
1619    }
1620}
1621
1622void Session::SetSessionSnapshotListener(const NotifySessionSnapshotFunc& func)
1623{
1624    if (func == nullptr) {
1625        WLOGFE("func is nullptr");
1626        return;
1627    }
1628    notifySessionSnapshotFunc_ = func;
1629}
1630
1631void Session::SetPendingSessionToForegroundListener(const NotifyPendingSessionToForegroundFunc& func)
1632{
1633    pendingSessionToForegroundFunc_ = func;
1634}
1635
1636WSError Session::PendingSessionToForeground()
1637{
1638    TLOGI(WmsLogTag::WMS_LIFE, "id: %{public}d", GetPersistentId());
1639    SessionInfo info = GetSessionInfo();
1640    if (pendingSessionActivationFunc_) {
1641        pendingSessionActivationFunc_(info);
1642    }
1643    return WSError::WS_OK;
1644}
1645
1646void Session::SetPendingSessionToBackgroundForDelegatorListener(
1647    const NotifyPendingSessionToBackgroundForDelegatorFunc& func)
1648{
1649    pendingSessionToBackgroundForDelegatorFunc_ = func;
1650}
1651
1652WSError Session::PendingSessionToBackgroundForDelegator(bool shouldBackToCaller)
1653{
1654    TLOGI(WmsLogTag::WMS_LIFE, "id: %{public}d, shouldBackToCaller: %{public}d",
1655        GetPersistentId(), shouldBackToCaller);
1656    SessionInfo info = GetSessionInfo();
1657    if (pendingSessionToBackgroundForDelegatorFunc_) {
1658        pendingSessionToBackgroundForDelegatorFunc_(info, shouldBackToCaller);
1659    }
1660    return WSError::WS_OK;
1661}
1662
1663void Session::SetLeashWindowSurfaceNodeChangedListener(const NotifyLeashWindowSurfaceNodeChangedFunc& func)
1664{
1665    leashWindowSurfaceNodeChangedFunc_ = func;
1666}
1667
1668void Session::SetRaiseToAppTopForPointDownFunc(const NotifyRaiseToTopForPointDownFunc& func)
1669{
1670    raiseToTopForPointDownFunc_ = func;
1671}
1672
1673void Session::NotifyScreenshot()
1674{
1675    if (!sessionStage_) {
1676        return;
1677    }
1678    sessionStage_->NotifyScreenshot();
1679}
1680
1681WSError Session::NotifyCloseExistPipWindow()
1682{
1683    if (!sessionStage_) {
1684        return WSError::WS_ERROR_NULLPTR;
1685    }
1686    return sessionStage_->NotifyCloseExistPipWindow();
1687}
1688
1689WSError Session::NotifyDestroy()
1690{
1691    if (!sessionStage_) {
1692        return WSError::WS_ERROR_NULLPTR;
1693    }
1694    return sessionStage_->NotifyDestroy();
1695}
1696
1697void Session::SetParentSession(const sptr<Session>& session)
1698{
1699    if (session == nullptr) {
1700        WLOGFW("Session is nullptr");
1701        return;
1702    }
1703    {
1704        std::unique_lock<std::shared_mutex> lock(parentSessionMutex_);
1705        parentSession_ = session;
1706    }
1707    TLOGD(WmsLogTag::WMS_SUB, "[WMSDialog][WMSSub]Set parent success, parentId: %{public}d, id: %{public}d",
1708        session->GetPersistentId(), GetPersistentId());
1709}
1710
1711sptr<Session> Session::GetParentSession() const
1712{
1713    std::shared_lock<std::shared_mutex> lock(parentSessionMutex_);
1714    return parentSession_;
1715}
1716
1717sptr<Session> Session::GetMainSession()
1718{
1719    if (SessionHelper::IsMainWindow(GetWindowType())) {
1720        return this;
1721    } else if (parentSession_) {
1722        return parentSession_->GetMainSession();
1723    } else {
1724        return nullptr;
1725    }
1726}
1727
1728void Session::BindDialogToParentSession(const sptr<Session>& session)
1729{
1730    std::unique_lock<std::shared_mutex> lock(dialogVecMutex_);
1731    auto iter = std::find(dialogVec_.begin(), dialogVec_.end(), session);
1732    if (iter != dialogVec_.end()) {
1733        TLOGW(WmsLogTag::WMS_DIALOG, "Dialog is existed in parentVec, id: %{public}d, parentId: %{public}d",
1734            session->GetPersistentId(), GetPersistentId());
1735        return;
1736    }
1737    dialogVec_.push_back(session);
1738    TLOGD(WmsLogTag::WMS_DIALOG, "Bind dialog success, id: %{public}d, parentId: %{public}d",
1739        session->GetPersistentId(), GetPersistentId());
1740}
1741
1742void Session::RemoveDialogToParentSession(const sptr<Session>& session)
1743{
1744    std::unique_lock<std::shared_mutex> lock(dialogVecMutex_);
1745    auto iter = std::find(dialogVec_.begin(), dialogVec_.end(), session);
1746    if (iter != dialogVec_.end()) {
1747        TLOGD(WmsLogTag::WMS_DIALOG, "Remove dialog success, id: %{public}d, parentId: %{public}d",
1748            session->GetPersistentId(), GetPersistentId());
1749        dialogVec_.erase(iter);
1750    }
1751    TLOGW(WmsLogTag::WMS_DIALOG, "Remove dialog failed, id: %{public}d, parentId: %{public}d",
1752        session->GetPersistentId(), GetPersistentId());
1753}
1754
1755std::vector<sptr<Session>> Session::GetDialogVector() const
1756{
1757    std::shared_lock<std::shared_mutex> lock(dialogVecMutex_);
1758    return dialogVec_;
1759}
1760
1761void Session::ClearDialogVector()
1762{
1763    std::unique_lock<std::shared_mutex> lock(dialogVecMutex_);
1764    dialogVec_.clear();
1765    TLOGD(WmsLogTag::WMS_DIALOG, "parentId: %{public}d", GetPersistentId());
1766    return;
1767}
1768
1769bool Session::CheckDialogOnForeground()
1770{
1771    auto dialogVec = GetDialogVector();
1772    if (dialogVec.empty()) {
1773        TLOGD(WmsLogTag::WMS_DIALOG, "Dialog is empty, id: %{public}d", GetPersistentId());
1774        return false;
1775    }
1776    for (auto iter = dialogVec.rbegin(); iter != dialogVec.rend(); iter++) {
1777        auto dialogSession = *iter;
1778        if (dialogSession && (dialogSession->GetSessionState() == SessionState::STATE_ACTIVE ||
1779            dialogSession->GetSessionState() == SessionState::STATE_FOREGROUND)) {
1780            TLOGD(WmsLogTag::WMS_DIALOG, "Notify touch dialog window, id: %{public}d", GetPersistentId());
1781            return true;
1782        }
1783    }
1784    return false;
1785}
1786
1787bool Session::CheckPointerEventDispatch(const std::shared_ptr<MMI::PointerEvent>& pointerEvent) const
1788{
1789    return true;
1790}
1791
1792bool Session::IsTopDialog() const
1793{
1794    int32_t currentPersistentId = GetPersistentId();
1795    auto parentSession = GetParentSession();
1796    if (parentSession == nullptr) {
1797        TLOGW(WmsLogTag::WMS_DIALOG, "Dialog's Parent is NULL. id: %{public}d", currentPersistentId);
1798        return false;
1799    }
1800    auto parentDialogVec = parentSession->GetDialogVector();
1801    if (parentDialogVec.size() <= 1) {
1802        return true;
1803    }
1804    for (auto iter = parentDialogVec.rbegin(); iter != parentDialogVec.rend(); iter++) {
1805        auto dialogSession = *iter;
1806        if (dialogSession && (dialogSession->GetSessionState() == SessionState::STATE_ACTIVE ||
1807            dialogSession->GetSessionState() == SessionState::STATE_FOREGROUND)) {
1808            WLOGFI("Dialog id: %{public}d, current dialog id: %{public}d", dialogSession->GetPersistentId(),
1809                currentPersistentId);
1810            return dialogSession->GetPersistentId() == currentPersistentId;
1811        }
1812    }
1813    return false;
1814}
1815
1816const char* Session::DumpPointerWindowArea(MMI::WindowArea area) const
1817{
1818    const std::map<MMI::WindowArea, const char*> areaMap = {
1819        { MMI::WindowArea::FOCUS_ON_INNER, "FOCUS_ON_INNER" },
1820        { MMI::WindowArea::FOCUS_ON_TOP, "FOCUS_ON_TOP" },
1821        { MMI::WindowArea::FOCUS_ON_BOTTOM, "FOCUS_ON_BOTTOM" },
1822        { MMI::WindowArea::FOCUS_ON_LEFT, "FOCUS_ON_LEFT" },
1823        { MMI::WindowArea::FOCUS_ON_RIGHT, "FOCUS_ON_RIGHT" },
1824        { MMI::WindowArea::FOCUS_ON_BOTTOM_LEFT, "FOCUS_ON_BOTTOM_LEFT" },
1825        { MMI::WindowArea::FOCUS_ON_BOTTOM_RIGHT, "FOCUS_ON_BOTTOM_RIGHT" },
1826        { MMI::WindowArea::FOCUS_ON_TOP_LEFT, "FOCUS_ON_TOP_LEFT" },
1827        { MMI::WindowArea::FOCUS_ON_TOP_RIGHT, "FOCUS_ON_TOP_RIGHT" },
1828        { MMI::WindowArea::EXIT, "EXIT" }
1829    };
1830    auto iter = areaMap.find(area);
1831    if (iter == areaMap.end()) {
1832        return "UNKNOWN";
1833    }
1834    return iter->second;
1835}
1836
1837WSError Session::RaiseToAppTopForPointDown()
1838{
1839    if (raiseToTopForPointDownFunc_) {
1840        raiseToTopForPointDownFunc_();
1841        WLOGFD("RaiseToAppTopForPointDown, id: %{public}d, type: %{public}d", GetPersistentId(), GetWindowType());
1842    }
1843    return WSError::WS_OK;
1844}
1845
1846void Session::PresentFocusIfPointDown()
1847{
1848    WLOGFI("id: %{public}d,type: %{public}d", GetPersistentId(), GetWindowType());
1849    if (!isFocused_ && GetFocusable()) {
1850        FocusChangeReason reason = FocusChangeReason::CLICK;
1851        NotifyRequestFocusStatusNotifyManager(true, false, reason);
1852    }
1853    NotifyClick();
1854}
1855
1856void Session::HandlePointDownDialog()
1857{
1858    auto dialogVec = GetDialogVector();
1859    sptr<Session> lastValidDialog = nullptr;
1860    for (auto dialog : dialogVec) {
1861        if (dialog && (dialog->GetSessionState() == SessionState::STATE_FOREGROUND ||
1862            dialog->GetSessionState() == SessionState::STATE_ACTIVE)) {
1863            dialog->RaiseToAppTopForPointDown();
1864            lastValidDialog = dialog;
1865            TLOGD(WmsLogTag::WMS_DIALOG, "Point main window, raise to top and dialog need focus, "
1866                "id: %{public}d, dialogId: %{public}d", GetPersistentId(), dialog->GetPersistentId());
1867        }
1868    }
1869    if (lastValidDialog != nullptr) {
1870        lastValidDialog->PresentFocusIfPointDown();
1871    }
1872}
1873
1874WSError Session::HandleSubWindowClick(int32_t action)
1875{
1876    auto parentSession = GetParentSession();
1877    if (parentSession && parentSession->CheckDialogOnForeground()) {
1878        TLOGD(WmsLogTag::WMS_DIALOG, "Its main window has dialog on foreground, id: %{public}d", GetPersistentId());
1879        return WSError::WS_ERROR_INVALID_PERMISSION;
1880    }
1881    auto property = GetSessionProperty();
1882    if (property == nullptr) {
1883        TLOGE(WmsLogTag::WMS_EVENT, "property is null");
1884        return WSError::WS_ERROR_NULLPTR;
1885    }
1886    bool raiseEnabled = property->GetRaiseEnabled() &&
1887        (action == MMI::PointerEvent::POINTER_ACTION_DOWN || action == MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN);
1888    if (raiseEnabled) {
1889        RaiseToAppTopForPointDown();
1890    } else if (parentSession) {
1891        // sub window is forbidden to raise to top after click, but its parent should raise
1892        parentSession->NotifyClick(!IsScbCoreEnabled());
1893    }
1894    return WSError::WS_OK;
1895}
1896
1897WSError Session::TransferPointerEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent, bool needNotifyClient)
1898{
1899    WLOGFD("Session TransferPointEvent, id: %{public}d", GetPersistentId());
1900    if (!IsSystemSession() && !IsSessionValid()) {
1901        return WSError::WS_ERROR_INVALID_SESSION;
1902    }
1903    if (pointerEvent == nullptr) {
1904        WLOGFE("PointerEvent is nullptr");
1905        return WSError::WS_ERROR_NULLPTR;
1906    }
1907    auto pointerAction = pointerEvent->GetPointerAction();
1908    bool isPointDown = (pointerAction == MMI::PointerEvent::POINTER_ACTION_DOWN) ||
1909        (pointerAction == MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN);
1910    if (GetWindowType() == WindowType::WINDOW_TYPE_APP_MAIN_WINDOW) {
1911        if (CheckDialogOnForeground() && isPointDown) {
1912            HandlePointDownDialog();
1913            return WSError::WS_ERROR_INVALID_PERMISSION;
1914        }
1915    } else if (GetWindowType() == WindowType::WINDOW_TYPE_APP_SUB_WINDOW) {
1916        WSError ret = HandleSubWindowClick(pointerAction);
1917        if (ret != WSError::WS_OK) {
1918            return ret;
1919        }
1920    } else if (GetWindowType() == WindowType::WINDOW_TYPE_DIALOG) {
1921        auto parentSession = GetParentSession();
1922        if (parentSession && parentSession->CheckDialogOnForeground() && isPointDown) {
1923            parentSession->HandlePointDownDialog();
1924            if (!IsTopDialog()) {
1925                TLOGI(WmsLogTag::WMS_DIALOG, "There is at least one active dialog upon this dialog, id: %{public}d",
1926                    GetPersistentId());
1927                return WSError::WS_ERROR_INVALID_PERMISSION;
1928            }
1929        }
1930    }
1931    PresentFoucusIfNeed(pointerAction);
1932    if (!windowEventChannel_) {
1933        if (!IsSystemSession()) {
1934            WLOGFE("windowEventChannel_ is null");
1935        }
1936        return WSError::WS_ERROR_NULLPTR;
1937    }
1938
1939    if (needNotifyClient) {
1940        WSError ret = windowEventChannel_->TransferPointerEvent(pointerEvent);
1941        if (ret != WSError::WS_OK) {
1942            WLOGFE("InputTracking id:%{public}d, TransferPointer failed, ret:%{public}d ",
1943                pointerEvent->GetId(), ret);
1944        }
1945        return ret;
1946    } else {
1947        pointerEvent->MarkProcessed();
1948    }
1949    if (pointerAction == MMI::PointerEvent::POINTER_ACTION_MOVE ||
1950        pointerAction == MMI::PointerEvent::POINTER_ACTION_PULL_MOVE) {
1951        WLOGFD("Session TransferPointEvent, eventId:%{public}d, action:%{public}s, persistentId:%{public}d, "
1952            "bundleName:%{public}s, pid:%{public}d", pointerEvent->GetId(), pointerEvent->DumpPointerAction(),
1953            persistentId_, callingBundleName_.c_str(), callingPid_);
1954    } else {
1955        WLOGFI("Session TransferPointEvent, eventId:%{public}d, action:%{public}s, persistentId:%{public}d, "
1956            "bundleName:%{public}s, pid:%{public}d", pointerEvent->GetId(), pointerEvent->DumpPointerAction(),
1957            persistentId_, callingBundleName_.c_str(), callingPid_);
1958    }
1959    if (pointerAction == MMI::PointerEvent::POINTER_ACTION_ENTER_WINDOW ||
1960        pointerAction == MMI::PointerEvent::POINTER_ACTION_LEAVE_WINDOW ||
1961        pointerAction == MMI::PointerEvent::POINTER_ACTION_PULL_IN_WINDOW ||
1962        pointerAction == MMI::PointerEvent::POINTER_ACTION_PULL_OUT_WINDOW) {
1963        WLOGFD("Action:%{public}s, eventId:%{public}d, report without timer",
1964            pointerEvent->DumpPointerAction(), pointerEvent->GetId());
1965    }
1966    return WSError::WS_OK;
1967}
1968
1969WSError Session::TransferKeyEvent(const std::shared_ptr<MMI::KeyEvent>& keyEvent)
1970{
1971    WLOGFD("Session TransferKeyEvent eventId:%{public}d persistentId:%{public}d bundleName:%{public}s pid:%{public}d",
1972        keyEvent->GetId(), persistentId_, callingBundleName_.c_str(), callingPid_);
1973    if (!windowEventChannel_) {
1974        WLOGFE("windowEventChannel_ is null");
1975        return WSError::WS_ERROR_NULLPTR;
1976    }
1977    WLOGD("TransferKeyEvent, id: %{public}d", persistentId_);
1978    WSError ret = windowEventChannel_->TransferKeyEvent(keyEvent);
1979    if (ret != WSError::WS_OK) {
1980        WLOGFE("TransferKeyEvent failed, ret:%{public}d", ret);
1981        return ret;
1982    }
1983    return WSError::WS_OK;
1984}
1985
1986WSError Session::TransferBackPressedEventForConsumed(bool& isConsumed)
1987{
1988    if (!windowEventChannel_) {
1989        WLOGFE("windowEventChannel_ is null");
1990        return WSError::WS_ERROR_NULLPTR;
1991    }
1992    return windowEventChannel_->TransferBackpressedEventForConsumed(isConsumed);
1993}
1994
1995WSError Session::TransferKeyEventForConsumed(const std::shared_ptr<MMI::KeyEvent>& keyEvent, bool& isConsumed,
1996    bool isPreImeEvent)
1997{
1998    if (!windowEventChannel_) {
1999        WLOGFE("windowEventChannel_ is null");
2000        return WSError::WS_ERROR_NULLPTR;
2001    }
2002    if (keyEvent == nullptr) {
2003        WLOGFE("KeyEvent is nullptr");
2004        return WSError::WS_ERROR_NULLPTR;
2005    }
2006    return windowEventChannel_->TransferKeyEventForConsumed(keyEvent, isConsumed, isPreImeEvent);
2007}
2008
2009WSError Session::TransferFocusActiveEvent(bool isFocusActive)
2010{
2011    if (!windowEventChannel_) {
2012        WLOGFE("windowEventChannel_ is null");
2013        return WSError::WS_ERROR_NULLPTR;
2014    }
2015    return windowEventChannel_->TransferFocusActiveEvent(isFocusActive);
2016}
2017
2018WSError Session::TransferFocusStateEvent(bool focusState)
2019{
2020    if (!windowEventChannel_) {
2021        if (!IsSystemSession()) {
2022            WLOGFW("windowEventChannel_ is null");
2023        }
2024        return WSError::WS_ERROR_NULLPTR;
2025    }
2026    return windowEventChannel_->TransferFocusState(focusState);
2027}
2028
2029std::shared_ptr<Media::PixelMap> Session::Snapshot(bool runInFfrt, float scaleParam, bool useCurWindow) const
2030{
2031    HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "Snapshot[%d][%s]", persistentId_, sessionInfo_.bundleName_.c_str());
2032    if (scenePersistence_ == nullptr) {
2033        return nullptr;
2034    }
2035    if (!surfaceNode_ || !surfaceNode_->IsBufferAvailable()) {
2036        scenePersistence_->SetHasSnapshot(false);
2037        return nullptr;
2038    }
2039    scenePersistence_->SetHasSnapshot(true);
2040    auto callback = std::make_shared<SurfaceCaptureFuture>();
2041    auto scaleValue = scaleParam == 0.0f ? snapshotScale_ : scaleParam;
2042    RSSurfaceCaptureConfig config = {
2043        .scaleX = scaleValue,
2044        .scaleY = scaleValue,
2045        .useDma = true,
2046        .useCurWindow = useCurWindow,
2047    };
2048    bool ret = RSInterfaces::GetInstance().TakeSurfaceCapture(surfaceNode_, callback, config);
2049    if (!ret) {
2050        TLOGE(WmsLogTag::WMS_MAIN, "TakeSurfaceCapture failed");
2051        return nullptr;
2052    }
2053    constexpr int32_t FFRT_SNAPSHOT_TIMEOUT_MS = 5000;
2054    auto pixelMap = callback->GetResult(runInFfrt ? FFRT_SNAPSHOT_TIMEOUT_MS : SNAPSHOT_TIMEOUT_MS);
2055    if (pixelMap != nullptr) {
2056        TLOGI(WmsLogTag::WMS_MAIN, "Save snapshot WxH = %{public}dx%{public}d, id: %{public}d",
2057            pixelMap->GetWidth(), pixelMap->GetHeight(), persistentId_);
2058        if (notifySessionSnapshotFunc_) {
2059            notifySessionSnapshotFunc_(persistentId_);
2060        }
2061        return pixelMap;
2062    }
2063    TLOGE(WmsLogTag::WMS_MAIN, "Save snapshot failed, id: %{public}d", persistentId_);
2064    return nullptr;
2065}
2066
2067void Session::SaveSnapshot(bool useFfrt)
2068{
2069    if (scenePersistence_ == nullptr) {
2070        return;
2071    }
2072    auto task = [weakThis = wptr(this), runInFfrt = useFfrt]() {
2073        auto session = weakThis.promote();
2074        if (session == nullptr) {
2075            TLOGE(WmsLogTag::WMS_LIFE, "session is null");
2076            return;
2077        }
2078        session->lastLayoutRect_ = session->layoutRect_;
2079        auto pixelMap = session->Snapshot(runInFfrt);
2080        if (pixelMap == nullptr) {
2081            return;
2082        }
2083        {
2084            std::lock_guard<std::mutex> lock(session->snapshotMutex_);
2085            session->snapshot_ = pixelMap;
2086        }
2087        std::function<void()> func = [weakThis]() {
2088            if (auto session = weakThis.promote()) {
2089                TLOGI(WmsLogTag::WMS_MAIN, "reset snapshot id: %{public}d", session->GetPersistentId());
2090                std::lock_guard<std::mutex> lock(session->snapshotMutex_);
2091                session->snapshot_ = nullptr;
2092            }
2093        };
2094        session->scenePersistence_->SaveSnapshot(pixelMap, func);
2095    };
2096    if (!useFfrt) {
2097        task();
2098        return;
2099    }
2100    auto snapshotFfrtHelper = scenePersistence_->GetSnapshotFfrtHelper();
2101    std::string taskName = "Session::SaveSnapshot" + std::to_string(persistentId_);
2102    snapshotFfrtHelper->CancelTask(taskName);
2103    snapshotFfrtHelper->SubmitTask(std::move(task), taskName);
2104}
2105
2106void Session::SetSessionStateChangeListenser(const NotifySessionStateChangeFunc& func)
2107{
2108    auto task = [weakThis = wptr(this), func]() {
2109        auto session = weakThis.promote();
2110        if (session == nullptr) {
2111            WLOGFE("session is null");
2112            return;
2113        }
2114        session->sessionStateChangeFunc_ = func;
2115        auto changedState = session->GetSessionState(); // read and write state should in one thread
2116        if (changedState == SessionState::STATE_ACTIVE) {
2117            changedState = SessionState::STATE_FOREGROUND;
2118        } else if (changedState == SessionState::STATE_INACTIVE) {
2119            changedState = SessionState::STATE_BACKGROUND;
2120        } else if (changedState == SessionState::STATE_DISCONNECT) {
2121            return;
2122        }
2123        session->NotifySessionStateChange(changedState);
2124        TLOGI(WmsLogTag::WMS_LIFE, "id: %{public}d, state_: %{public}d, changedState: %{public}d",
2125            session->GetPersistentId(), session->GetSessionState(), changedState);
2126    };
2127    PostTask(task, "SetSessionStateChangeListenser");
2128}
2129
2130void Session::SetBufferAvailableChangeListener(const NotifyBufferAvailableChangeFunc& func)
2131{
2132    bufferAvailableChangeFunc_ = func;
2133    if (bufferAvailable_ && bufferAvailableChangeFunc_ != nullptr) {
2134        bufferAvailableChangeFunc_(bufferAvailable_);
2135    }
2136    WLOGFD("SetBufferAvailableChangeListener, id: %{public}d", GetPersistentId());
2137}
2138
2139void Session::SetAcquireRotateAnimationConfigFunc(const AcquireRotateAnimationConfigFunc& func)
2140{
2141    if (func == nullptr) {
2142        TLOGI(WmsLogTag::DEFAULT, "func is nullptr");
2143        return;
2144    }
2145    acquireRotateAnimationConfigFunc_ = func;
2146}
2147
2148int32_t Session::GetRotateAnimationDuration()
2149{
2150    if (acquireRotateAnimationConfigFunc_) {
2151        RotateAnimationConfig rotateAnimationConfig;
2152        acquireRotateAnimationConfigFunc_(rotateAnimationConfig);
2153        return rotateAnimationConfig.duration_;
2154    }
2155    return ROTATE_ANIMATION_DURATION;
2156}
2157
2158void Session::UnregisterSessionChangeListeners()
2159{
2160    sessionStateChangeFunc_ = nullptr;
2161    sessionFocusableChangeFunc_ = nullptr;
2162    sessionTouchableChangeFunc_ = nullptr;
2163    clickFunc_ = nullptr;
2164    jsSceneSessionExceptionFunc_ = nullptr;
2165    sessionExceptionFunc_ = nullptr;
2166    terminateSessionFunc_ = nullptr;
2167    pendingSessionActivationFunc_ = nullptr;
2168    changeSessionVisibilityWithStatusBarFunc_ = nullptr;
2169    bufferAvailableChangeFunc_ = nullptr;
2170    backPressedFunc_ = nullptr;
2171    terminateSessionFuncNew_ = nullptr;
2172    terminateSessionFuncTotal_ = nullptr;
2173    updateSessionLabelFunc_ = nullptr;
2174    updateSessionIconFunc_ = nullptr;
2175    pendingSessionToForegroundFunc_ = nullptr;
2176    pendingSessionToBackgroundForDelegatorFunc_ = nullptr;
2177    raiseToTopForPointDownFunc_ = nullptr;
2178    sessionInfoLockedStateChangeFunc_ = nullptr;
2179    contextTransparentFunc_ = nullptr;
2180    sessionRectChangeFunc_ = nullptr;
2181    WLOGFD("UnregisterSessionChangeListenser, id: %{public}d", GetPersistentId());
2182}
2183
2184void Session::SetSessionStateChangeNotifyManagerListener(const NotifySessionStateChangeNotifyManagerFunc& func)
2185{
2186    sessionStateChangeNotifyManagerFunc_ = func;
2187    if (state_ == SessionState::STATE_DISCONNECT) {
2188        return;
2189    }
2190    NotifySessionStateChange(state_);
2191}
2192
2193void Session::SetSessionInfoChangeNotifyManagerListener(const NotifySessionInfoChangeNotifyManagerFunc& func)
2194{
2195    sessionInfoChangeNotifyManagerFunc_ = func;
2196}
2197
2198void Session::SetRequestFocusStatusNotifyManagerListener(const NotifyRequestFocusStatusNotifyManagerFunc& func)
2199{
2200    requestFocusStatusNotifyManagerFunc_ = func;
2201}
2202
2203void Session::SetNotifyUIRequestFocusFunc(const NotifyUIRequestFocusFunc& func)
2204{
2205    std::unique_lock<std::shared_mutex> lock(uiRequestFocusMutex_);
2206    requestFocusFunc_ = func;
2207}
2208
2209void Session::SetNotifyUILostFocusFunc(const NotifyUILostFocusFunc& func)
2210{
2211    std::unique_lock<std::shared_mutex> lock(uiLostFocusMutex_);
2212    lostFocusFunc_ = func;
2213}
2214
2215void Session::SetGetStateFromManagerListener(const GetStateFromManagerFunc& func)
2216{
2217    getStateFromManagerFunc_ = func;
2218}
2219
2220void Session::NotifySessionStateChange(const SessionState& state)
2221{
2222    auto task = [weakThis = wptr(this), state]() {
2223        auto session = weakThis.promote();
2224        if (session == nullptr) {
2225            WLOGFE("session is null");
2226            return;
2227        }
2228        TLOGD(WmsLogTag::WMS_LIFE, "NotifySessionStateChange, [state: %{public}u, persistent: %{public}d]",
2229            static_cast<uint32_t>(state), session->GetPersistentId());
2230        if (session->sessionStateChangeFunc_) {
2231            session->sessionStateChangeFunc_(state);
2232        }
2233
2234        if (session->sessionStateChangeNotifyManagerFunc_) {
2235            session->sessionStateChangeNotifyManagerFunc_(session->GetPersistentId(), state);
2236        }
2237    };
2238    PostTask(task, "NotifySessionStateChange");
2239}
2240
2241void Session::SetSessionFocusableChangeListener(const NotifySessionFocusableChangeFunc& func)
2242{
2243    sessionFocusableChangeFunc_ = func;
2244    NotifySessionFocusableChange(GetFocusable());
2245}
2246
2247void Session::SetSessionTouchableChangeListener(const NotifySessionTouchableChangeFunc& func)
2248{
2249    sessionTouchableChangeFunc_ = func;
2250    sessionTouchableChangeFunc_(GetTouchable());
2251}
2252
2253void Session::SetClickListener(const NotifyClickFunc& func)
2254{
2255    clickFunc_ = func;
2256}
2257
2258void Session::NotifySessionFocusableChange(bool isFocusable)
2259{
2260    TLOGI(WmsLogTag::WMS_FOCUS, "id: %{public}d, focusable: %{public}u", GetPersistentId(), isFocusable);
2261    if (sessionFocusableChangeFunc_) {
2262        sessionFocusableChangeFunc_(isFocusable);
2263    }
2264}
2265
2266void Session::NotifySessionTouchableChange(bool touchable)
2267{
2268    WLOGFD("Notify session touchable change: %{public}d", touchable);
2269    if (sessionTouchableChangeFunc_) {
2270        sessionTouchableChangeFunc_(touchable);
2271    }
2272}
2273
2274void Session::NotifyClick(bool requestFocus)
2275{
2276    TLOGD(WmsLogTag::WMS_FOCUS, "requestFocus: %{public}u", requestFocus);
2277    if (clickFunc_) {
2278        clickFunc_(requestFocus);
2279    }
2280}
2281
2282void Session::NotifyRequestFocusStatusNotifyManager(bool isFocused, bool byForeground, FocusChangeReason reason)
2283{
2284    TLOGD(WmsLogTag::WMS_FOCUS, "NotifyRequestFocusStatusNotifyManager id: %{public}d, focused: %{public}d,\
2285        reason:  %{public}d", GetPersistentId(), isFocused, reason);
2286    if (requestFocusStatusNotifyManagerFunc_) {
2287        requestFocusStatusNotifyManagerFunc_(GetPersistentId(), isFocused, byForeground, reason);
2288    }
2289}
2290
2291bool Session::GetStateFromManager(const ManagerState key)
2292{
2293    if (getStateFromManagerFunc_) {
2294        return getStateFromManagerFunc_(key);
2295    }
2296    switch (key)
2297    {
2298    case ManagerState::MANAGER_STATE_SCREEN_LOCKED:
2299        return false;
2300        break;
2301    default:
2302        return false;
2303    }
2304}
2305
2306void Session::NotifyUIRequestFocus()
2307{
2308    WLOGFD("NotifyUIRequestFocus id: %{public}d", GetPersistentId());
2309    std::shared_lock<std::shared_mutex> lock(uiRequestFocusMutex_);
2310    if (requestFocusFunc_) {
2311        requestFocusFunc_();
2312    }
2313}
2314
2315void Session::NotifyUILostFocus()
2316{
2317    WLOGFD("NotifyUILostFocus id: %{public}d", GetPersistentId());
2318    std::shared_lock<std::shared_mutex> lock(uiLostFocusMutex_);
2319    if (lostFocusFunc_) {
2320        lostFocusFunc_();
2321    }
2322}
2323
2324void Session::PresentFoucusIfNeed(int32_t pointerAction)
2325{
2326    WLOGFD("OnClick down, id: %{public}d", GetPersistentId());
2327    if (pointerAction == MMI::PointerEvent::POINTER_ACTION_DOWN ||
2328        pointerAction == MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN) {
2329        if (!isFocused_ && GetFocusable()) {
2330            FocusChangeReason reason = FocusChangeReason::CLICK;
2331            NotifyRequestFocusStatusNotifyManager(true, false, reason);
2332        }
2333        NotifyClick();
2334    }
2335}
2336
2337WSError Session::UpdateFocus(bool isFocused)
2338{
2339    if (isFocused_ == isFocused) {
2340        TLOGD(WmsLogTag::WMS_FOCUS, "Session focus do not change");
2341        return WSError::WS_DO_NOTHING;
2342    }
2343    isFocused_ = isFocused;
2344    UpdateGestureBackEnabled();
2345    // notify scb arkui focus
2346    if (!isFocused) {
2347        NotifyUILostFocus();
2348    }
2349    return WSError::WS_OK;
2350}
2351
2352WSError Session::NotifyFocusStatus(bool isFocused)
2353{
2354    if (!IsSessionValid()) {
2355        TLOGW(WmsLogTag::WMS_FOCUS, "Session is invalid, id: %{public}d state: %{public}u",
2356            GetPersistentId(), GetSessionState());
2357        return WSError::WS_ERROR_INVALID_SESSION;
2358    }
2359    if (!sessionStage_) {
2360        return WSError::WS_ERROR_NULLPTR;
2361    }
2362    sessionStage_->UpdateFocus(isFocused);
2363
2364    return WSError::WS_OK;
2365}
2366
2367WSError Session::RequestFocus(bool isFocused)
2368{
2369    if (!SessionPermission::IsSystemCalling()) {
2370        TLOGE(WmsLogTag::WMS_FOCUS, "permission denied!");
2371        return WSError::WS_ERROR_NOT_SYSTEM_APP;
2372    }
2373    FocusChangeReason reason = FocusChangeReason::CLIENT_REQUEST;
2374    NotifyRequestFocusStatusNotifyManager(isFocused, false, reason);
2375    return WSError::WS_OK;
2376}
2377
2378WSError Session::SetCompatibleModeInPc(bool enable, bool isSupportDragInPcCompatibleMode)
2379{
2380    TLOGI(WmsLogTag::WMS_SCB, "SetCompatibleModeInPc enable: %{public}d, isSupportDragInPcCompatibleMode: %{public}d",
2381        enable, isSupportDragInPcCompatibleMode);
2382    auto property = GetSessionProperty();
2383    if (property == nullptr) {
2384        TLOGE(WmsLogTag::WMS_SCB, "id: %{public}d property is nullptr", persistentId_);
2385        return WSError::WS_ERROR_NULLPTR;
2386    }
2387
2388    property->SetCompatibleModeInPc(enable);
2389    property->SetIsSupportDragInPcCompatibleMode(isSupportDragInPcCompatibleMode);
2390    if (enable) {
2391        property->SetDragEnabled(isSupportDragInPcCompatibleMode);
2392    }
2393    return WSError::WS_OK;
2394}
2395
2396WSError Session::SetCompatibleModeEnableInPad(bool enable)
2397{
2398    TLOGI(WmsLogTag::WMS_SCB, "id: %{public}d, enable: %{public}d", persistentId_, enable);
2399    if (!IsSessionValid()) {
2400        TLOGW(WmsLogTag::WMS_SCB, "Session is invalid, id: %{public}d state: %{public}u",
2401            GetPersistentId(), GetSessionState());
2402        return WSError::WS_ERROR_INVALID_SESSION;
2403    }
2404    auto property = GetSessionProperty();
2405    if (!property) {
2406        TLOGE(WmsLogTag::WMS_SCB, "id: %{public}d property is nullptr", persistentId_);
2407        return WSError::WS_ERROR_NULLPTR;
2408    }
2409    property->SetCompatibleModeEnableInPad(enable);
2410
2411    if (!sessionStage_) {
2412        TLOGE(WmsLogTag::WMS_SCB, "sessionStage is null");
2413        return WSError::WS_ERROR_NULLPTR;
2414    }
2415    return sessionStage_->NotifyCompatibleModeEnableInPad(enable);
2416}
2417
2418WSError Session::SetAppSupportPhoneInPc(bool isSupportPhone)
2419{
2420    TLOGI(WmsLogTag::WMS_SCB, "isSupportPhone: %{public}d", isSupportPhone);
2421    auto property = GetSessionProperty();
2422    if (property == nullptr) {
2423        TLOGE(WmsLogTag::WMS_SCB, "id: %{public}d property is nullptr", persistentId_);
2424        return WSError::WS_ERROR_NULLPTR;
2425    }
2426    property->SetIsAppSupportPhoneInPc(isSupportPhone);
2427    return WSError::WS_OK;
2428}
2429
2430WSError Session::SetCompatibleWindowSizeInPc(int32_t portraitWidth, int32_t portraitHeight,
2431    int32_t landscapeWidth, int32_t landscapeHeight)
2432{
2433    TLOGI(WmsLogTag::WMS_SCB, "compatible size: [%{public}d, %{public}d, %{public}d, %{public}d]",
2434        portraitWidth, portraitHeight, landscapeWidth, landscapeHeight);
2435    auto property = GetSessionProperty();
2436    if (property == nullptr) {
2437        TLOGE(WmsLogTag::WMS_SCB, "id: %{public}d property is nullptr", persistentId_);
2438        return WSError::WS_ERROR_NULLPTR;
2439    }
2440    property->SetCompatibleWindowSizeInPc(portraitWidth, portraitHeight, landscapeWidth, landscapeHeight);
2441    return WSError::WS_OK;
2442}
2443
2444WSError Session::SetIsPcAppInPad(bool enable)
2445{
2446    TLOGI(WmsLogTag::WMS_SCB, "SetIsPcAppInPad enable: %{public}d", enable);
2447    auto property = GetSessionProperty();
2448    if (property == nullptr) {
2449        TLOGE(WmsLogTag::WMS_SCB, "id: %{public}d property is nullptr", persistentId_);
2450        return WSError::WS_ERROR_NULLPTR;
2451    }
2452    property->SetIsPcAppInPad(enable);
2453    return WSError::WS_OK;
2454}
2455
2456WSError Session::CompatibleFullScreenRecover()
2457{
2458    TLOGD(WmsLogTag::WMS_MAIN, "recover compatible full screen windowId:%{public}d", GetPersistentId());
2459    if (!IsSessionValid()) {
2460        TLOGD(WmsLogTag::WMS_MAIN, "Session is invalid, id: %{public}d state: %{public}u",
2461            GetPersistentId(), GetSessionState());
2462        return WSError::WS_ERROR_INVALID_SESSION;
2463    }
2464    if (sessionStage_ == nullptr) {
2465        TLOGE(WmsLogTag::WMS_MAIN, "session stage is nullptr id: %{public}d state: %{public}u",
2466              GetPersistentId(), GetSessionState());
2467        return WSError::WS_ERROR_NULLPTR;
2468    }
2469    return sessionStage_->CompatibleFullScreenRecover();
2470}
2471
2472WSError Session::CompatibleFullScreenMinimize()
2473{
2474    TLOGD(WmsLogTag::WMS_MAIN, "minimize compatible full screen windowId:%{public}d", GetPersistentId());
2475    if (!IsSessionValid()) {
2476        TLOGD(WmsLogTag::WMS_MAIN, "Session is invalid, id: %{public}d state: %{public}u",
2477            GetPersistentId(), GetSessionState());
2478        return WSError::WS_ERROR_INVALID_SESSION;
2479    }
2480    if (sessionStage_ == nullptr) {
2481        TLOGE(WmsLogTag::WMS_MAIN, "session stage is nullptr id: %{public}d state: %{public}u",
2482              GetPersistentId(), GetSessionState());
2483        return WSError::WS_ERROR_NULLPTR;
2484    }
2485    return sessionStage_->CompatibleFullScreenMinimize();
2486}
2487
2488WSError Session::CompatibleFullScreenClose()
2489{
2490    TLOGD(WmsLogTag::WMS_LIFE, "close compatible full screen windowId:%{public}d", GetPersistentId());
2491    if (!IsSessionValid()) {
2492        TLOGD(WmsLogTag::WMS_LIFE, "Session is invalid, id: %{public}d state: %{public}u",
2493            GetPersistentId(), GetSessionState());
2494        return WSError::WS_ERROR_INVALID_SESSION;
2495    }
2496    if (sessionStage_ == nullptr) {
2497        TLOGE(WmsLogTag::WMS_LIFE, "session stage is nullptr id: %{public}d state: %{public}u",
2498              GetPersistentId(), GetSessionState());
2499        return WSError::WS_ERROR_NULLPTR;
2500    }
2501    return sessionStage_->CompatibleFullScreenClose();
2502}
2503
2504WSError Session::UpdateWindowMode(WindowMode mode)
2505{
2506    WLOGFD("Session update window mode, id: %{public}d, mode: %{public}d", GetPersistentId(),
2507        static_cast<int32_t>(mode));
2508    auto property = GetSessionProperty();
2509    if (property == nullptr) {
2510        WLOGFD("id: %{public}d property is nullptr", persistentId_);
2511        return WSError::WS_ERROR_NULLPTR;
2512    }
2513    if (state_ == SessionState::STATE_END) {
2514        WLOGFI("session is already destroyed or property is nullptr! id: %{public}d state: %{public}u",
2515            GetPersistentId(), GetSessionState());
2516        return WSError::WS_ERROR_INVALID_SESSION;
2517    } else if (state_ == SessionState::STATE_DISCONNECT) {
2518        property->SetWindowMode(mode);
2519        property->SetIsNeedUpdateWindowMode(true);
2520        UpdateGestureBackEnabled();
2521    } else {
2522        property->SetWindowMode(mode);
2523        if (mode == WindowMode::WINDOW_MODE_SPLIT_PRIMARY || mode == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) {
2524            property->SetMaximizeMode(MaximizeMode::MODE_RECOVER);
2525            if (mode == WindowMode::WINDOW_MODE_SPLIT_PRIMARY) {
2526                surfaceNode_->MarkUifirstNode(false);
2527            }
2528        } else {
2529            surfaceNode_->MarkUifirstNode(true);
2530        }
2531        UpdateGestureBackEnabled();
2532        if (!sessionStage_) {
2533            return WSError::WS_ERROR_NULLPTR;
2534        }
2535        return sessionStage_->UpdateWindowMode(mode);
2536    }
2537    return WSError::WS_OK;
2538}
2539
2540WSError Session::SetSystemSceneBlockingFocus(bool blocking)
2541{
2542    TLOGW(WmsLogTag::WMS_FOCUS, "Session set blocking focus, id: %{public}d, mode: %{public}d, Session is not system.",
2543        GetPersistentId(), blocking);
2544    return WSError::WS_ERROR_INVALID_SESSION;
2545}
2546
2547bool Session::GetBlockingFocus() const
2548{
2549    return blockingFocus_;
2550}
2551
2552WSError Session::SetSessionProperty(const sptr<WindowSessionProperty>& property)
2553{
2554    TLOGI(WmsLogTag::WMS_LAYOUT, "set property dragEnable: %{public}d", property->GetDragEnabled());
2555    {
2556        std::unique_lock<std::shared_mutex> lock(propertyMutex_);
2557        property_ = property;
2558    }
2559    NotifySessionInfoChange();
2560    if (property == nullptr) {
2561        return WSError::WS_OK;
2562    }
2563
2564    auto hotAreasChangeCallback = [weakThis = wptr(this)]() {
2565        auto session = weakThis.promote();
2566        if (session == nullptr) {
2567            WLOGFE("session is nullptr");
2568            return;
2569        }
2570        session->NotifySessionInfoChange();
2571    };
2572    property->SetSessionPropertyChangeCallback(hotAreasChangeCallback);
2573    return WSError::WS_OK;
2574}
2575
2576sptr<WindowSessionProperty> Session::GetSessionProperty() const
2577{
2578    std::shared_lock<std::shared_mutex> lock(propertyMutex_);
2579    return property_;
2580}
2581
2582/** @note @window.layout */
2583void Session::RectSizeCheckProcess(uint32_t curWidth, uint32_t curHeight, uint32_t minWidth,
2584    uint32_t minHeight, uint32_t maxFloatingWindowSize)
2585{
2586    if ((curWidth < minWidth) || (curWidth > maxFloatingWindowSize) ||
2587        (curHeight < minHeight) || (curHeight > maxFloatingWindowSize)) {
2588        TLOGE(WmsLogTag::WMS_LAYOUT, "RectCheck err sessionID: %{public}d rect %{public}s",
2589            GetPersistentId(), GetSessionRect().ToString().c_str());
2590        std::ostringstream oss;
2591        oss << " RectCheck err size ";
2592        oss << " cur persistentId: " << GetPersistentId() << ",";
2593        oss << " windowType: " << static_cast<uint32_t>(GetWindowType()) << ",";
2594        auto property = GetSessionProperty();
2595        if (property) {
2596            oss << " windowName: " << property->GetWindowName() << ",";
2597            oss << " windowState: " << static_cast<uint32_t>(property->GetWindowState()) << ",";
2598        }
2599        oss << " curWidth: " << curWidth << ",";
2600        oss << " curHeight: " << curHeight << ",";
2601        oss << " minWidth: " << minWidth << ",";
2602        oss << " minHeight: " << minHeight << ",";
2603        oss << " maxFloatingWindowSize: " << maxFloatingWindowSize << ",";
2604        oss << " sessionRect: " << GetSessionRect().ToString() << ";";
2605        WindowInfoReporter::GetInstance().ReportWindowException(
2606            static_cast<int32_t>(WindowDFXHelperType::WINDOW_RECT_CHECK), getpid(), oss.str());
2607    }
2608}
2609
2610/** @note @window.layout */
2611void Session::RectCheckProcess()
2612{
2613    if (!(IsSessionForeground() || isVisible_)) {
2614        return;
2615    }
2616    auto property = GetSessionProperty();
2617    if (!property) {
2618        TLOGE(WmsLogTag::WMS_LAYOUT, "property is null");
2619        return;
2620    }
2621    auto displayId = property->GetDisplayId();
2622    std::map<ScreenId, ScreenProperty> screensProperties =
2623        Rosen::ScreenSessionManagerClient::GetInstance().GetAllScreensProperties();
2624    if (screensProperties.find(displayId) == screensProperties.end()) {
2625        return;
2626    }
2627    auto screenProperty = screensProperties[displayId];
2628    float density = screenProperty.GetDensity();
2629    if (!NearZero(density) && !NearZero(GetSessionRect().height_)) {
2630        float curWidth = GetSessionRect().width_ / density;
2631        float curHeight = GetSessionRect().height_ / density;
2632        float ratio = GetAspectRatio();
2633        float actRatio = curWidth / curHeight;
2634        if ((ratio != 0) && !NearEqual(ratio, actRatio)) {
2635            TLOGE(WmsLogTag::WMS_LAYOUT, "RectCheck err ratio %{public}f != actRatio: %{public}f", ratio, actRatio);
2636            std::ostringstream oss;
2637            oss << " RectCheck err ratio ";
2638            oss << " cur persistentId: " << GetPersistentId() << ",";
2639            oss << " windowType: " << static_cast<uint32_t>(GetWindowType()) << ",";
2640            oss << " windowName: " << property->GetWindowName() << ",";
2641            oss << " windowState: " << static_cast<uint32_t>(property->GetWindowState()) << ",";
2642            oss << " curWidth: " << curWidth << ",";
2643            oss << " curHeight: " << curHeight << ",";
2644            oss << " setting ratio: " << ratio << ",";
2645            oss << " sessionRect: " << GetSessionRect().ToString() << ";";
2646            WindowInfoReporter::GetInstance().ReportWindowException(
2647                static_cast<int32_t>(WindowDFXHelperType::WINDOW_RECT_CHECK), getpid(), oss.str());
2648        }
2649        RectCheck(curWidth, curHeight);
2650    }
2651}
2652
2653/** @note @window.layout */
2654void Session::SetSessionRect(const WSRect& rect)
2655{
2656    if (winRect_ == rect) {
2657        WLOGFW("id: %{public}d skip same rect", persistentId_);
2658        return;
2659    }
2660    winRect_ = rect;
2661    dirtyFlags_ |= static_cast<uint32_t>(SessionUIDirtyFlag::RECT);
2662    RectCheckProcess();
2663}
2664
2665/** @note @window.layout */
2666WSRect Session::GetSessionRect() const
2667{
2668    return winRect_;
2669}
2670
2671/** @note @window.layout */
2672WSRect Session::GetSessionGlobalRect() const
2673{
2674    if (IsScbCoreEnabled()) {
2675        std::lock_guard<std::mutex> lock(globalRectMutex_);
2676        return globalRect_;
2677    }
2678    return winRect_;
2679}
2680
2681/** @note @window.layout */
2682void Session::SetSessionGlobalRect(const WSRect& rect)
2683{
2684    std::lock_guard<std::mutex> lock(globalRectMutex_);
2685    globalRect_ = rect;
2686}
2687
2688/** @note @window.layout */
2689WSRect Session::GetLastLayoutRect() const
2690{
2691    return lastLayoutRect_;
2692}
2693
2694/** @note @window.layout */
2695WSRect Session::GetLayoutRect() const
2696{
2697    return layoutRect_;
2698}
2699
2700void Session::SetSessionRequestRect(const WSRect& rect)
2701{
2702    auto property = GetSessionProperty();
2703    if (property == nullptr) {
2704        WLOGFD("id: %{public}d property is nullptr", persistentId_);
2705        return;
2706    }
2707    property->SetRequestRect(SessionHelper::TransferToRect(rect));
2708    WLOGFD("is: %{public}d, rect: [%{public}d, %{public}d, %{public}u, %{public}u]", persistentId_,
2709        rect.posX_, rect.posY_, rect.width_, rect.height_);
2710}
2711
2712WSRect Session::GetSessionRequestRect() const
2713{
2714    WSRect rect;
2715    auto property = GetSessionProperty();
2716    if (property == nullptr) {
2717        WLOGFD("id: %{public}d property is nullptr", persistentId_);
2718        return rect;
2719    }
2720    rect = SessionHelper::TransferToWSRect(property->GetRequestRect());
2721    WLOGFD("id: %{public}d, rect: %{public}s", persistentId_, rect.ToString().c_str());
2722    return rect;
2723}
2724
2725/** @note @window.layout */
2726void Session::SetClientRect(const WSRect& rect)
2727{
2728    clientRect_ = rect;
2729    TLOGI(WmsLogTag::WMS_LAYOUT, "Id:%{public}d, update client rect:%{public}s",
2730        GetPersistentId(), rect.ToString().c_str());
2731}
2732
2733/** @note @window.layout */
2734WSRect Session::GetClientRect() const
2735{
2736    return clientRect_;
2737}
2738
2739WindowType Session::GetWindowType() const
2740{
2741    auto property = GetSessionProperty();
2742    if (property) {
2743        return property->GetWindowType();
2744    }
2745    return WindowType::WINDOW_TYPE_APP_MAIN_WINDOW;
2746}
2747
2748std::string Session::GetWindowName() const
2749{
2750    if (GetSessionInfo().isSystem_) {
2751        return GetSessionInfo().abilityName_;
2752    } else {
2753        auto property = GetSessionProperty();
2754        return property ? property->GetWindowName() : "";
2755    }
2756}
2757
2758void Session::SetSystemConfig(const SystemSessionConfig& systemConfig)
2759{
2760    systemConfig_ = systemConfig;
2761}
2762
2763SystemSessionConfig Session::GetSystemConfig() const
2764{
2765    return systemConfig_;
2766}
2767
2768void Session::SetSnapshotScale(const float snapshotScale)
2769{
2770    snapshotScale_ = snapshotScale;
2771}
2772
2773WSError Session::ProcessBackEvent()
2774{
2775    if (!IsSessionValid()) {
2776        TLOGW(WmsLogTag::WMS_EVENT, "Session is invalid, id: %{public}d state: %{public}u",
2777            GetPersistentId(), GetSessionState());
2778        return WSError::WS_ERROR_INVALID_SESSION;
2779    }
2780    if (!sessionStage_) {
2781        TLOGE(WmsLogTag::WMS_EVENT, "session stage is nullptr");
2782        return WSError::WS_ERROR_NULLPTR;
2783    }
2784    return sessionStage_->HandleBackEvent();
2785}
2786
2787void Session::GeneratePersistentId(bool isExtension, int32_t persistentId)
2788{
2789    if (persistentId != INVALID_SESSION_ID  && !g_persistentIdSet.count(persistentId)) {
2790        g_persistentIdSet.insert(persistentId);
2791        persistentId_ = persistentId;
2792        return;
2793    }
2794
2795    if (g_persistentId == INVALID_SESSION_ID) {
2796        g_persistentId++; // init non system session id from 2
2797    }
2798
2799    g_persistentId++;
2800    while (g_persistentIdSet.count(g_persistentId)) {
2801        g_persistentId++;
2802    }
2803    if (isExtension) {
2804        constexpr uint32_t pidLength = 18;
2805        constexpr uint32_t pidMask = (1 << pidLength) - 1;
2806        constexpr uint32_t persistentIdLength = 12;
2807        constexpr uint32_t persistentIdMask = (1 << persistentIdLength) - 1;
2808        uint32_t assembledPersistentId = ((static_cast<uint32_t>(getpid()) & pidMask) << persistentIdLength) |
2809            (static_cast<uint32_t>(g_persistentId.load()) & persistentIdMask);
2810        persistentId_ = assembledPersistentId | 0x40000000;
2811    } else {
2812        persistentId_ = static_cast<uint32_t>(g_persistentId.load()) & 0x3fffffff;
2813    }
2814    g_persistentIdSet.insert(g_persistentId);
2815    WLOGFI("GeneratePersistentId, persistentId: %{public}d, persistentId_: %{public}d", persistentId, persistentId_);
2816}
2817
2818sptr<ScenePersistence> Session::GetScenePersistence() const
2819{
2820    return scenePersistence_;
2821}
2822
2823void Session::NotifyOccupiedAreaChangeInfo(sptr<OccupiedAreaChangeInfo> info,
2824                                           const std::shared_ptr<RSTransaction>& rsTransaction)
2825{
2826    if (!sessionStage_) {
2827        TLOGD(WmsLogTag::WMS_KEYBOARD, "session stage is nullptr");
2828        return;
2829    }
2830    sessionStage_->NotifyOccupiedAreaChangeInfo(info, rsTransaction);
2831}
2832
2833WindowMode Session::GetWindowMode() const
2834{
2835    auto property = GetSessionProperty();
2836    if (property == nullptr) {
2837        WLOGFW("null property.");
2838        return WindowMode::WINDOW_MODE_UNDEFINED;
2839    }
2840    return property->GetWindowMode();
2841}
2842
2843WSError Session::UpdateMaximizeMode(bool isMaximize)
2844{
2845    WLOGFD("Session update maximize mode, isMaximize: %{public}d", isMaximize);
2846    if (!IsSessionValid()) {
2847        TLOGW(WmsLogTag::WMS_LAYOUT, "Session is invalid, id: %{public}d state: %{public}u",
2848            GetPersistentId(), GetSessionState());
2849        return WSError::WS_ERROR_INVALID_SESSION;
2850    }
2851    MaximizeMode mode = MaximizeMode::MODE_RECOVER;
2852    if (isMaximize) {
2853        mode = MaximizeMode::MODE_AVOID_SYSTEM_BAR;
2854    } else if (GetWindowMode() == WindowMode::WINDOW_MODE_FULLSCREEN) {
2855        mode = MaximizeMode::MODE_FULL_FILL;
2856    }
2857    auto property = GetSessionProperty();
2858    if (property == nullptr) {
2859        TLOGE(WmsLogTag::WMS_EVENT, "property is null");
2860        return WSError::WS_ERROR_NULLPTR;
2861    }
2862    property->SetMaximizeMode(mode);
2863    if (!sessionStage_) {
2864        TLOGE(WmsLogTag::WMS_MAIN, "sessionStage_ is null");
2865        return WSError::WS_ERROR_NULLPTR;
2866    }
2867    return sessionStage_->UpdateMaximizeMode(mode);
2868}
2869
2870/** @note @window.hierarchy */
2871void Session::SetZOrder(uint32_t zOrder)
2872{
2873    lastZOrder_ = zOrder_;
2874    zOrder_ = zOrder;
2875    NotifySessionInfoChange();
2876}
2877
2878/** @note @window.hierarchy */
2879uint32_t Session::GetZOrder() const
2880{
2881    return zOrder_;
2882}
2883
2884/** @note @window.hierarchy */
2885uint32_t Session::GetLastZOrder() const
2886{
2887    return lastZOrder_;
2888}
2889
2890void Session::SetUINodeId(uint32_t uiNodeId)
2891{
2892    if (uiNodeId_ != 0 && uiNodeId != 0 && !IsSystemSession() && SessionPermission::IsBetaVersion()) {
2893        int32_t eventRet = HiSysEventWrite(
2894            OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER,
2895            "REPEAT_SET_UI_NODE_ID",
2896            OHOS::HiviewDFX::HiSysEvent::EventType::STATISTIC,
2897            "PID", getpid(),
2898            "UID", getuid());
2899        TLOGE(WmsLogTag::WMS_LIFE, " SetUINodeId: Repeat set UINodeId ret:%{public}d", eventRet);
2900        return;
2901    }
2902    uiNodeId_ = uiNodeId;
2903}
2904
2905uint32_t Session::GetUINodeId() const
2906{
2907    return uiNodeId_;
2908}
2909
2910void Session::SetShowRecent(bool showRecent)
2911{
2912    TLOGI(WmsLogTag::WMS_MAIN, "in recents: %{public}d, id: %{public}d", showRecent, persistentId_);
2913    bool isAttach = GetAttachState();
2914    if (!IsSupportDetectWindow(isAttach) ||
2915        !ShouldCreateDetectTaskInRecent(showRecent, showRecent_, isAttach)) {
2916        showRecent_ = showRecent;
2917        return;
2918    }
2919    showRecent_ = showRecent;
2920    WindowMode windowMode = GetWindowMode();
2921    if (!showRecent_ && ShouldCreateDetectTask(isAttach, windowMode)) {
2922        CreateWindowStateDetectTask(isAttach, windowMode);
2923    }
2924}
2925
2926bool Session::GetShowRecent() const
2927{
2928    return showRecent_;
2929}
2930
2931bool Session::GetAttachState() const
2932{
2933    return isAttach_;
2934}
2935
2936DetectTaskInfo Session::GetDetectTaskInfo() const
2937{
2938    std::shared_lock<std::shared_mutex> lock(detectTaskInfoMutex_);
2939    return detectTaskInfo_;
2940}
2941
2942void Session::SetDetectTaskInfo(const DetectTaskInfo& detectTaskInfo)
2943{
2944    std::unique_lock<std::shared_mutex> lock(detectTaskInfoMutex_);
2945    detectTaskInfo_ = detectTaskInfo;
2946}
2947
2948bool Session::IsStateMatch(bool isAttach) const
2949{
2950    return isAttach ? ATTACH_MAP.at(GetSessionState()) : DETACH_MAP.at(GetSessionState());
2951}
2952
2953bool Session::IsSupportDetectWindow(bool isAttach)
2954{
2955    if (!systemConfig_.IsPcWindow() && !systemConfig_.IsPhoneWindow()) {
2956        TLOGD(WmsLogTag::WMS_LIFE, "device type not support, id:%{public}d", persistentId_);
2957        return false;
2958    }
2959    if (isScreenLockedCallback_ && isScreenLockedCallback_()) {
2960        TLOGD(WmsLogTag::WMS_LIFE, "screen locked, id:%{public}d", persistentId_);
2961        return false;
2962    }
2963    if (!SessionHelper::IsMainWindow(GetWindowType())) {
2964        TLOGD(WmsLogTag::WMS_LIFE, "only support main window, id:%{public}d", persistentId_);
2965        return false;
2966    }
2967    // Only detecting cold start scenarios on PC
2968    if (systemConfig_.IsPcWindow() && (!isAttach || state_ != SessionState::STATE_DISCONNECT)) {
2969        TLOGD(WmsLogTag::WMS_LIFE, "pc only support cold start, id:%{public}d", persistentId_);
2970        RemoveWindowDetectTask();
2971        return false;
2972    }
2973    return true;
2974}
2975
2976void Session::RemoveWindowDetectTask()
2977{
2978    if (handler_) {
2979        handler_->RemoveTask(GetWindowDetectTaskName());
2980    }
2981}
2982
2983bool Session::ShouldCreateDetectTask(bool isAttach, WindowMode windowMode) const
2984{
2985    // Create detect task directy without pre-exiting tasks.
2986    if (GetDetectTaskInfo().taskState == DetectTaskState::NO_TASK) {
2987        return true;
2988    }
2989    // If the taskState matches the attach detach state, it will be create detect task directly.
2990    if ((GetDetectTaskInfo().taskState == DetectTaskState::ATTACH_TASK && isAttach) ||
2991        (GetDetectTaskInfo().taskState == DetectTaskState::DETACH_TASK && !isAttach)) {
2992        return true;
2993    } else {
2994        // Do not create detect task if the windowMode changes.
2995        return GetDetectTaskInfo().taskWindowMode == windowMode;
2996    }
2997}
2998
2999bool Session::ShouldCreateDetectTaskInRecent(bool newShowRecent, bool oldShowRecent, bool isAttach) const
3000{
3001    if (newShowRecent) {
3002        return false;
3003    }
3004    return oldShowRecent ? isAttach : false;
3005}
3006
3007void Session::RegisterIsScreenLockedCallback(const std::function<bool()>& callback)
3008{
3009    isScreenLockedCallback_ = callback;
3010}
3011
3012std::string Session::GetWindowDetectTaskName() const
3013{
3014    return "wms:WindowStateDetect" + std::to_string(persistentId_);
3015}
3016
3017void Session::CreateWindowStateDetectTask(bool isAttach, WindowMode windowMode)
3018{
3019    if (!handler_) {
3020        return;
3021    }
3022    std::string taskName = GetWindowDetectTaskName();
3023    RemoveWindowDetectTask();
3024    auto detectTask = [weakThis = wptr(this), isAttach]() {
3025        auto session = weakThis.promote();
3026        if (session == nullptr) {
3027            if (isAttach) {
3028                TLOGE(WmsLogTag::WMS_LIFE, "Window attach state and session"
3029                    "state mismatch, session is nullptr, attach:%{public}d", isAttach);
3030            }
3031            return;
3032        }
3033        // Skip state detect when screen locked.
3034        if (session->isScreenLockedCallback_ && !session->isScreenLockedCallback_()) {
3035            if (!session->IsStateMatch(isAttach)) {
3036                TLOGE(WmsLogTag::WMS_LIFE, "Window attach state and session state mismatch, "
3037                    "attach:%{public}d, sessioniState:%{public}d, persistenId:%{public}d, bundleName:%{public}s",
3038                    isAttach, static_cast<uint32_t>(session->GetSessionState()),
3039                    session->GetPersistentId(), session->GetSessionInfo().bundleName_.c_str());
3040            }
3041        }
3042        DetectTaskInfo detectTaskInfo;
3043        session->SetDetectTaskInfo(detectTaskInfo);
3044    };
3045    handler_->PostTask(detectTask, taskName, STATE_DETECT_DELAYTIME);
3046    DetectTaskInfo detectTaskInfo;
3047    detectTaskInfo.taskWindowMode = windowMode;
3048    detectTaskInfo.taskState = isAttach ? DetectTaskState::ATTACH_TASK : DetectTaskState::DETACH_TASK;
3049    SetDetectTaskInfo(detectTaskInfo);
3050}
3051
3052void Session::SetBufferAvailable(bool bufferAvailable)
3053{
3054    WLOGFI("SetBufferAvailable: %{public}d", bufferAvailable);
3055    if (bufferAvailableChangeFunc_) {
3056        bufferAvailableChangeFunc_(bufferAvailable);
3057    }
3058    bufferAvailable_ = bufferAvailable;
3059}
3060
3061bool Session::GetBufferAvailable() const
3062{
3063    return bufferAvailable_;
3064}
3065
3066void Session::SetNeedSnapshot(bool needSnapshot)
3067{
3068    needSnapshot_ = needSnapshot;
3069}
3070
3071void Session::SetExitSplitOnBackground(bool isExitSplitOnBackground)
3072{
3073    TLOGW(WmsLogTag::WMS_MULTI_WINDOW, "id: %{public}d, SetExitSplitOnBackground not implement", persistentId_);
3074}
3075
3076bool Session::IsExitSplitOnBackground() const
3077{
3078    TLOGW(WmsLogTag::WMS_MULTI_WINDOW, "id: %{public}d, IsExitSplitOnBackground not implement", persistentId_);
3079    return false;
3080}
3081
3082void Session::SetFloatingScale(float floatingScale)
3083{
3084    floatingScale_ = floatingScale;
3085}
3086
3087float Session::GetFloatingScale() const
3088{
3089    return floatingScale_;
3090}
3091
3092void Session::SetScale(float scaleX, float scaleY, float pivotX, float pivotY)
3093{
3094    scaleX_ = scaleX;
3095    scaleY_ = scaleY;
3096    pivotX_ = pivotX;
3097    pivotY_ = pivotY;
3098}
3099
3100float Session::GetScaleX() const
3101{
3102    return scaleX_;
3103}
3104
3105float Session::GetScaleY() const
3106{
3107    return scaleY_;
3108}
3109
3110float Session::GetPivotX() const
3111{
3112    return pivotX_;
3113}
3114
3115float Session::GetPivotY() const
3116{
3117    return pivotY_;
3118}
3119
3120void Session::SetSCBKeepKeyboard(bool scbKeepKeyboardFlag)
3121{
3122    scbKeepKeyboardFlag_ = scbKeepKeyboardFlag;
3123}
3124
3125bool Session::GetSCBKeepKeyboardFlag() const
3126{
3127    return scbKeepKeyboardFlag_;
3128}
3129
3130void Session::SetOffset(float x, float y)
3131{
3132    offsetX_ = x;
3133    offsetY_ = y;
3134    WSRect newRect {
3135        .posX_ = std::round(bounds_.posX_ + x),
3136        .posY_ = std::round(bounds_.posY_ + y),
3137        .width_ = std::round(bounds_.width_),
3138        .height_ = std::round(bounds_.height_),
3139    };
3140    if (newRect != winRect_) {
3141        UpdateRect(newRect, SizeChangeReason::UNDEFINED, "SetOffset");
3142    }
3143}
3144
3145float Session::GetOffsetX() const
3146{
3147    return offsetX_;
3148}
3149
3150float Session::GetOffsetY() const
3151{
3152    return offsetY_;
3153}
3154
3155void Session::SetBounds(const WSRectF& bounds)
3156{
3157    bounds_ = bounds;
3158}
3159
3160WSRectF Session::GetBounds()
3161{
3162    return bounds_;
3163}
3164
3165void Session::SetRotation(Rotation rotation)
3166{
3167    rotation_ = rotation;
3168}
3169
3170Rotation Session::GetRotation() const
3171{
3172    return rotation_;
3173}
3174
3175WSError Session::UpdateTitleInTargetPos(bool isShow, int32_t height)
3176{
3177    WLOGFD("Session update title in target position, id: %{public}d, isShow: %{public}d, height: %{public}d",
3178        GetPersistentId(), isShow, height);
3179    if (!IsSessionValid()) {
3180        TLOGW(WmsLogTag::WMS_MAIN, "Session is invalid, id: %{public}d state: %{public}u",
3181            GetPersistentId(), GetSessionState());
3182        return WSError::WS_ERROR_INVALID_SESSION;
3183    }
3184    if (!sessionStage_) {
3185        TLOGE(WmsLogTag::WMS_MAIN, "sessionStage_ is null");
3186        return WSError::WS_ERROR_NULLPTR;
3187    }
3188    return sessionStage_->UpdateTitleInTargetPos(isShow, height);
3189}
3190
3191void Session::SetSessionInfoLockedStateChangeListener(const NotifySessionInfoLockedStateChangeFunc& func)
3192{
3193    sessionInfoLockedStateChangeFunc_ = func;
3194}
3195
3196void Session::NotifySessionInfoLockedStateChange(bool lockedState)
3197{
3198    WLOGFD("Notify sessioninfo lockedstate change: %{public}u", lockedState);
3199    if (sessionInfoLockedStateChangeFunc_) {
3200        sessionInfoLockedStateChangeFunc_(lockedState);
3201    }
3202}
3203
3204WSError Session::SwitchFreeMultiWindow(bool enable)
3205{
3206    TLOGD(WmsLogTag::WMS_LAYOUT, "windowId:%{public}d enable: %{public}d", GetPersistentId(), enable);
3207    systemConfig_.freeMultiWindowEnable_ = enable;
3208    if (!IsSessionValid()) {
3209        TLOGD(WmsLogTag::WMS_LAYOUT, "Session is invalid, id: %{public}d state: %{public}u",
3210            GetPersistentId(), GetSessionState());
3211        return WSError::WS_ERROR_INVALID_SESSION;
3212    }
3213    if (!sessionStage_) {
3214        TLOGE(WmsLogTag::WMS_MAIN, "sessionStage_ is null");
3215        return WSError::WS_ERROR_NULLPTR;
3216    }
3217    return sessionStage_->SwitchFreeMultiWindow(enable);
3218}
3219
3220WSError Session::GetUIContentRemoteObj(sptr<IRemoteObject>& uiContentRemoteObj)
3221{
3222    if (!IsSessionValid()) {
3223        TLOGE(WmsLogTag::DEFAULT, "session %{public}d is invalid. Failed to get UIContentRemoteObj", GetPersistentId());
3224        return WSError::WS_ERROR_INVALID_SESSION;
3225    }
3226    if (sessionStage_ == nullptr) {
3227        TLOGE(WmsLogTag::DEFAULT, "sessionStage_ is nullptr");
3228        return WSError::WS_ERROR_NULLPTR;
3229    }
3230    return sessionStage_->GetUIContentRemoteObj(uiContentRemoteObj);
3231}
3232
3233void Session::SetNotifySystemSessionPointerEventFunc(const NotifySystemSessionPointerEventFunc& func)
3234{
3235    std::lock_guard<std::mutex> lock(pointerEventMutex_);
3236    systemSessionPointerEventFunc_ = func;
3237}
3238
3239void Session::SetNotifySystemSessionKeyEventFunc(const NotifySystemSessionKeyEventFunc& func)
3240{
3241    std::unique_lock<std::shared_mutex> lock(keyEventMutex_);
3242    systemSessionKeyEventFunc_ = func;
3243}
3244
3245void Session::NotifySessionInfoChange()
3246{
3247    if (sessionInfoChangeNotifyManagerFunc_) {
3248        sessionInfoChangeNotifyManagerFunc_(GetPersistentId());
3249    }
3250}
3251
3252bool Session::NeedCheckContextTransparent() const
3253{
3254    return contextTransparentFunc_ != nullptr;
3255}
3256
3257void Session::SetContextTransparentFunc(const NotifyContextTransparentFunc& func)
3258{
3259    contextTransparentFunc_ = func;
3260}
3261
3262void Session::NotifyContextTransparent()
3263{
3264    if (contextTransparentFunc_) {
3265        int32_t eventRet = HiSysEventWrite(
3266            OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER,
3267            "SESSION_IS_TRANSPARENT",
3268            OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
3269            "PERSISTENT_ID", GetPersistentId(),
3270            "BUNDLE_NAME", sessionInfo_.bundleName_);
3271        WLOGFE("Session context is transparent, persistentId:%{public}d, eventRet:%{public}d",
3272            GetPersistentId(), eventRet);
3273        contextTransparentFunc_();
3274    }
3275}
3276
3277bool Session::IsSystemInput()
3278{
3279    return sessionInfo_.sceneType_ == SceneType::INPUT_SCENE;
3280}
3281
3282void Session::SetIsMidScene(bool isMidScene)
3283{
3284    auto task = [weakThis = wptr(this), isMidScene] {
3285        auto session = weakThis.promote();
3286        if (session == nullptr) {
3287            TLOGI(WmsLogTag::WMS_MULTI_WINDOW, "session is null");
3288            return;
3289        }
3290        if (session->isMidScene_ != isMidScene) {
3291            TLOGI(WmsLogTag::WMS_MULTI_WINDOW, "persistentId:%{public}d, isMidScene:%{public}d",
3292                session->GetPersistentId(), isMidScene);
3293            session->isMidScene_ = isMidScene;
3294        }
3295    };
3296    PostTask(task, "SetIsMidScene");
3297}
3298
3299bool Session::GetIsMidScene() const
3300{
3301    return isMidScene_;
3302}
3303
3304void Session::SetTouchHotAreas(const std::vector<Rect>& touchHotAreas)
3305{
3306    auto property = GetSessionProperty();
3307    if (property == nullptr) {
3308        return;
3309    }
3310    std::vector<Rect> lastTouchHotAreas;
3311    property->GetTouchHotAreas(lastTouchHotAreas);
3312    if (touchHotAreas == lastTouchHotAreas) {
3313        return;
3314    }
3315
3316    dirtyFlags_ |= static_cast<uint32_t>(SessionUIDirtyFlag::TOUCH_HOT_AREA);
3317    std::string rectStr;
3318    for (const auto& rect : touchHotAreas) {
3319        rectStr = rectStr + " hot : " + rect.ToString();
3320    }
3321    TLOGI(WmsLogTag::WMS_EVENT, "id:%{public}d rects:%{public}s", GetPersistentId(), rectStr.c_str());
3322    property->SetTouchHotAreas(touchHotAreas);
3323}
3324
3325std::shared_ptr<Media::PixelMap> Session::GetSnapshotPixelMap(const float oriScale, const float newScale)
3326{
3327    TLOGI(WmsLogTag::WMS_MAIN, "id %{public}d", GetPersistentId());
3328    if (scenePersistence_ == nullptr) {
3329        return nullptr;
3330    }
3331    return scenePersistence_->IsSavingSnapshot() ? GetSnapshot() :
3332        scenePersistence_->GetLocalSnapshotPixelMap(oriScale, newScale);
3333}
3334
3335bool Session::IsVisibleForeground() const
3336{
3337    return isVisible_ && IsSessionForeground();
3338}
3339
3340void Session::SetIsStarting(bool isStarting)
3341{
3342    isStarting_ = isStarting;
3343}
3344
3345void Session::ResetDirtyFlags()
3346{
3347    if (!isVisible_) {
3348        dirtyFlags_ &= static_cast<uint32_t>(SessionUIDirtyFlag::AVOID_AREA);
3349    } else {
3350        dirtyFlags_ = 0;
3351    }
3352}
3353
3354void Session::SetUIStateDirty(bool dirty)
3355{
3356    mainUIStateDirty_.store(dirty);
3357}
3358
3359bool Session::GetUIStateDirty() const
3360{
3361    return mainUIStateDirty_.load();
3362}
3363
3364void Session::SetMainSessionUIStateDirty(bool dirty)
3365{
3366    if (GetParentSession() && WindowHelper::IsMainWindow(GetParentSession()->GetWindowType())) {
3367        GetParentSession()->SetUIStateDirty(dirty);
3368    }
3369}
3370
3371bool Session::IsScbCoreEnabled()
3372{
3373    return isScbCoreEnabled_;
3374}
3375
3376void Session::SetScbCoreEnabled(bool enabled)
3377{
3378    TLOGI(WmsLogTag::WMS_PIPELINE, "%{public}d", enabled);
3379    isScbCoreEnabled_ = enabled;
3380}
3381
3382bool Session::IsVisible() const
3383{
3384    return isVisible_;
3385}
3386} // namespace OHOS::Rosen
3387