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