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/main_session.h"
17 
18 #include <ui/rs_surface_node.h>
19 
20 #include "key_event.h"
21 #include "pointer_event.h"
22 #include "session_helper.h"
23 #include "session/host/include/scene_persistent_storage.h"
24 #include "window_manager_hilog.h"
25 
26 namespace OHOS::Rosen {
27 namespace {
28 constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, HILOG_DOMAIN_WINDOW, "MainSession" };
29 } // namespace
30 
MainSession(const SessionInfo& info, const sptr<SpecificSessionCallback>& specificCallback)31 MainSession::MainSession(const SessionInfo& info, const sptr<SpecificSessionCallback>& specificCallback)
32     : SceneSession(info, specificCallback)
33 {
34     scenePersistence_ = sptr<ScenePersistence>::MakeSptr(info.bundleName_, GetPersistentId());
35     if (info.persistentId_ != 0 && info.persistentId_ != GetPersistentId()) {
36         // persistentId changed due to id conflicts. Need to rename the old snapshot if exists
37         scenePersistence_->RenameSnapshotFromOldPersistentId(info.persistentId_);
38     }
39     moveDragController_ = sptr<MoveDragController>::MakeSptr(GetPersistentId());
40     if (specificCallback != nullptr &&
41         specificCallback->onWindowInputPidChangeCallback_ != nullptr) {
42         moveDragController_->SetNotifyWindowPidChangeCallback(specificCallback->onWindowInputPidChangeCallback_);
43     }
44     SetMoveDragCallback();
45     std::string key = GetRatioPreferenceKey();
46     if (!key.empty()) {
47         if (ScenePersistentStorage::HasKey(key, ScenePersistentStorageType::ASPECT_RATIO)) {
48             ScenePersistentStorage::Get(key, aspectRatio_, ScenePersistentStorageType::ASPECT_RATIO);
49             WLOGFD("init aspectRatio, key %{public}s, value: %{public}f", key.c_str(), aspectRatio_);
50             moveDragController_->SetAspectRatio(aspectRatio_);
51         }
52     }
53 
54     WLOGFD("Create MainSession");
55 }
56 
~MainSession()57 MainSession::~MainSession()
58 {
59     WLOGD("~MainSession, id: %{public}d", GetPersistentId());
60 }
61 
Reconnect(const sptr<ISessionStage>& sessionStage, const sptr<IWindowEventChannel>& eventChannel, const std::shared_ptr<RSSurfaceNode>& surfaceNode, sptr<WindowSessionProperty> property, sptr<IRemoteObject> token, int32_t pid, int32_t uid)62 WSError MainSession::Reconnect(const sptr<ISessionStage>& sessionStage, const sptr<IWindowEventChannel>& eventChannel,
63     const std::shared_ptr<RSSurfaceNode>& surfaceNode, sptr<WindowSessionProperty> property, sptr<IRemoteObject> token,
64     int32_t pid, int32_t uid)
65 {
66     return PostSyncTask([weakThis = wptr(this), sessionStage, eventChannel, surfaceNode, property, token, pid, uid]() {
67         auto session = weakThis.promote();
68         if (!session) {
69             WLOGFE("session is null");
70             return WSError::WS_ERROR_DESTROYED_OBJECT;
71         }
72         WSError ret = session->Session::Reconnect(sessionStage, eventChannel, surfaceNode, property, token, pid, uid);
73         if (ret != WSError::WS_OK) {
74             return ret;
75         }
76         WindowState windowState = property->GetWindowState();
77         if (windowState == WindowState::STATE_SHOWN) {
78             session->isActive_ = true;
79             session->UpdateSessionState(SessionState::STATE_ACTIVE);
80         } else {
81             session->isActive_ = false;
82             session->UpdateSessionState(SessionState::STATE_BACKGROUND);
83             if (session->scenePersistence_) {
84                 session->scenePersistence_->SetHasSnapshot(true);
85             }
86         }
87         return ret;
88     });
89 }
90 
ProcessPointDownSession(int32_t posX, int32_t posY)91 WSError MainSession::ProcessPointDownSession(int32_t posX, int32_t posY)
92 {
93     const auto& id = GetPersistentId();
94     WLOGFI("id: %{public}d, type: %{public}d", id, GetWindowType());
95     if (CheckDialogOnForeground()) {
96         HandlePointDownDialog();
97         return WSError::WS_OK;
98     }
99     PresentFocusIfPointDown();
100     return SceneSession::ProcessPointDownSession(posX, posY);
101 }
102 
NotifyForegroundInteractiveStatus(bool interactive)103 void MainSession::NotifyForegroundInteractiveStatus(bool interactive)
104 {
105     SetForegroundInteractiveStatus(interactive);
106     if (!IsSessionValid() || !sessionStage_) {
107         TLOGW(WmsLogTag::WMS_MAIN, "Session or sessionStage is invalid, id: %{public}d state: %{public}u",
108             GetPersistentId(), GetSessionState());
109         return;
110     }
111     const auto& state = GetSessionState();
112     if (isVisible_ || state == SessionState::STATE_ACTIVE || state == SessionState::STATE_FOREGROUND) {
113         WLOGFI("NotifyForegroundInteractiveStatus %{public}d", interactive);
114         sessionStage_->NotifyForegroundInteractiveStatus(interactive);
115     }
116 }
117 
TransferKeyEvent(const std::shared_ptr<MMI::KeyEvent>& keyEvent)118 WSError MainSession::TransferKeyEvent(const std::shared_ptr<MMI::KeyEvent>& keyEvent)
119 {
120     if (!IsSessionValid()) {
121         return WSError::WS_ERROR_INVALID_SESSION;
122     }
123     if (keyEvent == nullptr) {
124         WLOGFE("KeyEvent is nullptr");
125         return WSError::WS_ERROR_NULLPTR;
126     }
127     if (CheckDialogOnForeground()) {
128         TLOGD(WmsLogTag::WMS_DIALOG, "Has dialog on foreground, not transfer pointer event");
129         return WSError::WS_ERROR_INVALID_PERMISSION;
130     }
131 
132     WSError ret = Session::TransferKeyEvent(keyEvent);
133     return ret;
134 }
135 
UpdatePointerArea(const WSRect& rect)136 void MainSession::UpdatePointerArea(const WSRect& rect)
137 {
138     if (GetWindowMode() != WindowMode::WINDOW_MODE_FLOATING) {
139         return;
140     }
141     Session::UpdatePointerArea(rect);
142 }
143 
CheckPointerEventDispatch(const std::shared_ptr<MMI::PointerEvent>& pointerEvent) const144 bool MainSession::CheckPointerEventDispatch(const std::shared_ptr<MMI::PointerEvent>& pointerEvent) const
145 {
146     auto sessionState = GetSessionState();
147     int32_t action = pointerEvent->GetPointerAction();
148     if (sessionState != SessionState::STATE_FOREGROUND &&
149         sessionState != SessionState::STATE_ACTIVE &&
150         action != MMI::PointerEvent::POINTER_ACTION_LEAVE_WINDOW) {
151         WLOGFW("Current Session Info: [persistentId: %{public}d, "
152             "state: %{public}d, action:%{public}d]", GetPersistentId(), GetSessionState(), action);
153         return false;
154     }
155     return true;
156 }
157 
SetTopmost(bool topmost)158 WSError MainSession::SetTopmost(bool topmost)
159 {
160     TLOGI(WmsLogTag::WMS_HIERARCHY, "SetTopmost id: %{public}d, topmost: %{public}d", GetPersistentId(), topmost);
161     auto task = [weakThis = wptr(this), topmost]() {
162         auto session = weakThis.promote();
163         if (!session) {
164             TLOGE(WmsLogTag::WMS_HIERARCHY, "session is null");
165             return;
166         }
167         auto property = session->GetSessionProperty();
168         if (property) {
169             TLOGI(WmsLogTag::WMS_HIERARCHY, "Notify session topmost change, id: %{public}d, topmost: %{public}u",
170                 session->GetPersistentId(), topmost);
171             property->SetTopmost(topmost);
172             if (session->sessionChangeCallback_ && session->sessionChangeCallback_->onSessionTopmostChange_) {
173                 session->sessionChangeCallback_->onSessionTopmostChange_(topmost);
174             }
175         }
176     };
177     PostTask(task, "SetTopmost");
178     return WSError::WS_OK;
179 }
180 
IsTopmost() const181 bool MainSession::IsTopmost() const
182 {
183     return GetSessionProperty()->IsTopmost();
184 }
185 
SetMainWindowTopmost(bool isTopmost)186 WSError MainSession::SetMainWindowTopmost(bool isTopmost)
187 {
188     auto property = GetSessionProperty();
189     if (property) {
190         property->SetMainWindowTopmost(isTopmost);
191         TLOGD(WmsLogTag::WMS_HIERARCHY,
192             "Notify session topmost change, id: %{public}d, isTopmost: %{public}u",
193             GetPersistentId(), isTopmost);
194         if (mainWindowTopmostChangeFunc_) {
195             mainWindowTopmostChangeFunc_(isTopmost);
196         }
197     }
198     return WSError::WS_OK;
199 }
200 
IsMainWindowTopmost() const201 bool MainSession::IsMainWindowTopmost() const
202 {
203     return GetSessionProperty()->IsMainWindowTopmost();
204 }
205 
RectCheck(uint32_t curWidth, uint32_t curHeight)206 void MainSession::RectCheck(uint32_t curWidth, uint32_t curHeight)
207 {
208     uint32_t minWidth = GetSystemConfig().miniWidthOfMainWindow_;
209     uint32_t minHeight = GetSystemConfig().miniHeightOfMainWindow_;
210     uint32_t maxFloatingWindowSize = GetSystemConfig().maxFloatingWindowSize_;
211     RectSizeCheckProcess(curWidth, curHeight, minWidth, minHeight, maxFloatingWindowSize);
212 }
213 
SetExitSplitOnBackground(bool isExitSplitOnBackground)214 void MainSession::SetExitSplitOnBackground(bool isExitSplitOnBackground)
215 {
216     TLOGI(WmsLogTag::WMS_MULTI_WINDOW, "id: %{public}d, isExitSplitOnBackground: %{public}d", persistentId_,
217         isExitSplitOnBackground);
218     isExitSplitOnBackground_ = isExitSplitOnBackground;
219 }
220 
IsExitSplitOnBackground() const221 bool MainSession::IsExitSplitOnBackground() const
222 {
223     return isExitSplitOnBackground_;
224 }
225 
NotifyClientToUpdateInteractive(bool interactive)226 void MainSession::NotifyClientToUpdateInteractive(bool interactive)
227 {
228     if (!sessionStage_) {
229         return;
230     }
231     const auto state = GetSessionState();
232     if (state == SessionState::STATE_ACTIVE || state == SessionState::STATE_FOREGROUND) {
233         WLOGFI("%{public}d", interactive);
234         sessionStage_->NotifyForegroundInteractiveStatus(interactive);
235         isClientInteractive_ = interactive;
236     }
237 }
238 
OnRestoreMainWindow()239 WSError MainSession::OnRestoreMainWindow()
240 {
241     auto task = [weakThis = wptr(this)]() {
242         auto session = weakThis.promote();
243         if (!session) {
244             TLOGNE(WmsLogTag::WMS_LIFE, "session is null");
245             return WSError::WS_ERROR_DESTROYED_OBJECT;
246         }
247         if (session->sessionChangeCallback_ && session->sessionChangeCallback_->onRestoreMainWindowFunc_) {
248             session->sessionChangeCallback_->onRestoreMainWindowFunc_();
249         }
250         return WSError::WS_OK;
251     };
252     PostTask(task, "OnRestoreMainWindow");
253     return WSError::WS_OK;
254 }
255 
256 } // namespace OHOS::Rosen
257