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 "core/components_ng/pattern/ui_extension/ui_extension_manager.h"
17
18 #include "adapter/ohos/entrance/ace_container.h"
19 #include "core/components_ng/pattern/ui_extension/security_ui_extension_pattern.h"
20 #include "core/components_ng/pattern/ui_extension/ui_extension_pattern.h"
21
22 namespace OHOS::Ace::NG {
UIExtensionIdUtility()23 UIExtensionIdUtility::UIExtensionIdUtility() {}
24
~UIExtensionIdUtility()25 UIExtensionIdUtility::~UIExtensionIdUtility() {}
26
ApplyExtensionId()27 int32_t UIExtensionIdUtility::ApplyExtensionId()
28 {
29 std::lock_guard<std::mutex> poolMutex(poolMutex_);
30 for (int32_t index = 0; index < UI_EXTENSION_ID_FIRST_MAX; index++) {
31 if (!idPool_.test(index)) {
32 idPool_.set(index, 1);
33 return index + 1;
34 }
35 }
36 return UI_EXTENSION_UNKNOW_ID;
37 }
38
RecycleExtensionId(int32_t id)39 void UIExtensionIdUtility::RecycleExtensionId(int32_t id)
40 {
41 std::lock_guard<std::mutex> poolMutex(poolMutex_);
42 if ((id > UI_EXTENSION_UNKNOW_ID) && (id <= UI_EXTENSION_ID_FIRST_MAX)) {
43 idPool_.set(id - 1, 0);
44 }
45 }
46
RegisterUIExtensionInFocus(const WeakPtr<UIExtensionPattern> & uiExtensionFocused,const WeakPtr<SessionWrapper> & sessionWrapper)47 void UIExtensionManager::RegisterUIExtensionInFocus(
48 const WeakPtr<UIExtensionPattern>& uiExtensionFocused, const WeakPtr<SessionWrapper>& sessionWrapper)
49 {
50 securityUiExtensionFocused_ = nullptr;
51 uiExtensionFocused_ = uiExtensionFocused;
52 sessionWrapper_ = sessionWrapper;
53 }
54
RegisterSecurityUIExtensionInFocus(const WeakPtr<SecurityUIExtensionPattern> & uiExtensionFocused,const WeakPtr<SessionWrapper> & sessionWrapper)55 void UIExtensionManager::RegisterSecurityUIExtensionInFocus(
56 const WeakPtr<SecurityUIExtensionPattern>& uiExtensionFocused,
57 const WeakPtr<SessionWrapper>& sessionWrapper)
58 {
59 uiExtensionFocused_ = nullptr;
60 securityUiExtensionFocused_ = uiExtensionFocused;
61 sessionWrapper_ = sessionWrapper;
62 }
63
OnBackPressed()64 bool UIExtensionManager::OnBackPressed()
65 {
66 auto sessionWrapper = sessionWrapper_.Upgrade();
67 if (sessionWrapper) {
68 return sessionWrapper->NotifyBackPressedSync();
69 }
70
71 return HandleUnfocusedModalUecBackPressed();
72 }
73
DumpUIExt()74 void UIExtensionManager::DumpUIExt()
75 {
76 auto pattern = uiExtensionFocused_.Upgrade();
77 CHECK_NULL_VOID(pattern);
78 pattern->DumpOthers();
79 }
80
HandleUnfocusedModalUecBackPressed()81 bool UIExtensionManager::HandleUnfocusedModalUecBackPressed()
82 {
83 RefPtr<SessionWrapper> session = nullptr;
84 {
85 std::lock_guard<std::mutex> aliveUIExtensionMutex(aliveUIExtensionMutex_);
86 for (auto item = aliveUIExtensions_.rbegin(); item != aliveUIExtensions_.rend(); ++item) {
87 auto uiExtension = item->second.Upgrade();
88 if (uiExtension == nullptr) {
89 continue;
90 }
91
92 if (!uiExtension->IsModalUec()) {
93 continue;
94 }
95
96 bool isForeground = uiExtension->IsForeground();
97 bool isLastModal = IsLastModalUec(uiExtension->GetHost());
98 TAG_LOGI(AceLogTag::ACE_UIEXTENSIONCOMPONENT, "HandleUnfocusedModalUecBackPressed,"
99 " sessionId: %{public}d, isForeground: %{public}d, isLastModal: %{public}d",
100 uiExtension->GetSessionId(), isForeground, isLastModal);
101 if (!isForeground || !isLastModal) {
102 continue;
103 }
104
105 session = uiExtension->GetSessionWrapper();
106 break;
107 }
108 }
109
110 if (session) {
111 return session->NotifyBackPressedSync();
112 }
113
114 return false;
115 }
116
IsLastModalUec(const RefPtr<FrameNode> & frameNode)117 bool UIExtensionManager::IsLastModalUec(const RefPtr<FrameNode>& frameNode)
118 {
119 CHECK_NULL_RETURN(frameNode, false);
120 auto parentNode = frameNode->GetParent();
121 CHECK_NULL_RETURN(parentNode, false);
122 if (parentNode->GetTag() != V2::MODAL_PAGE_TAG) {
123 TAG_LOGW(AceLogTag::ACE_UIEXTENSIONCOMPONENT,
124 "parentNode not modalPage, parentNode tag: %{public}s",
125 parentNode->GetTag().c_str());
126 return false;
127 }
128
129 auto grandpaNode = parentNode->GetParent();
130 if (grandpaNode == nullptr) {
131 TAG_LOGW(AceLogTag::ACE_UIEXTENSIONCOMPONENT, "ModalPage no parent.");
132 return false;
133 }
134
135 auto lastChild = grandpaNode->GetLastChild();
136 if (lastChild == nullptr) {
137 TAG_LOGW(AceLogTag::ACE_UIEXTENSIONCOMPONENT, "LastChild is null.");
138 return false;
139 }
140
141 if (lastChild != parentNode) {
142 TAG_LOGW(AceLogTag::ACE_UIEXTENSIONCOMPONENT, "ModalPage is not the last "
143 "child of rootNode, lastChild tag: %{public}s, parentNode tag: %{public}s",
144 lastChild->GetTag().c_str(), parentNode->GetTag().c_str());
145 return false;
146 }
147
148 return true;
149 }
150
IsWrapExtensionAbilityId(int64_t elementId)151 bool UIExtensionManager::IsWrapExtensionAbilityId(int64_t elementId)
152 {
153 return elementId > UI_EXTENSION_OFFSET_MIN;
154 }
155
SendAccessibilityEventInfo(const Accessibility::AccessibilityEventInfo & eventInfo,int64_t uiExtensionOffset,const RefPtr<PipelineBase> & pipeline)156 bool UIExtensionManager::SendAccessibilityEventInfo(const Accessibility::AccessibilityEventInfo& eventInfo,
157 int64_t uiExtensionOffset, const RefPtr<PipelineBase>& pipeline)
158 {
159 CHECK_NULL_RETURN(pipeline, false);
160 auto instanceId = pipeline->GetInstanceId();
161 auto window = Platform::AceContainer::GetUIWindow(instanceId);
162 CHECK_NULL_RETURN(window, false);
163 OHOS::Rosen::WMError ret = window->TransferAccessibilityEvent(eventInfo, uiExtensionOffset);
164 return ret == OHOS::Rosen::WMError::WM_OK;
165 }
166
UnWrapExtensionAbilityId(int64_t extensionOffset,int64_t elementId)167 std::pair<int64_t, int64_t> UIExtensionManager::UnWrapExtensionAbilityId(int64_t extensionOffset, int64_t elementId)
168 {
169 if (extensionOffset == 0) {
170 return std::pair<int64_t, int64_t>(0, 0);
171 }
172 int64_t index = elementId / extensionOffset;
173 int64_t abilityId = elementId % extensionOffset;
174 return std::pair<int64_t, int64_t>(index, abilityId);
175 }
176
GetFocusUiExtensionNode()177 const RefPtr<FrameNode> UIExtensionManager::GetFocusUiExtensionNode()
178 {
179 auto uiExtensionFocused = uiExtensionFocused_.Upgrade();
180 CHECK_NULL_RETURN(uiExtensionFocused, nullptr);
181 return uiExtensionFocused->GetHost();
182 }
183
ApplyExtensionId()184 int32_t UIExtensionManager::ApplyExtensionId()
185 {
186 return UIExtensionIdUtility::GetInstance().ApplyExtensionId();
187 }
188
RecycleExtensionId(int32_t id)189 void UIExtensionManager::RecycleExtensionId(int32_t id)
190 {
191 UIExtensionIdUtility::GetInstance().RecycleExtensionId(id);
192 }
193
AddAliveUIExtension(int32_t nodeId,const WeakPtr<UIExtensionPattern> & uiExtension)194 void UIExtensionManager::AddAliveUIExtension(int32_t nodeId, const WeakPtr<UIExtensionPattern>& uiExtension)
195 {
196 std::lock_guard<std::mutex> aliveUIExtensionMutex(aliveUIExtensionMutex_);
197 aliveUIExtensions_.try_emplace(nodeId, uiExtension);
198 }
199
AddAliveUIExtension(int32_t nodeId,const WeakPtr<SecurityUIExtensionPattern> & uiExtension)200 void UIExtensionManager::AddAliveUIExtension(
201 int32_t nodeId, const WeakPtr<SecurityUIExtensionPattern>& uiExtension)
202 {
203 aliveSecurityUIExtensions_.try_emplace(nodeId, uiExtension);
204 }
205
TransferOriginAvoidArea(const Rosen::AvoidArea & avoidArea,uint32_t type)206 void UIExtensionManager::TransferOriginAvoidArea(const Rosen::AvoidArea& avoidArea, uint32_t type)
207 {
208 for (const auto& it : aliveUIExtensions_) {
209 auto uiExtension = it.second.Upgrade();
210 if (uiExtension) {
211 uiExtension->DispatchOriginAvoidArea(avoidArea, type);
212 }
213 }
214
215 for (const auto& it : aliveSecurityUIExtensions_) {
216 auto uiExtension = it.second.Upgrade();
217 if (uiExtension) {
218 uiExtension->DispatchOriginAvoidArea(avoidArea, type);
219 }
220 }
221 }
222
RemoveDestroyedUIExtension(int32_t nodeId)223 void UIExtensionManager::RemoveDestroyedUIExtension(int32_t nodeId)
224 {
225 {
226 std::lock_guard<std::mutex> aliveUIExtensionMutex(aliveUIExtensionMutex_);
227 auto it = aliveUIExtensions_.find(nodeId);
228 if (it != aliveUIExtensions_.end()) {
229 aliveUIExtensions_.erase(nodeId);
230 }
231 }
232
233 auto iter = aliveSecurityUIExtensions_.find(nodeId);
234 if (iter != aliveSecurityUIExtensions_.end()) {
235 aliveSecurityUIExtensions_.erase(nodeId);
236 }
237 }
238
NotifyOccupiedAreaChangeInfo(const sptr<Rosen::OccupiedAreaChangeInfo> & info)239 bool UIExtensionManager::NotifyOccupiedAreaChangeInfo(const sptr<Rosen::OccupiedAreaChangeInfo>& info)
240 {
241 int32_t keyboardHeight = static_cast<int32_t>(info->rect_.height_);
242 if (keyboardHeight != 0) {
243 auto sessionWrapper = sessionWrapper_.Upgrade();
244 return sessionWrapper && sessionWrapper->NotifyOccupiedAreaChangeInfo(info, true);
245 }
246 // keyboardHeight is 0, broadcast it.
247 bool ret = false;
248 for (const auto& it : aliveUIExtensions_) {
249 auto uiExtension = it.second.Upgrade();
250 if (uiExtension) {
251 auto session = uiExtension->GetSessionWrapper();
252 if (session && session->IsSessionValid()) {
253 ret |= session->NotifyOccupiedAreaChangeInfo(info);
254 }
255 }
256 }
257 return ret;
258 }
259
NotifySizeChangeReason(WindowSizeChangeReason type,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction)260 void UIExtensionManager::NotifySizeChangeReason(
261 WindowSizeChangeReason type, const std::shared_ptr<Rosen::RSTransaction>& rsTransaction)
262 {
263 for (const auto& it : aliveUIExtensions_) {
264 auto uiExtension = it.second.Upgrade();
265 if (uiExtension) {
266 uiExtension->NotifySizeChangeReason(type, rsTransaction);
267 }
268 }
269
270 for (const auto& it : aliveSecurityUIExtensions_) {
271 auto uiExtension = it.second.Upgrade();
272 if (uiExtension) {
273 uiExtension->NotifySizeChangeReason(type, rsTransaction);
274 }
275 }
276 }
277
IsShowPlaceholder(int32_t nodeId)278 bool UIExtensionManager::IsShowPlaceholder(int32_t nodeId)
279 {
280 auto it = aliveUIExtensions_.find(nodeId);
281 if (it != aliveUIExtensions_.end()) {
282 auto uiExtension = it->second.Upgrade();
283 if (uiExtension) {
284 return uiExtension->IsShowPlaceholder();
285 }
286 }
287 return true;
288 }
289 } // namespace OHOS::Ace::NG
290