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_manager/include/extension_session_manager.h"
17 
18 #include <ability_manager_client.h>
19 #include <hitrace_meter.h>
20 
21 #include "display_info.h"
22 #include "display_manager.h"
23 #include "singleton_container.h"
24 
25 #include "session/host/include/extension_session.h"
26 
27 namespace OHOS::Rosen {
28 namespace {
29 constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, HILOG_DOMAIN_WINDOW, "ExtensionSessionManager" };
30 const std::string EXTENSION_SESSION_MANAGER_THREAD = "OS_ExtensionSessionManager";
31 } // namespace
32 
ExtensionSessionManager()33 ExtensionSessionManager::ExtensionSessionManager()
34 {
35     taskScheduler_ = std::make_shared<TaskScheduler>(EXTENSION_SESSION_MANAGER_THREAD);
36 }
37 
38 WM_IMPLEMENT_SINGLE_INSTANCE(ExtensionSessionManager)
39 
SetAbilitySessionInfo(const sptr<ExtensionSession>& extSession)40 sptr<AAFwk::SessionInfo> ExtensionSessionManager::SetAbilitySessionInfo(const sptr<ExtensionSession>& extSession)
41 {
42     sptr<AAFwk::SessionInfo> abilitySessionInfo = new (std::nothrow) AAFwk::SessionInfo();
43     if (!abilitySessionInfo) {
44         WLOGFE("abilitySessionInfo is nullptr");
45         return nullptr;
46     }
47     auto sessionInfo = extSession->GetSessionInfo();
48     sptr<ISession> iSession(extSession);
49     abilitySessionInfo->sessionToken = iSession->AsObject();
50     abilitySessionInfo->callerToken = sessionInfo.callerToken_;
51     abilitySessionInfo->parentToken = sessionInfo.rootToken_;
52     abilitySessionInfo->persistentId = extSession->GetPersistentId();
53     abilitySessionInfo->realHostWindowId = sessionInfo.realParentId_;
54     abilitySessionInfo->isAsyncModalBinding = sessionInfo.isAsyncModalBinding_;
55     abilitySessionInfo->uiExtensionUsage = static_cast<AAFwk::UIExtensionUsage>(sessionInfo.uiExtensionUsage_);
56     abilitySessionInfo->parentWindowType = sessionInfo.parentWindowType_;
57     abilitySessionInfo->displayId = sessionInfo.config_.displayId_;
58     abilitySessionInfo->density = sessionInfo.config_.density_;
59     abilitySessionInfo->orientation = sessionInfo.config_.orientation_;
60     if (sessionInfo.want != nullptr) {
61         abilitySessionInfo->want = *sessionInfo.want;
62     }
63     return abilitySessionInfo;
64 }
65 
GetSystemDensity(uint64_t displayId)66 float ExtensionSessionManager::GetSystemDensity(uint64_t displayId)
67 {
68     float vpr = 1.0f;
69     auto display = SingletonContainer::Get<DisplayManager>().GetDisplayById(displayId);
70     if (display == nullptr) {
71         TLOGE(WmsLogTag::WMS_UIEXT, "display is null");
72         return vpr;
73     }
74     auto displayInfo = display->GetDisplayInfo();
75     if (displayInfo == nullptr) {
76         TLOGE(WmsLogTag::WMS_UIEXT, "displayInfo is null");
77         return vpr;
78     }
79     return displayInfo->GetVirtualPixelRatio();
80 }
81 
RequestExtensionSession(const SessionInfo& sessionInfo)82 sptr<ExtensionSession> ExtensionSessionManager::RequestExtensionSession(const SessionInfo& sessionInfo)
83 {
84     auto task = [this, sessionInfo]() {
85         HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "RequestExtensionSession");
86         SessionInfo tempSessionInfo = sessionInfo;
87         if (!tempSessionInfo.config_.isDensityFollowHost_) {
88             tempSessionInfo.config_.density_ = GetSystemDensity(tempSessionInfo.config_.displayId_);
89         }
90         sptr<ExtensionSession> extensionSession = new ExtensionSession(tempSessionInfo);
91         extensionSession->SetEventHandler(taskScheduler_->GetEventHandler(), nullptr);
92         auto persistentId = extensionSession->GetPersistentId();
93         TLOGI(WmsLogTag::WMS_UIEXT,
94             "persistentId: %{public}d, bundleName: %{public}s, moduleName: %{public}s, abilityName: %{public}s, "
95             "isDensityFollowHost_: %{public}d, density_: %{public}f",
96             persistentId, tempSessionInfo.bundleName_.c_str(), tempSessionInfo.moduleName_.c_str(),
97             tempSessionInfo.abilityName_.c_str(), tempSessionInfo.config_.isDensityFollowHost_,
98             tempSessionInfo.config_.density_);
99         extensionSessionMap_.insert({ persistentId, extensionSession });
100         return extensionSession;
101     };
102 
103     return taskScheduler_->PostSyncTask(task, "RequestExtensionSession");
104 }
105 
RequestExtensionSessionActivation(const sptr<ExtensionSession>& extensionSession, uint32_t hostWindowId, const std::function<void(WSError)>&& resultCallback)106 WSError ExtensionSessionManager::RequestExtensionSessionActivation(const sptr<ExtensionSession>& extensionSession,
107     uint32_t hostWindowId, const std::function<void(WSError)>&& resultCallback)
108 {
109     wptr<ExtensionSession> weakExtSession(extensionSession);
110     auto task = [this, weakExtSession, hostWindowId, callback = std::move(resultCallback)]() {
111         auto extSession = weakExtSession.promote();
112         if (extSession == nullptr) {
113             WLOGFE("session is nullptr");
114             return WSError::WS_ERROR_NULLPTR;
115         }
116         auto persistentId = extSession->GetPersistentId();
117         WLOGFI("Activate session with persistentId: %{public}d", persistentId);
118         HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "esm:RequestExtensionSessionActivation");
119         if (extensionSessionMap_.count(persistentId) == 0) {
120             WLOGFE("RequestExtensionSessionActivation Session is invalid! persistentId:%{public}d", persistentId);
121             return WSError::WS_ERROR_INVALID_SESSION;
122         }
123         auto extSessionInfo = SetAbilitySessionInfo(extSession);
124         if (extSessionInfo == nullptr) {
125             return WSError::WS_ERROR_NULLPTR;
126         }
127         extSessionInfo->hostWindowId = hostWindowId;
128         auto errorCode = AAFwk::AbilityManagerClient::GetInstance()->StartUIExtensionAbility(extSessionInfo,
129             AAFwk::DEFAULT_INVAL_VALUE);
130         if (callback) {
131             auto ret = errorCode == ERR_OK ? WSError::WS_OK : WSError::WS_ERROR_START_UI_EXTENSION_ABILITY_FAILED;
132             callback(ret);
133             return ret;
134         }
135         return WSError::WS_OK;
136     };
137     taskScheduler_->PostAsyncTask(task, "RequestExtensionSessionActivation");
138     return WSError::WS_OK;
139 }
140 
RequestExtensionSessionBackground(const sptr<ExtensionSession>& extensionSession, const std::function<void(WSError)>&& resultCallback)141 WSError ExtensionSessionManager::RequestExtensionSessionBackground(const sptr<ExtensionSession>& extensionSession,
142     const std::function<void(WSError)>&& resultCallback)
143 {
144     wptr<ExtensionSession> weakExtSession(extensionSession);
145     auto task = [this, weakExtSession, callback = std::move(resultCallback)]() {
146         auto extSession = weakExtSession.promote();
147         if (extSession == nullptr) {
148             WLOGFE("session is nullptr");
149             return WSError::WS_ERROR_NULLPTR;
150         }
151         auto persistentId = extSession->GetPersistentId();
152         WLOGFI("Background session with persistentId: %{public}d", persistentId);
153         HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "esm:RequestExtensionSessionBackground");
154         extSession->SetActive(false);
155         extSession->Background();
156         if (extensionSessionMap_.count(persistentId) == 0) {
157             WLOGFE("RequestExtensionSessionBackground Session is invalid! persistentId:%{public}d", persistentId);
158             return WSError::WS_ERROR_INVALID_SESSION;
159         }
160         auto extSessionInfo = SetAbilitySessionInfo(extSession);
161         if (!extSessionInfo) {
162             return WSError::WS_ERROR_NULLPTR;
163         }
164         auto errorCode = AAFwk::AbilityManagerClient::GetInstance()->MinimizeUIExtensionAbility(extSessionInfo);
165         if (callback) {
166             auto ret = errorCode == ERR_OK ? WSError::WS_OK : WSError::WS_ERROR_MIN_UI_EXTENSION_ABILITY_FAILED;
167             callback(ret);
168             return ret;
169         }
170         return WSError::WS_OK;
171     };
172     taskScheduler_->PostAsyncTask(task, "RequestExtensionSessionBackground");
173     return WSError::WS_OK;
174 }
175 
RequestExtensionSessionDestruction(const sptr<ExtensionSession>& extensionSession, const std::function<void(WSError)>&& resultCallback)176 WSError ExtensionSessionManager::RequestExtensionSessionDestruction(const sptr<ExtensionSession>& extensionSession,
177     const std::function<void(WSError)>&& resultCallback)
178 {
179     wptr<ExtensionSession> weakExtSession(extensionSession);
180     auto task = [this, weakExtSession, callback = std::move(resultCallback)]() {
181         auto extSession = weakExtSession.promote();
182         if (extSession == nullptr) {
183             WLOGFE("session is nullptr");
184             return WSError::WS_ERROR_NULLPTR;
185         }
186         auto persistentId = extSession->GetPersistentId();
187         WLOGFI("Destroy session with persistentId: %{public}d", persistentId);
188         HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "esm:RequestExtensionSessionDestruction");
189         extSession->Disconnect();
190         if (extensionSessionMap_.count(persistentId) == 0) {
191             WLOGFE("RequestExtensionSessionDestruction Session is invalid! persistentId:%{public}d", persistentId);
192             return WSError::WS_ERROR_INVALID_SESSION;
193         }
194         auto extSessionInfo = SetAbilitySessionInfo(extSession);
195         if (!extSessionInfo) {
196             return WSError::WS_ERROR_NULLPTR;
197         }
198         auto errorCode = AAFwk::AbilityManagerClient::GetInstance()->TerminateUIExtensionAbility(extSessionInfo);
199         extensionSessionMap_.erase(persistentId);
200         if (callback) {
201             auto ret = errorCode == ERR_OK ? WSError::WS_OK : WSError::WS_ERROR_TERMINATE_UI_EXTENSION_ABILITY_FAILED;
202             callback(ret);
203             return ret;
204         }
205         return WSError::WS_OK;
206     };
207     taskScheduler_->PostAsyncTask(task, "RequestExtensionSessionDestruction");
208     return WSError::WS_OK;
209 }
210 
RequestExtensionSessionDestructionDone(const sptr<ExtensionSession>& extensionSession)211 WSError ExtensionSessionManager::RequestExtensionSessionDestructionDone(const sptr<ExtensionSession>& extensionSession)
212 {
213     const char* const where = __func__;
214     auto task = [this, where, weakExtSession = wptr<ExtensionSession>(extensionSession)] {
215         auto extSession = weakExtSession.promote();
216         if (extSession == nullptr) {
217             TLOGNE(WmsLogTag::WMS_UIEXT, "%{public}s session is nullptr", where);
218             return;
219         }
220         auto persistentId = extSession->GetPersistentId();
221         TLOGNI(WmsLogTag::WMS_UIEXT, "Destroy session done with persistentId: %{public}d", persistentId);
222         HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "esm:%{public}s", where);
223         if (extensionSessionMap_.count(persistentId) == 0) {
224             TLOGNE(WmsLogTag::WMS_UIEXT, "%{public}s session is invalid! persistentId: %{public}d",
225                 where, persistentId);
226             return;
227         }
228         auto extSessionInfo = SetAbilitySessionInfo(extSession);
229         if (!extSessionInfo) {
230             return;
231         }
232         AAFwk::AbilityManagerClient::GetInstance()->TerminateUIExtensionAbility(extSessionInfo);
233         extensionSessionMap_.erase(persistentId);
234     };
235     taskScheduler_->PostAsyncTask(task, __func__);
236     return WSError::WS_OK;
237 }
238 } // namespace OHOS::Rosen
239