1 /*
2 * Copyright (c) 2023-2024 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_pattern.h"
17
18 #include <optional>
19
20 #include "core/event/key_event.h"
21 #include "core/event/pointer_event.h"
22 #include "session/host/include/extension_session.h"
23 #include "session/host/include/session.h"
24 #include "ui/rs_surface_node.h"
25
26 #include "adapter/ohos/entrance/ace_container.h"
27 #include "adapter/ohos/entrance/ace_extra_input_data.h"
28 #include "adapter/ohos/entrance/mmi_event_convertor.h"
29 #include "adapter/ohos/osal/want_wrap_ohos.h"
30 #include "base/geometry/offset.h"
31 #include "base/error/error_code.h"
32 #include "base/utils/utils.h"
33 #include "core/common/container.h"
34 #include "core/components_ng/event/event_hub.h"
35 #include "core/components_ng/pattern/pattern.h"
36 #include "core/components_ng/pattern/text_field/text_field_manager.h"
37 #include "core/components_ng/pattern/ui_extension/modal_ui_extension_proxy_impl.h"
38 #include "core/components_ng/pattern/ui_extension/session_wrapper.h"
39 #include "core/components_ng/pattern/ui_extension/session_wrapper_factory.h"
40 #include "core/components_ng/pattern/ui_extension/session_wrapper_impl.h"
41 #include "core/components_ng/pattern/ui_extension/ui_extension_layout_algorithm.h"
42 #include "core/components_ng/pattern/ui_extension/ui_extension_surface_pattern.h"
43 #include "core/components_ng/pattern/ui_extension/ui_extension_proxy.h"
44 #include "core/components_ng/pattern/window_scene/helper/window_scene_helper.h"
45 #include "core/components_ng/pattern/window_scene/scene/window_pattern.h"
46 #include "core/components_ng/render/adapter/rosen_render_context.h"
47 #include "core/components_ng/render/adapter/rosen_window.h"
48 #include "core/event/ace_events.h"
49 #include "core/event/mouse_event.h"
50 #include "core/event/touch_event.h"
51 #include "core/pipeline/pipeline_context.h"
52 #include "core/pipeline_ng/pipeline_context.h"
53
54 namespace OHOS::Ace::NG {
55 namespace {
56 constexpr char ABILITY_KEY_ASYNC[] = "ability.want.params.KeyAsync";
57 constexpr char ABILITY_KEY_IS_MODAL[] = "ability.want.params.IsModal";
58 constexpr char ATOMIC_SERVICE_PREFIX[] = "com.atomicservice.";
59 constexpr char PROHIBIT_NESTING_FAIL_NAME[] = "Prohibit_Nesting_SecurityUIExtensionComponent";
60 constexpr char PROHIBIT_NESTING_FAIL_MESSAGE[] =
61 "Prohibit nesting securityUIExtensionComponent in UIExtensionAbility";
62 constexpr double SHOW_START = 0.0;
63 constexpr double SHOW_FULL = 1.0;
64
StartWith(const std::string & source,const std::string & prefix)65 bool StartWith(const std::string &source, const std::string &prefix)
66 {
67 if (source.empty() || prefix.empty()) {
68 return false;
69 }
70
71 return source.find(prefix) == 0;
72 }
73
SetInputEventExtraProperty(std::shared_ptr<MMI::PointerEvent> & newInputEvent,const std::shared_ptr<MMI::PointerEvent> & oldInputEvent)74 void SetInputEventExtraProperty(std::shared_ptr<MMI::PointerEvent>& newInputEvent,
75 const std::shared_ptr<MMI::PointerEvent>& oldInputEvent)
76 {
77 if (!newInputEvent || !oldInputEvent) {
78 TAG_LOGW(AceLogTag::ACE_UIEXTENSIONCOMPONENT,
79 "The newInputEvent or oldInputEvent is null.");
80 return;
81 }
82
83 std::shared_ptr<const uint8_t[]> raw;
84 uint32_t length = 0;
85 oldInputEvent->GetExtraData(raw, length);
86 if (length == 0 || !raw) {
87 TAG_LOGW(AceLogTag::ACE_UIEXTENSIONCOMPONENT,
88 "The oldInputEvent no extra data.");
89 } else {
90 newInputEvent->SetExtraData(raw, length);
91 }
92
93 newInputEvent->SetSensorInputTime(oldInputEvent->GetSensorInputTime());
94 }
95
SetPointerEventExtraProperty(std::shared_ptr<MMI::PointerEvent> & newPointerEvent,const std::shared_ptr<MMI::PointerEvent> & pointerEvent)96 void SetPointerEventExtraProperty(std::shared_ptr<MMI::PointerEvent>& newPointerEvent,
97 const std::shared_ptr<MMI::PointerEvent>& pointerEvent)
98 {
99 if (!newPointerEvent) {
100 TAG_LOGW(AceLogTag::ACE_UIEXTENSIONCOMPONENT, "The New PointerEvent is null.");
101 return;
102 }
103 CHECK_NULL_VOID(pointerEvent);
104 #ifdef OHOS_BUILD_ENABLE_SECURITY_COMPONENT
105 newPointerEvent->SetEnhanceData(pointerEvent->GetEnhanceData());
106 #endif // OHOS_BUILD_ENABLE_SECURITY_COMPONENT
107 #ifdef OHOS_BUILD_ENABLE_ANCO
108 newPointerEvent->SetAncoDeal(pointerEvent->GetAncoDeal());
109 #endif // OHOS_BUILD_ENABLE_ANCO
110 newPointerEvent->SetHandlerEventType(pointerEvent->GetHandlerEventType());
111 SetInputEventExtraProperty(newPointerEvent, pointerEvent);
112 }
113
114 class UIExtensionAccessibilityChildTreeCallback : public AccessibilityChildTreeCallback {
115 public:
UIExtensionAccessibilityChildTreeCallback(const WeakPtr<UIExtensionPattern> & weakPattern,int64_t accessibilityId)116 UIExtensionAccessibilityChildTreeCallback(const WeakPtr<UIExtensionPattern> &weakPattern, int64_t accessibilityId)
117 : AccessibilityChildTreeCallback(accessibilityId), weakPattern_(weakPattern)
118 {}
119
120 ~UIExtensionAccessibilityChildTreeCallback() override = default;
121
OnRegister(uint32_t windowId,int32_t treeId)122 bool OnRegister(uint32_t windowId, int32_t treeId) override
123 {
124 auto pattern = weakPattern_.Upgrade();
125 if (pattern == nullptr) {
126 return false;
127 }
128 if (isReg_) {
129 return true;
130 }
131 pattern->OnAccessibilityChildTreeRegister(windowId, treeId, GetAccessibilityId());
132 isReg_ = true;
133 return true;
134 }
135
OnDeregister()136 bool OnDeregister() override
137 {
138 auto pattern = weakPattern_.Upgrade();
139 if (pattern == nullptr) {
140 return false;
141 }
142 if (!isReg_) {
143 return true;
144 }
145 pattern->OnAccessibilityChildTreeDeregister();
146 isReg_ = false;
147 return true;
148 }
149
OnSetChildTree(int32_t childWindowId,int32_t childTreeId)150 bool OnSetChildTree(int32_t childWindowId, int32_t childTreeId) override
151 {
152 auto pattern = weakPattern_.Upgrade();
153 if (pattern == nullptr) {
154 return false;
155 }
156 pattern->OnSetAccessibilityChildTree(childWindowId, childTreeId);
157 return true;
158 }
159
OnDumpChildInfo(const std::vector<std::string> & params,std::vector<std::string> & info)160 bool OnDumpChildInfo(const std::vector<std::string>& params, std::vector<std::string>& info) override
161 {
162 auto pattern = weakPattern_.Upgrade();
163 if (pattern == nullptr) {
164 return false;
165 }
166 pattern->OnAccessibilityDumpChildInfo(params, info);
167 return true;
168 }
169
OnClearRegisterFlag()170 void OnClearRegisterFlag() override
171 {
172 auto pattern = weakPattern_.Upgrade();
173 if (pattern == nullptr) {
174 return;
175 }
176 isReg_ = false;
177 }
178
179 private:
180 bool isReg_ = false;
181 WeakPtr<UIExtensionPattern> weakPattern_;
182 };
183 }
UIExtensionPattern(bool isTransferringCaller,bool isModal,bool isAsyncModalBinding,SessionType sessionType)184 UIExtensionPattern::UIExtensionPattern(
185 bool isTransferringCaller, bool isModal, bool isAsyncModalBinding, SessionType sessionType)
186 : isTransferringCaller_(isTransferringCaller), isModal_(isModal),
187 isAsyncModalBinding_(isAsyncModalBinding), sessionType_(sessionType)
188 {
189 uiExtensionId_ = UIExtensionIdUtility::GetInstance().ApplyExtensionId();
190 sessionWrapper_ = SessionWrapperFactory::CreateSessionWrapper(
191 sessionType, AceType::WeakClaim(this), instanceId_, isTransferringCaller_);
192 accessibilitySessionAdapter_ =
193 AceType::MakeRefPtr<AccessibilitySessionAdapterUIExtension>(sessionWrapper_);
194 UIEXT_LOGI("The %{public}smodal UIExtension is created.", isModal_ ? "" : "non");
195 }
196
~UIExtensionPattern()197 UIExtensionPattern::~UIExtensionPattern()
198 {
199 UIEXT_LOGI("The %{public}smodal UIExtension is destroyed.", isModal_ ? "" : "non");
200 if (isModal_) {
201 LogoutModalUIExtension();
202 }
203 NotifyDestroy();
204 FireModalOnDestroy();
205 UIExtensionIdUtility::GetInstance().RecycleExtensionId(uiExtensionId_);
206 auto pipeline = PipelineContext::GetCurrentContext();
207 CHECK_NULL_VOID(pipeline);
208 auto uiExtensionManager = pipeline->GetUIExtensionManager();
209 CHECK_NULL_VOID(uiExtensionManager);
210 uiExtensionManager->RemoveDestroyedUIExtension(GetNodeId());
211
212 if (accessibilityChildTreeCallback_ == nullptr) {
213 return;
214 }
215
216 auto instanceId = GetInstanceIdFromHost();
217 ContainerScope scope(instanceId);
218 auto ngPipeline = NG::PipelineContext::GetCurrentContext();
219 CHECK_NULL_VOID(ngPipeline);
220 auto frontend = ngPipeline->GetFrontend();
221 CHECK_NULL_VOID(frontend);
222 auto accessibilityManager = frontend->GetAccessibilityManager();
223 CHECK_NULL_VOID(accessibilityManager);
224 accessibilityManager->DeregisterAccessibilityChildTreeCallback(
225 accessibilityChildTreeCallback_->GetAccessibilityId());
226 accessibilityChildTreeCallback_ = nullptr;
227 }
228
LogoutModalUIExtension()229 void UIExtensionPattern::LogoutModalUIExtension()
230 {
231 auto sessionId = GetSessionId();
232 UIEXT_LOGI("LogoutModalUIExtension sessionId %{public}d.", sessionId);
233 auto pipeline = PipelineContext::GetCurrentContext();
234 CHECK_NULL_VOID(pipeline);
235 auto overlay = pipeline->GetOverlayManager();
236 CHECK_NULL_VOID(overlay);
237 overlay->ResetRootNode(-(sessionId));
238 }
239
CreateLayoutAlgorithm()240 RefPtr<LayoutAlgorithm> UIExtensionPattern::CreateLayoutAlgorithm()
241 {
242 return MakeRefPtr<UIExtensionLayoutAlgorithm>();
243 }
244
GetFocusPattern() const245 FocusPattern UIExtensionPattern::GetFocusPattern() const
246 {
247 return { FocusType::NODE, true, FocusStyleType::FORCE_NONE };
248 }
249
GetAccessibilitySessionAdapter()250 RefPtr<AccessibilitySessionAdapter> UIExtensionPattern::GetAccessibilitySessionAdapter()
251 {
252 return accessibilitySessionAdapter_;
253 }
254
UpdateWant(const RefPtr<OHOS::Ace::WantWrap> & wantWrap)255 void UIExtensionPattern::UpdateWant(const RefPtr<OHOS::Ace::WantWrap>& wantWrap)
256 {
257 if (!wantWrap) {
258 UIEXT_LOGW("wantWrap is nullptr");
259 return;
260 }
261 auto wantWrapOhos = AceType::DynamicCast<WantWrapOhos>(wantWrap);
262 if (!wantWrapOhos) {
263 UIEXT_LOGW("DynamicCast failed, wantWrapOhos is nullptr");
264 return;
265 }
266 auto want = wantWrapOhos->GetWant();
267 UpdateWant(want);
268 }
269
MountPlaceholderNode()270 void UIExtensionPattern::MountPlaceholderNode()
271 {
272 if (!isShowPlaceholder_ && placeholderNode_) {
273 auto host = GetHost();
274 CHECK_NULL_VOID(host);
275 host->AddChild(placeholderNode_, 0);
276 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
277 isShowPlaceholder_ = true;
278 }
279 }
280
RemovePlaceholderNode()281 void UIExtensionPattern::RemovePlaceholderNode()
282 {
283 if (isShowPlaceholder_) {
284 auto host = GetHost();
285 CHECK_NULL_VOID(host);
286 host->RemoveChildAtIndex(0);
287 isShowPlaceholder_ = false;
288 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
289 }
290 }
291
CheckConstraint()292 bool UIExtensionPattern::CheckConstraint()
293 {
294 auto container = Platform::AceContainer::GetContainer(instanceId_);
295 CHECK_NULL_RETURN(container, false);
296 if (container->GetUIContentType() == UIContentType::SECURITY_UI_EXTENSION) {
297 UIEXT_LOGE("Not allowed nesting in SECURITY_UI_EXTENSION.");
298 FireOnErrorCallback(ERROR_CODE_UIEXTENSION_FORBID_CASCADE,
299 PROHIBIT_NESTING_FAIL_NAME, PROHIBIT_NESTING_FAIL_MESSAGE);
300 return false;
301 }
302
303 return true;
304 }
305
UpdateWant(const AAFwk::Want & want)306 void UIExtensionPattern::UpdateWant(const AAFwk::Want& want)
307 {
308 if (!CheckConstraint()) {
309 UIEXT_LOGE("Check constraint failed.");
310 return;
311 }
312
313 CHECK_NULL_VOID(sessionWrapper_);
314 UIEXT_LOGI("The current state is '%{public}s' when UpdateWant, needCheck: '%{public}d'.",
315 ToString(state_), needCheckWindowSceneId_);
316 bool isBackground = state_ == AbilityState::BACKGROUND;
317 // Prohibit rebuilding the session unless the Want is updated.
318 if (sessionWrapper_->IsSessionValid()) {
319 if (sessionWrapper_->GetWant()->IsEquals(want)) {
320 return;
321 }
322 UIEXT_LOGI("The old want is %{private}s.", sessionWrapper_->GetWant()->ToString().c_str());
323 auto host = GetHost();
324 CHECK_NULL_VOID(host);
325 host->RemoveChildAtIndex(0);
326 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
327 NotifyDestroy();
328 // reset callback, in order to register childtree call back again when onConnect to new ability
329 ResetAccessibilityChildTreeCallback();
330 }
331
332 isKeyAsync_ = want.GetBoolParam(ABILITY_KEY_ASYNC, false);
333 UIExtensionUsage uIExtensionUsage = GetUIExtensionUsage(want);
334 usage_ = uIExtensionUsage;
335 UIEXT_LOGI("The ability KeyAsync %{public}d, uIExtensionUsage: %{public}u.",
336 isKeyAsync_, uIExtensionUsage);
337 MountPlaceholderNode();
338 SessionConfig config;
339 config.isAsyncModalBinding = isAsyncModalBinding_;
340 config.uiExtensionUsage = uIExtensionUsage;
341 sessionWrapper_->CreateSession(want, config);
342 if (isBackground) {
343 UIEXT_LOGW("Unable to StartUiextensionAbility while in the background.");
344 return;
345 }
346 auto container = Platform::AceContainer::GetContainer(instanceId_);
347 CHECK_NULL_VOID(container);
348 if (needCheckWindowSceneId_ && container->IsScenceBoardWindow() &&
349 uIExtensionUsage != UIExtensionUsage::MODAL && !hasMountToParent_) {
350 needReNotifyForeground_ = true;
351 UIEXT_LOGI("Should NotifyForeground after MountToParent.");
352 return;
353 }
354 NotifyForeground();
355 }
356
IsModalUec()357 bool UIExtensionPattern::IsModalUec()
358 {
359 return usage_ == UIExtensionUsage::MODAL;
360 }
361
IsForeground()362 bool UIExtensionPattern::IsForeground()
363 {
364 return state_ == AbilityState::FOREGROUND;
365 }
366
GetUIExtensionUsage(const AAFwk::Want & want)367 UIExtensionUsage UIExtensionPattern::GetUIExtensionUsage(const AAFwk::Want& want)
368 {
369 if (sessionType_ == SessionType::EMBEDDED_UI_EXTENSION) {
370 return UIExtensionUsage::EMBEDDED;
371 }
372
373 if (isModal_) {
374 return UIExtensionUsage::MODAL;
375 }
376
377 bool wantParamModal = want.GetBoolParam(ABILITY_KEY_IS_MODAL, false);
378 auto bundleName = want.GetElement().GetBundleName();
379 bool startWithAtomicService = StartWith(bundleName, ATOMIC_SERVICE_PREFIX);
380 if (wantParamModal && startWithAtomicService) {
381 return UIExtensionUsage::MODAL;
382 }
383
384 return UIExtensionUsage::EMBEDDED;
385 }
386
OnConnect()387 void UIExtensionPattern::OnConnect()
388 {
389 CHECK_RUN_ON(UI);
390 CHECK_NULL_VOID(sessionWrapper_);
391 UIEXT_LOGI("The session is connected and the current state is '%{public}s'.", ToString(state_));
392 ContainerScope scope(instanceId_);
393 contentNode_ = FrameNode::CreateFrameNode(V2::UI_EXTENSION_SURFACE_TAG,
394 ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<UIExtensionSurfacePattern>());
395 contentNode_->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_PARENT);
396 contentNode_->SetHitTestMode(HitTestMode::HTMNONE);
397 auto host = GetHost();
398 CHECK_NULL_VOID(host);
399 auto&& opts = host->GetLayoutProperty()->GetSafeAreaExpandOpts();
400 if (opts && opts->Expansive()) {
401 contentNode_->GetLayoutProperty()->UpdateSafeAreaExpandOpts(*opts);
402 contentNode_->MarkModifyDone();
403 }
404 auto context = AceType::DynamicCast<NG::RosenRenderContext>(contentNode_->GetRenderContext());
405 CHECK_NULL_VOID(context);
406 auto surfaceNode = sessionWrapper_->GetSurfaceNode();
407 if (!surfaceNode) {
408 UIEXT_LOGE("Get surfaceNode from session is null.");
409 return;
410 }
411 context->SetRSNode(surfaceNode);
412 RemovePlaceholderNode();
413 host->AddChild(contentNode_, 0);
414 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
415 surfaceNode->CreateNodeInRenderThread();
416 surfaceNode->SetForeground(usage_ == UIExtensionUsage::MODAL);
417 FireOnRemoteReadyCallback();
418 auto focusHub = host->GetFocusHub();
419 if ((usage_ == UIExtensionUsage::MODAL) && focusHub) {
420 focusHub->RequestFocusImmediately();
421 }
422 bool isFocused = focusHub && focusHub->IsCurrentFocus();
423 RegisterVisibleAreaChange();
424 DispatchFocusState(isFocused);
425 DispatchFollowHostDensity(GetDensityDpi());
426 auto pipeline = host->GetContextRefPtr();
427 CHECK_NULL_VOID(pipeline);
428 auto uiExtensionManager = pipeline->GetUIExtensionManager();
429 uiExtensionManager->AddAliveUIExtension(host->GetId(), WeakClaim(this));
430 if (isFocused || (usage_ == UIExtensionUsage::MODAL)) {
431 uiExtensionManager->RegisterUIExtensionInFocus(WeakClaim(this), sessionWrapper_);
432 }
433 InitializeAccessibility();
434 ReDispatchDisplayArea();
435 }
436
OnAccessibilityEvent(const Accessibility::AccessibilityEventInfo & info,int64_t uiExtensionOffset)437 void UIExtensionPattern::OnAccessibilityEvent(
438 const Accessibility::AccessibilityEventInfo& info, int64_t uiExtensionOffset)
439 {
440 UIEXT_LOGI("The accessibility event is reported and the current state is '%{public}s'.", ToString(state_));
441 ContainerScope scope(instanceId_);
442 auto ngPipeline = NG::PipelineContext::GetCurrentContext();
443 CHECK_NULL_VOID(ngPipeline);
444 uiExtensionOffset = uiExtensionId_ * NG::UI_EXTENSION_OFFSET_MAX + uiExtensionOffset;
445 auto frontend = ngPipeline->GetFrontend();
446 CHECK_NULL_VOID(frontend);
447 auto accessibilityManager = frontend->GetAccessibilityManager();
448 CHECK_NULL_VOID(accessibilityManager);
449 accessibilityManager->SendExtensionAccessibilityEvent(info, uiExtensionOffset);
450 }
451
OnDisconnect(bool isAbnormal)452 void UIExtensionPattern::OnDisconnect(bool isAbnormal)
453 {
454 CHECK_RUN_ON(UI);
455 UIEXT_LOGI("The session is disconnected and the current state is '%{public}s'.", ToString(state_));
456 auto host = GetHost();
457 CHECK_NULL_VOID(host);
458 host->RemoveChildAtIndex(0);
459 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
460 }
461
OnSyncGeometryNode(const DirtySwapConfig & config)462 void UIExtensionPattern::OnSyncGeometryNode(const DirtySwapConfig& config)
463 {
464 if (needReNotifyForeground_) {
465 needReNotifyForeground_ = false;
466 UIEXT_LOGI("NotifyForeground onSyncGeometryNode first.");
467 NotifyForeground();
468 needReDispatchDisplayArea_ = true;
469 }
470 DispatchDisplayArea(true);
471 }
472
ReDispatchDisplayArea()473 void UIExtensionPattern::ReDispatchDisplayArea()
474 {
475 if (needReDispatchDisplayArea_) {
476 UIEXT_LOGI("ReDispatchDisplayArea.");
477 DispatchDisplayArea(true);
478 needReDispatchDisplayArea_ = false;
479 }
480 }
481
OnWindowShow()482 void UIExtensionPattern::OnWindowShow()
483 {
484 UIEXT_LOGI("The window is being shown and the component is %{public}s.", isVisible_ ? "visible" : "invisible");
485 if (isVisible_) {
486 NotifyForeground();
487 }
488 }
489
OnWindowHide()490 void UIExtensionPattern::OnWindowHide()
491 {
492 UIEXT_LOGI("The window is being hidden and the component is %{public}s.", isVisible_ ? "visible" : "invisible");
493 if (isVisible_) {
494 NotifyBackground();
495 }
496 }
497
NotifySizeChangeReason(WindowSizeChangeReason type,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction)498 void UIExtensionPattern::NotifySizeChangeReason(
499 WindowSizeChangeReason type, const std::shared_ptr<Rosen::RSTransaction>& rsTransaction)
500 {
501 CHECK_NULL_VOID(sessionWrapper_);
502 sessionWrapper_->NotifySizeChangeReason(type, rsTransaction);
503 }
504
NotifyForeground()505 void UIExtensionPattern::NotifyForeground()
506 {
507 if (sessionWrapper_ && sessionWrapper_->IsSessionValid() && state_ != AbilityState::FOREGROUND) {
508 UIEXT_LOGI("The state is changing from '%{public}s' to 'FOREGROUND'.", ToString(state_));
509 state_ = AbilityState::FOREGROUND;
510 sessionWrapper_->NotifyForeground();
511 }
512 }
513
NotifyBackground()514 void UIExtensionPattern::NotifyBackground()
515 {
516 if (sessionWrapper_ && sessionWrapper_->IsSessionValid() && state_ == AbilityState::FOREGROUND) {
517 UIEXT_LOGI("The state is changing from '%{public}s' to 'BACKGROUND'.", ToString(state_));
518 state_ = AbilityState::BACKGROUND;
519 sessionWrapper_->NotifyBackground();
520 }
521 }
522
NotifyDestroy()523 void UIExtensionPattern::NotifyDestroy()
524 {
525 if (sessionWrapper_ && sessionWrapper_->IsSessionValid() && state_ != AbilityState::DESTRUCTION &&
526 state_ != AbilityState::NONE) {
527 UIEXT_LOGI("The state is changing from '%{public}s' to 'DESTRUCTION'.", ToString(state_));
528 state_ = AbilityState::DESTRUCTION;
529 sessionWrapper_->NotifyDestroy();
530 sessionWrapper_->DestroySession();
531 }
532 }
533
OnAttachToFrameNode()534 void UIExtensionPattern::OnAttachToFrameNode()
535 {
536 ContainerScope scope(instanceId_);
537 auto pipeline = PipelineContext::GetCurrentContext();
538 CHECK_NULL_VOID(pipeline);
539 auto host = GetHost();
540 CHECK_NULL_VOID(host);
541 auto eventHub = host->GetEventHub<EventHub>();
542 CHECK_NULL_VOID(eventHub);
543 OnAreaChangedFunc onAreaChangedFunc = [weak = WeakClaim(this)](
544 const RectF& oldRect,
545 const OffsetF& oldOrigin,
546 const RectF& rect,
547 const OffsetF& origin) {
548 auto pattern = weak.Upgrade();
549 CHECK_NULL_VOID(pattern);
550 pattern->DispatchDisplayArea();
551 };
552 eventHub->AddInnerOnAreaChangedCallback(host->GetId(), std::move(onAreaChangedFunc));
553 pipeline->AddOnAreaChangeNode(host->GetId());
554 callbackId_ = pipeline->RegisterSurfacePositionChangedCallback([weak = WeakClaim(this)](int32_t, int32_t) {
555 auto pattern = weak.Upgrade();
556 if (pattern) {
557 pattern->DispatchDisplayArea(true);
558 }
559 });
560 UIEXT_LOGI("OnAttachToFrameNode");
561 }
562
OnDetachFromFrameNode(FrameNode * frameNode)563 void UIExtensionPattern::OnDetachFromFrameNode(FrameNode* frameNode)
564 {
565 auto id = frameNode->GetId();
566 ContainerScope scope(instanceId_);
567 auto pipeline = PipelineContext::GetCurrentContext();
568 CHECK_NULL_VOID(pipeline);
569 pipeline->RemoveOnAreaChangeNode(id);
570 pipeline->RemoveWindowStateChangedCallback(id);
571 pipeline->UnregisterSurfacePositionChangedCallback(callbackId_);
572 }
573
OnModifyDone()574 void UIExtensionPattern::OnModifyDone()
575 {
576 Pattern::OnModifyDone();
577 auto host = GetHost();
578 CHECK_NULL_VOID(host);
579 auto hub = host->GetEventHub<EventHub>();
580 CHECK_NULL_VOID(hub);
581 auto gestureHub = hub->GetOrCreateGestureEventHub();
582 CHECK_NULL_VOID(gestureHub);
583 InitTouchEvent(gestureHub);
584 auto inputHub = hub->GetOrCreateInputEventHub();
585 CHECK_NULL_VOID(inputHub);
586 InitMouseEvent(inputHub);
587 InitHoverEvent(inputHub);
588 auto focusHub = host->GetFocusHub();
589 CHECK_NULL_VOID(focusHub);
590 InitKeyEvent(focusHub);
591 }
592
InitKeyEvent(const RefPtr<FocusHub> & focusHub)593 void UIExtensionPattern::InitKeyEvent(const RefPtr<FocusHub>& focusHub)
594 {
595 focusHub->SetOnFocusInternal([weak = WeakClaim(this)]() {
596 auto pattern = weak.Upgrade();
597 if (pattern) {
598 pattern->HandleFocusEvent();
599 }
600 });
601
602 focusHub->SetOnBlurInternal([weak = WeakClaim(this)]() {
603 auto pattern = weak.Upgrade();
604 if (pattern) {
605 pattern->HandleBlurEvent();
606 }
607 });
608
609 focusHub->SetOnClearFocusStateInternal([weak = WeakClaim(this)]() {
610 auto pattern = weak.Upgrade();
611 if (pattern) {
612 pattern->DispatchFocusActiveEvent(false);
613 }
614 });
615 focusHub->SetOnPaintFocusStateInternal([weak = WeakClaim(this)]() -> bool {
616 auto pattern = weak.Upgrade();
617 if (pattern) {
618 pattern->DispatchFocusActiveEvent(true);
619 return true;
620 }
621 return false;
622 });
623
624 focusHub->SetOnKeyEventInternal([wp = WeakClaim(this)](const KeyEvent& event) -> bool {
625 auto pattern = wp.Upgrade();
626 if (pattern) {
627 return pattern->HandleKeyEvent(event);
628 }
629 return false;
630 });
631 }
632
InitTouchEvent(const RefPtr<GestureEventHub> & gestureHub)633 void UIExtensionPattern::InitTouchEvent(const RefPtr<GestureEventHub>& gestureHub)
634 {
635 if (touchEvent_) {
636 return;
637 }
638 auto callback = [weak = WeakClaim(this)](const TouchEventInfo& info) {
639 auto pattern = weak.Upgrade();
640 if (pattern) {
641 pattern->HandleTouchEvent(info);
642 }
643 };
644 if (touchEvent_) {
645 gestureHub->RemoveTouchEvent(touchEvent_);
646 }
647 touchEvent_ = MakeRefPtr<TouchEventImpl>(std::move(callback));
648 gestureHub->AddTouchEvent(touchEvent_);
649 }
650
InitMouseEvent(const RefPtr<InputEventHub> & inputHub)651 void UIExtensionPattern::InitMouseEvent(const RefPtr<InputEventHub>& inputHub)
652 {
653 if (mouseEvent_) {
654 return;
655 }
656 auto callback = [weak = WeakClaim(this)](MouseInfo& info) {
657 auto pattern = weak.Upgrade();
658 if (pattern) {
659 pattern->HandleMouseEvent(info);
660 }
661 };
662 if (mouseEvent_) {
663 inputHub->RemoveOnMouseEvent(mouseEvent_);
664 }
665 mouseEvent_ = MakeRefPtr<InputEvent>(std::move(callback));
666 inputHub->AddOnMouseEvent(mouseEvent_);
667 }
668
InitHoverEvent(const RefPtr<InputEventHub> & inputHub)669 void UIExtensionPattern::InitHoverEvent(const RefPtr<InputEventHub>& inputHub)
670 {
671 if (hoverEvent_) {
672 return;
673 }
674 auto callback = [weak = WeakClaim(this)](bool isHover) {
675 auto pattern = weak.Upgrade();
676 if (pattern) {
677 pattern->HandleHoverEvent(isHover);
678 }
679 };
680 if (hoverEvent_) {
681 inputHub->RemoveOnHoverEvent(hoverEvent_);
682 }
683 hoverEvent_ = MakeRefPtr<InputEvent>(std::move(callback));
684 inputHub->AddOnHoverEvent(hoverEvent_);
685 }
686
HandleKeyEvent(const KeyEvent & event)687 bool UIExtensionPattern::HandleKeyEvent(const KeyEvent& event)
688 {
689 return DispatchKeyEventSync(event);
690 }
691
HandleFocusEvent()692 void UIExtensionPattern::HandleFocusEvent()
693 {
694 auto pipeline = PipelineContext::GetCurrentContext();
695 CHECK_NULL_VOID(pipeline);
696 if (canFocusSendToUIExtension_) {
697 if (pipeline->GetIsFocusActive()) {
698 DispatchFocusActiveEvent(true);
699 }
700
701 DispatchFocusState(true);
702 needReSendFocusToUIExtension_ = false;
703 } else {
704 needReSendFocusToUIExtension_ = true;
705 }
706
707 canFocusSendToUIExtension_ = true;
708 auto uiExtensionManager = pipeline->GetUIExtensionManager();
709 uiExtensionManager->RegisterUIExtensionInFocus(WeakClaim(this), sessionWrapper_);
710 }
711
HandleBlurEvent()712 void UIExtensionPattern::HandleBlurEvent()
713 {
714 DispatchFocusActiveEvent(false);
715 DispatchFocusState(false);
716 auto pipeline = PipelineContext::GetCurrentContext();
717 CHECK_NULL_VOID(pipeline);
718 auto uiExtensionManager = pipeline->GetUIExtensionManager();
719 uiExtensionManager->RegisterUIExtensionInFocus(nullptr, nullptr);
720 }
721
HandleTouchEvent(const TouchEventInfo & info)722 void UIExtensionPattern::HandleTouchEvent(const TouchEventInfo& info)
723 {
724 if (info.GetSourceDevice() != SourceType::TOUCH) {
725 UIEXT_LOGE("The source type is not TOUCH.");
726 return;
727 }
728 const auto pointerEvent = info.GetPointerEvent();
729 if (!pointerEvent) {
730 UIEXT_LOGE("The pointerEvent is empty.");
731 return;
732 }
733 auto host = GetHost();
734 CHECK_NULL_VOID(host);
735 auto pipeline = PipelineBase::GetCurrentContext();
736 CHECK_NULL_VOID(pipeline);
737 AceExtraInputData::InsertInterpolatePoints(info);
738 std::shared_ptr<MMI::PointerEvent> newPointerEvent = std::make_shared<MMI::PointerEvent>(*pointerEvent);
739 SetPointerEventExtraProperty(newPointerEvent, pointerEvent);
740 Platform::CalculatePointerEvent(newPointerEvent, host);
741 auto focusHub = host->GetFocusHub();
742 CHECK_NULL_VOID(focusHub);
743 bool ret = true;
744 if (pipeline->IsWindowFocused() && !focusHub->IsCurrentFocus()) {
745 canFocusSendToUIExtension_ = false;
746 ret = focusHub->RequestFocusImmediately();
747 if (!ret) {
748 canFocusSendToUIExtension_ = true;
749 UIEXT_LOGW("RequestFocusImmediately failed when HandleTouchEvent.");
750 }
751 }
752 DispatchPointerEvent(newPointerEvent);
753 if (pipeline->IsWindowFocused() && needReSendFocusToUIExtension_ &&
754 newPointerEvent->GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_UP) {
755 HandleFocusEvent();
756 needReSendFocusToUIExtension_ = false;
757 }
758 }
759
HandleMouseEvent(const MouseInfo & info)760 void UIExtensionPattern::HandleMouseEvent(const MouseInfo& info)
761 {
762 if (info.GetSourceDevice() != SourceType::MOUSE) {
763 return;
764 }
765 if (info.GetPullAction() == MouseAction::PULL_MOVE || info.GetPullAction() == MouseAction::PULL_UP) {
766 return;
767 }
768 const auto pointerEvent = info.GetPointerEvent();
769 CHECK_NULL_VOID(pointerEvent);
770 lastPointerEvent_ = pointerEvent;
771 auto host = GetHost();
772 CHECK_NULL_VOID(host);
773 Platform::CalculatePointerEvent(pointerEvent, host);
774 if (info.GetAction() == MouseAction::PRESS) {
775 auto hub = host->GetFocusHub();
776 CHECK_NULL_VOID(hub);
777 hub->RequestFocusImmediately();
778 }
779 DispatchPointerEvent(pointerEvent);
780 }
781
HandleHoverEvent(bool isHover)782 void UIExtensionPattern::HandleHoverEvent(bool isHover)
783 {
784 if (isHover) {
785 return;
786 }
787 CHECK_NULL_VOID(lastPointerEvent_);
788 lastPointerEvent_->SetPointerAction(MMI::PointerEvent::POINTER_ACTION_LEAVE_WINDOW);
789 DispatchPointerEvent(lastPointerEvent_);
790 }
791
DispatchKeyEvent(const KeyEvent & event)792 void UIExtensionPattern::DispatchKeyEvent(const KeyEvent& event)
793 {
794 CHECK_NULL_VOID(event.rawKeyEvent);
795 CHECK_NULL_VOID(sessionWrapper_);
796 sessionWrapper_->NotifyKeyEventAsync(event.rawKeyEvent);
797 }
798
DispatchKeyEventSync(const KeyEvent & event)799 bool UIExtensionPattern::DispatchKeyEventSync(const KeyEvent& event)
800 {
801 CHECK_NULL_RETURN(sessionWrapper_, false);
802 if (isKeyAsync_) {
803 sessionWrapper_->NotifyKeyEventAsync(event.rawKeyEvent, false);
804 return true;
805 }
806
807 return sessionWrapper_->NotifyKeyEventSync(event.rawKeyEvent, event.isPreIme);
808 }
809
DispatchFocusActiveEvent(bool isFocusActive)810 void UIExtensionPattern::DispatchFocusActiveEvent(bool isFocusActive)
811 {
812 CHECK_NULL_VOID(sessionWrapper_);
813 sessionWrapper_->NotifyFocusEventAsync(isFocusActive);
814 }
815
DispatchFocusState(bool focusState)816 void UIExtensionPattern::DispatchFocusState(bool focusState)
817 {
818 CHECK_NULL_VOID(sessionWrapper_);
819 sessionWrapper_->NotifyFocusStateAsync(focusState);
820 }
821
DispatchPointerEvent(const std::shared_ptr<MMI::PointerEvent> & pointerEvent)822 void UIExtensionPattern::DispatchPointerEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent)
823 {
824 if (!pointerEvent) {
825 UIEXT_LOGE("DispatchPointerEvent pointerEvent is null.");
826 return;
827 }
828 if (!sessionWrapper_) {
829 UIEXT_LOGE("DispatchPointerEvent sessionWrapper is null.");
830 return;
831 }
832 sessionWrapper_->NotifyPointerEventAsync(pointerEvent);
833 }
834
DispatchDisplayArea(bool isForce)835 void UIExtensionPattern::DispatchDisplayArea(bool isForce)
836 {
837 CHECK_NULL_VOID(sessionWrapper_);
838 auto host = GetHost();
839 CHECK_NULL_VOID(host);
840 auto [displayOffset, err] = host->GetPaintRectGlobalOffsetWithTranslate();
841 auto geometryNode = host->GetGeometryNode();
842 CHECK_NULL_VOID(geometryNode);
843 auto renderContext = host->GetRenderContext();
844 CHECK_NULL_VOID(renderContext);
845 auto displaySize = renderContext->GetPaintRectWithoutTransform().GetSize();
846 auto displayArea = RectF(displayOffset, displaySize);
847 if (displayArea_ != displayArea || isForce) {
848 displayArea_ = displayArea;
849 sessionWrapper_->NotifyDisplayArea(displayArea_);
850 }
851 }
852
HandleDragEvent(const PointerEvent & info)853 void UIExtensionPattern::HandleDragEvent(const PointerEvent& info)
854 {
855 auto pointerEvent = info.rawPointerEvent;
856 CHECK_NULL_VOID(pointerEvent);
857 auto host = GetHost();
858 CHECK_NULL_VOID(host);
859 auto pipeline = PipelineBase::GetCurrentContext();
860 CHECK_NULL_VOID(pipeline);
861 Platform::CalculatePointerEvent(pointerEvent, host, true);
862 Platform::UpdatePointerAction(pointerEvent, info.action);
863 DispatchPointerEvent(pointerEvent);
864 }
865
SetOnRemoteReadyCallback(const std::function<void (const RefPtr<UIExtensionProxy> &)> && callback)866 void UIExtensionPattern::SetOnRemoteReadyCallback(const std::function<void(const RefPtr<UIExtensionProxy>&)>&& callback)
867 {
868 onRemoteReadyCallback_ = std::move(callback);
869 }
870
SetModalOnRemoteReadyCallback(const std::function<void (const std::shared_ptr<ModalUIExtensionProxy> &)> && callback)871 void UIExtensionPattern::SetModalOnRemoteReadyCallback(
872 const std::function<void(const std::shared_ptr<ModalUIExtensionProxy>&)>&& callback)
873 {
874 onModalRemoteReadyCallback_ = std::move(callback);
875 }
876
FireOnRemoteReadyCallback()877 void UIExtensionPattern::FireOnRemoteReadyCallback()
878 {
879 UIEXT_LOGI("OnRemoteReady the current state is '%{public}s'.", ToString(state_));
880 ContainerScope scope(instanceId_);
881 // These two callbacks will be unified in the future.
882 if (onRemoteReadyCallback_) {
883 onRemoteReadyCallback_(MakeRefPtr<UIExtensionProxy>(sessionWrapper_, Claim(this)));
884 }
885 if (onModalRemoteReadyCallback_) {
886 onModalRemoteReadyCallback_(std::make_shared<ModalUIExtensionProxyImpl>(sessionWrapper_));
887 }
888 }
889
SetModalOnDestroy(const std::function<void ()> && callback)890 void UIExtensionPattern::SetModalOnDestroy(const std::function<void()>&& callback)
891 {
892 onModalDestroy_ = std::move(callback);
893 }
894
FireModalOnDestroy()895 void UIExtensionPattern::FireModalOnDestroy()
896 {
897 UIEXT_LOGI("ModalOnDestroy the current state is '%{public}s'.", ToString(state_));
898 // Native modal page destroy callback
899 if (onModalDestroy_) {
900 ContainerScope scope(instanceId_);
901 onModalDestroy_();
902 }
903 }
904
SetOnReleaseCallback(const std::function<void (int32_t)> && callback)905 void UIExtensionPattern::SetOnReleaseCallback(const std::function<void(int32_t)>&& callback)
906 {
907 onReleaseCallback_ = std::move(callback);
908 }
909
FireOnReleaseCallback(int32_t releaseCode)910 void UIExtensionPattern::FireOnReleaseCallback(int32_t releaseCode)
911 {
912 UIEXT_LOGI("OnRelease the state is changing from '%{public}s' to 'DESTRUCTION' and releaseCode = %{public}d.",
913 ToString(state_), releaseCode);
914 state_ = AbilityState::DESTRUCTION;
915 if (onReleaseCallback_) {
916 onReleaseCallback_(releaseCode);
917 }
918 // Release the session.
919 if (sessionWrapper_ && sessionWrapper_->IsSessionValid()) {
920 sessionWrapper_->DestroySession();
921 }
922 }
923
SetOnErrorCallback(const std::function<void (int32_t code,const std::string & name,const std::string & message)> && callback)924 void UIExtensionPattern::SetOnErrorCallback(
925 const std::function<void(int32_t code, const std::string& name, const std::string& message)>&& callback)
926 {
927 onErrorCallback_ = std::move(callback);
928 if (lastError_.code != 0) {
929 ErrorMsg error;
930 std::swap(lastError_, error);
931 FireOnErrorCallback(error.code, error.name, error.message);
932 }
933 }
934
FireOnErrorCallback(int32_t code,const std::string & name,const std::string & message)935 void UIExtensionPattern::FireOnErrorCallback(int32_t code, const std::string& name, const std::string& message)
936 {
937 // 1. As long as the error occurs, the host believes that UIExtensionAbility has been killed.
938 UIEXT_LOGI("OnError the state is changing from '%{public}s' to 'NONE'.", ToString(state_));
939 state_ = AbilityState::NONE;
940 // Release the session.
941 if (sessionWrapper_ && sessionWrapper_->IsSessionValid()) {
942 if (!isShowPlaceholder_) {
943 auto host = GetHost();
944 CHECK_NULL_VOID(host);
945 host->RemoveChildAtIndex(0);
946 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
947 }
948 sessionWrapper_->NotifyDestroy(false);
949 sessionWrapper_->DestroySession();
950 }
951 if (onErrorCallback_) {
952 ContainerScope scope(instanceId_);
953 onErrorCallback_(code, name, message);
954 return;
955 }
956 lastError_ = { code, name, message };
957 }
958
SetOnResultCallback(const std::function<void (int32_t,const AAFwk::Want &)> && callback)959 void UIExtensionPattern::SetOnResultCallback(const std::function<void(int32_t, const AAFwk::Want&)>&& callback)
960 {
961 onResultCallback_ = std::move(callback);
962 }
963
FireOnResultCallback(int32_t code,const AAFwk::Want & want)964 void UIExtensionPattern::FireOnResultCallback(int32_t code, const AAFwk::Want& want)
965 {
966 UIEXT_LOGI("OnResult the state is changing from '%{public}s' to 'DESTRUCTION'.", ToString(state_));
967 if (onResultCallback_ && (state_ != AbilityState::DESTRUCTION)) {
968 ContainerScope scope(instanceId_);
969 onResultCallback_(code, want);
970 }
971 state_ = AbilityState::DESTRUCTION;
972 }
973
IsCompatibleOldVersion()974 bool UIExtensionPattern::IsCompatibleOldVersion()
975 {
976 ContainerScope scope(instanceId_);
977 return (sessionType_ == SessionType::UI_EXTENSION_ABILITY) && (onTerminatedCallback_ == nullptr);
978 }
979
SetOnTerminatedCallback(const std::function<void (int32_t,const RefPtr<WantWrap> & wantWrap)> && callback)980 void UIExtensionPattern::SetOnTerminatedCallback(
981 const std::function<void(int32_t, const RefPtr<WantWrap>& wantWrap)>&& callback)
982 {
983 onTerminatedCallback_ = std::move(callback);
984 }
985
FireOnTerminatedCallback(int32_t code,const RefPtr<WantWrap> & wantWrap)986 void UIExtensionPattern::FireOnTerminatedCallback(int32_t code, const RefPtr<WantWrap>& wantWrap)
987 {
988 UIEXT_LOGI("OnTerminated the state is changing from '%{public}s' to 'DESTRUCTION'.", ToString(state_));
989 if (onTerminatedCallback_ && (state_ != AbilityState::DESTRUCTION)) {
990 ContainerScope scope(instanceId_);
991 onTerminatedCallback_(code, wantWrap);
992 }
993 state_ = AbilityState::DESTRUCTION;
994 }
995
SetOnReceiveCallback(const std::function<void (const AAFwk::WantParams &)> && callback)996 void UIExtensionPattern::SetOnReceiveCallback(const std::function<void(const AAFwk::WantParams&)>&& callback)
997 {
998 onReceiveCallback_ = std::move(callback);
999 }
1000
FireOnReceiveCallback(const AAFwk::WantParams & params)1001 void UIExtensionPattern::FireOnReceiveCallback(const AAFwk::WantParams& params)
1002 {
1003 UIEXT_LOGI("OnReceive the current state is '%{public}s'.", ToString(state_));
1004 if (onReceiveCallback_) {
1005 ContainerScope scope(instanceId_);
1006 onReceiveCallback_(params);
1007 }
1008 }
1009
SetSyncCallbacks(const std::list<std::function<void (const RefPtr<UIExtensionProxy> &)>> && callbackList)1010 void UIExtensionPattern::SetSyncCallbacks(
1011 const std::list<std::function<void(const RefPtr<UIExtensionProxy>&)>>&& callbackList)
1012 {
1013 onSyncOnCallbackList_ = std::move(callbackList);
1014 }
1015
FireSyncCallbacks()1016 void UIExtensionPattern::FireSyncCallbacks()
1017 {
1018 UIEXT_LOGD("The size of sync callbacks = %{public}zu.", onSyncOnCallbackList_.size());
1019 ContainerScope scope(instanceId_);
1020 for (const auto& callback : onSyncOnCallbackList_) {
1021 if (callback) {
1022 callback(MakeRefPtr<UIExtensionProxy>(sessionWrapper_, Claim(this)));
1023 }
1024 }
1025 }
1026
SetAsyncCallbacks(const std::list<std::function<void (const RefPtr<UIExtensionProxy> &)>> && callbackList)1027 void UIExtensionPattern::SetAsyncCallbacks(
1028 const std::list<std::function<void(const RefPtr<UIExtensionProxy>&)>>&& callbackList)
1029 {
1030 onAsyncOnCallbackList_ = std::move(callbackList);
1031 }
1032
FireAsyncCallbacks()1033 void UIExtensionPattern::FireAsyncCallbacks()
1034 {
1035 UIEXT_LOGD("The size of async callbacks = %{public}zu.", onSyncOnCallbackList_.size());
1036 ContainerScope scope(instanceId_);
1037 for (const auto& callback : onAsyncOnCallbackList_) {
1038 if (callback) {
1039 callback(MakeRefPtr<UIExtensionProxy>(sessionWrapper_, Claim(this)));
1040 }
1041 }
1042 }
1043
SetBindModalCallback(const std::function<void ()> && callback)1044 void UIExtensionPattern::SetBindModalCallback(const std::function<void()>&& callback)
1045 {
1046 bindModalCallback_ = std::move(callback);
1047 }
1048
FireBindModalCallback()1049 void UIExtensionPattern::FireBindModalCallback()
1050 {
1051 if (bindModalCallback_) {
1052 bindModalCallback_();
1053 }
1054 }
1055
SetDensityDpi(bool densityDpi)1056 void UIExtensionPattern::SetDensityDpi(bool densityDpi)
1057 {
1058 densityDpi_ = densityDpi;
1059 }
1060
DispatchFollowHostDensity(bool densityDpi)1061 void UIExtensionPattern::DispatchFollowHostDensity(bool densityDpi)
1062 {
1063 densityDpi_ = densityDpi;
1064 CHECK_NULL_VOID(sessionWrapper_);
1065 sessionWrapper_->SetDensityDpiImpl(densityDpi_);
1066 }
1067
OnDpiConfigurationUpdate()1068 void UIExtensionPattern::OnDpiConfigurationUpdate()
1069 {
1070 if (GetDensityDpi()) {
1071 DispatchFollowHostDensity(true);
1072 }
1073 }
1074
GetDensityDpi()1075 bool UIExtensionPattern::GetDensityDpi()
1076 {
1077 return densityDpi_;
1078 }
1079
OnVisibleChange(bool visible)1080 void UIExtensionPattern::OnVisibleChange(bool visible)
1081 {
1082 UIEXT_LOGI("The component is changing from '%{public}s' to '%{public}s'.", isVisible_ ? "visible" : "invisible",
1083 visible ? "visible" : "invisible");
1084 isVisible_ = visible;
1085 if (visible) {
1086 NotifyForeground();
1087 } else {
1088 NotifyBackground();
1089 }
1090 }
1091
InitializeAccessibility()1092 void UIExtensionPattern::InitializeAccessibility()
1093 {
1094 if (accessibilityChildTreeCallback_ != nullptr) {
1095 return;
1096 }
1097 auto instanceId = GetInstanceIdFromHost();
1098 ContainerScope scope(instanceId);
1099 auto ngPipeline = NG::PipelineContext::GetCurrentContext();
1100 CHECK_NULL_VOID(ngPipeline);
1101 auto frontend = ngPipeline->GetFrontend();
1102 CHECK_NULL_VOID(frontend);
1103 auto accessibilityManager = frontend->GetAccessibilityManager();
1104 CHECK_NULL_VOID(accessibilityManager);
1105 auto frameNode = frameNode_.Upgrade();
1106 CHECK_NULL_VOID(frameNode);
1107 int64_t accessibilityId = frameNode->GetAccessibilityId();
1108 accessibilityChildTreeCallback_ = std::make_shared<UIExtensionAccessibilityChildTreeCallback>(
1109 WeakClaim(this), accessibilityId);
1110 CHECK_NULL_VOID(accessibilityChildTreeCallback_);
1111 auto realHostWindowId = ngPipeline->GetRealHostWindowId();
1112 if (accessibilityManager->IsRegister()) {
1113 accessibilityChildTreeCallback_->OnRegister(
1114 realHostWindowId, accessibilityManager->GetTreeId());
1115 }
1116 UIEXT_LOGI("UIExtension: %{public}" PRId64 " register child tree, realHostWindowId: %{public}u",
1117 accessibilityId, realHostWindowId);
1118 accessibilityManager->RegisterAccessibilityChildTreeCallback(accessibilityId, accessibilityChildTreeCallback_);
1119 }
1120
OnAccessibilityChildTreeRegister(uint32_t windowId,int32_t treeId,int64_t accessibilityId)1121 void UIExtensionPattern::OnAccessibilityChildTreeRegister(uint32_t windowId, int32_t treeId, int64_t accessibilityId)
1122 {
1123 UIEXT_LOGI("treeId: %{public}d, id: %{public}" PRId64, treeId, accessibilityId);
1124 if (sessionWrapper_ == nullptr) {
1125 UIEXT_LOGI("sessionWrapper_ is null");
1126 return;
1127 }
1128 sessionWrapper_->TransferAccessibilityChildTreeRegister(windowId, treeId, accessibilityId);
1129 }
1130
OnAccessibilityChildTreeDeregister()1131 void UIExtensionPattern::OnAccessibilityChildTreeDeregister()
1132 {
1133 UIEXT_LOGI("deregister accessibility child tree");
1134 if (sessionWrapper_ == nullptr) {
1135 UIEXT_LOGI("sessionWrapper_ is null");
1136 return;
1137 }
1138 sessionWrapper_->TransferAccessibilityChildTreeDeregister();
1139 }
1140
OnSetAccessibilityChildTree(int32_t childWindowId,int32_t childTreeId)1141 void UIExtensionPattern::OnSetAccessibilityChildTree(int32_t childWindowId, int32_t childTreeId)
1142 {
1143 auto frameNode = frameNode_.Upgrade();
1144 CHECK_NULL_VOID(frameNode);
1145 auto accessibilityProperty = frameNode->GetAccessibilityProperty<AccessibilityProperty>();
1146 if (accessibilityProperty != nullptr) {
1147 accessibilityProperty->SetChildWindowId(childWindowId);
1148 accessibilityProperty->SetChildTreeId(childTreeId);
1149 }
1150 }
1151
OnAccessibilityDumpChildInfo(const std::vector<std::string> & params,std::vector<std::string> & info)1152 void UIExtensionPattern::OnAccessibilityDumpChildInfo(
1153 const std::vector<std::string>& params, std::vector<std::string>& info)
1154 {
1155 UIEXT_LOGI("dump accessibility child info");
1156 if (sessionWrapper_ == nullptr) {
1157 UIEXT_LOGI("sessionWrapper_ is null");
1158 return;
1159 }
1160 sessionWrapper_->TransferAccessibilityDumpChildInfo(params, info);
1161 }
1162
ResetAccessibilityChildTreeCallback()1163 void UIExtensionPattern::ResetAccessibilityChildTreeCallback()
1164 {
1165 CHECK_NULL_VOID(accessibilityChildTreeCallback_);
1166 auto instanceId = GetInstanceIdFromHost();
1167 ContainerScope scope(instanceId);
1168 auto ngPipeline = NG::PipelineContext::GetCurrentContext();
1169 CHECK_NULL_VOID(ngPipeline);
1170 auto frontend = ngPipeline->GetFrontend();
1171 CHECK_NULL_VOID(frontend);
1172 auto accessibilityManager = frontend->GetAccessibilityManager();
1173 CHECK_NULL_VOID(accessibilityManager);
1174 accessibilityManager->DeregisterAccessibilityChildTreeCallback(
1175 accessibilityChildTreeCallback_->GetAccessibilityId());
1176 accessibilityChildTreeCallback_.reset();
1177 accessibilityChildTreeCallback_ = nullptr;
1178 }
1179
OnMountToParentDone()1180 void UIExtensionPattern::OnMountToParentDone()
1181 {
1182 UIEXT_LOGI("OnMountToParentDone.");
1183 hasMountToParent_ = true;
1184 if (needReNotifyForeground_) {
1185 auto hostWindowNode = WindowSceneHelper::FindWindowScene(GetHost());
1186 if (hostWindowNode) {
1187 needReNotifyForeground_ = false;
1188 UIEXT_LOGI("NotifyForeground OnMountToParentDone.");
1189 NotifyForeground();
1190 } else {
1191 UIEXT_LOGI("No WindowScene when OnMountToParentDone, wait.");
1192 }
1193 }
1194 auto frameNode = frameNode_.Upgrade();
1195 CHECK_NULL_VOID(frameNode);
1196 if (frameNode->GetNodeStatus() == NodeStatus::NORMAL_NODE) {
1197 UIEXT_LOGD("Frame node status is normal.");
1198 return;
1199 }
1200 auto wantWrap = GetWantWrap();
1201 CHECK_NULL_VOID(wantWrap);
1202 UpdateWant(wantWrap);
1203 SetWantWrap(nullptr);
1204 }
1205
AfterMountToParent()1206 void UIExtensionPattern::AfterMountToParent()
1207 {
1208 UIEXT_LOGI("AfterMountToParent.");
1209 hasMountToParent_ = true;
1210 if (needReNotifyForeground_) {
1211 auto hostWindowNode = WindowSceneHelper::FindWindowScene(GetHost());
1212 if (hostWindowNode) {
1213 needReNotifyForeground_ = false;
1214 UIEXT_LOGI("NotifyForeground AfterMountToParent.");
1215 NotifyForeground();
1216 } else {
1217 UIEXT_LOGI("No WindowScene when AfterMountToParent, wait.");
1218 }
1219 }
1220 }
1221
RegisterVisibleAreaChange()1222 void UIExtensionPattern::RegisterVisibleAreaChange()
1223 {
1224 auto pipeline = PipelineContext::GetCurrentContext();
1225 CHECK_NULL_VOID(pipeline);
1226 auto callback = [weak = WeakClaim(this)](bool visible, double ratio) {
1227 auto uiExtension = weak.Upgrade();
1228 CHECK_NULL_VOID(uiExtension);
1229 uiExtension->HandleVisibleAreaChange(visible, ratio);
1230 };
1231 auto host = GetHost();
1232 CHECK_NULL_VOID(host);
1233 std::vector<double> ratioList = { SHOW_START, SHOW_FULL };
1234 pipeline->AddVisibleAreaChangeNode(host, ratioList, callback, false);
1235 }
1236
HandleVisibleAreaChange(bool visible,double ratio)1237 void UIExtensionPattern::HandleVisibleAreaChange(bool visible, double ratio)
1238 {
1239 UIEXT_LOGI("HandleVisibleAreaChange visible: %{public}d, curVisible: %{public}d, "
1240 "ratio: %{public}f, displayArea: %{public}s.", visible, curVisible_,
1241 ratio, displayArea_.ToString().c_str());
1242 bool needCheckDisplayArea = NearEqual(ratio, SHOW_FULL) && curVisible_ && visible;
1243 bool curVisible = !NearEqual(ratio, SHOW_START);
1244 if (curVisible_ != curVisible) {
1245 curVisible_ = curVisible;
1246 OnVisibleChange(curVisible_);
1247 }
1248
1249 if (needCheckDisplayArea) {
1250 DispatchDisplayArea(false);
1251 }
1252 }
1253
OnLanguageConfigurationUpdate()1254 void UIExtensionPattern::OnLanguageConfigurationUpdate()
1255 {
1256 CHECK_NULL_VOID(sessionWrapper_);
1257 sessionWrapper_->NotifyConfigurationUpdate();
1258 }
1259
OnColorConfigurationUpdate()1260 void UIExtensionPattern::OnColorConfigurationUpdate()
1261 {
1262 CHECK_NULL_VOID(sessionWrapper_);
1263 sessionWrapper_->NotifyConfigurationUpdate();
1264 }
1265
GetSessionId()1266 int32_t UIExtensionPattern::GetSessionId()
1267 {
1268 return sessionWrapper_ ? sessionWrapper_->GetSessionId() : 0;
1269 }
1270
GetUiExtensionId()1271 int32_t UIExtensionPattern::GetUiExtensionId()
1272 {
1273 return uiExtensionId_;
1274 }
1275
GetNodeId()1276 int32_t UIExtensionPattern::GetNodeId()
1277 {
1278 auto host = GetHost();
1279 return host ? host->GetId() : -1;
1280 }
1281
GetInstanceId()1282 int32_t UIExtensionPattern::GetInstanceId()
1283 {
1284 return instanceId_;
1285 }
1286
GetInstanceIdFromHost()1287 int32_t UIExtensionPattern::GetInstanceIdFromHost()
1288 {
1289 auto instanceId = GetHostInstanceId();
1290 if (instanceId != instanceId_) {
1291 UIEXT_LOGW("UIExtension pattern instanceId %{public}d not equal frame node instanceId %{public}d",
1292 instanceId_, instanceId);
1293 }
1294 return instanceId;
1295 }
1296
DispatchOriginAvoidArea(const Rosen::AvoidArea & avoidArea,uint32_t type)1297 void UIExtensionPattern::DispatchOriginAvoidArea(const Rosen::AvoidArea& avoidArea, uint32_t type)
1298 {
1299 CHECK_NULL_VOID(sessionWrapper_);
1300 sessionWrapper_->NotifyOriginAvoidArea(avoidArea, type);
1301 }
1302
SetWantWrap(const RefPtr<OHOS::Ace::WantWrap> & wantWrap)1303 void UIExtensionPattern::SetWantWrap(const RefPtr<OHOS::Ace::WantWrap>& wantWrap)
1304 {
1305 curWant_ = wantWrap;
1306 }
1307
GetWantWrap()1308 RefPtr<OHOS::Ace::WantWrap> UIExtensionPattern::GetWantWrap()
1309 {
1310 return curWant_;
1311 }
1312
WrapExtensionAbilityId(int64_t extensionOffset,int64_t abilityId)1313 int64_t UIExtensionPattern::WrapExtensionAbilityId(int64_t extensionOffset, int64_t abilityId)
1314 {
1315 return uiExtensionId_ * extensionOffset + abilityId;
1316 }
1317
ToString(AbilityState state)1318 const char* UIExtensionPattern::ToString(AbilityState state)
1319 {
1320 switch (state) {
1321 case AbilityState::FOREGROUND:
1322 return "FOREGROUND";
1323 case AbilityState::BACKGROUND:
1324 return "BACKGROUND";
1325 case AbilityState::DESTRUCTION:
1326 return "DESTRUCTION";
1327 case AbilityState::NONE:
1328 default:
1329 return "NONE";
1330 }
1331 }
1332 } // namespace OHOS::Ace::NG
1333