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/session_wrapper_impl.h"
17
18 #include <cmath>
19 #include <memory>
20
21 #include "accessibility_event_info.h"
22 #include "refbase.h"
23 #include "session_manager/include/extension_session_manager.h"
24 #include "ui/rs_surface_node.h"
25 #include "wm/wm_common.h"
26
27 #include "adapter/ohos/entrance/ace_container.h"
28 #include "adapter/ohos/osal/want_wrap_ohos.h"
29 #include "base/utils/utils.h"
30 #include "core/common/container.h"
31 #include "core/common/container_scope.h"
32 #include "core/pipeline_ng/pipeline_context.h"
33
34 namespace OHOS::Ace::NG {
35
36 class UIExtensionLifecycleListener : public Rosen::ILifecycleListener {
37 public:
UIExtensionLifecycleListener(int32_t instanceId,const WeakPtr<UIExtensionPattern> & hostPattern)38 UIExtensionLifecycleListener(int32_t instanceId, const WeakPtr<UIExtensionPattern>& hostPattern)
39 : instanceId_(instanceId), hostPattern_(hostPattern)
40 {}
41 virtual ~UIExtensionLifecycleListener() = default;
42
OnActivation()43 void OnActivation() override {}
OnForeground()44 void OnForeground() override {}
OnBackground()45 void OnBackground() override {}
46
OnConnect()47 void OnConnect() override
48 {
49 ContainerScope scope(instanceId_);
50 auto pipeline = PipelineBase::GetCurrentContext();
51 CHECK_NULL_VOID(pipeline);
52 auto taskExecutor = pipeline->GetTaskExecutor();
53 CHECK_NULL_VOID(taskExecutor);
54 taskExecutor->PostTask(
55 [weak = hostPattern_]() {
56 auto pattern = weak.Upgrade();
57 CHECK_NULL_VOID(pattern);
58 pattern->OnConnect();
59 },
60 TaskExecutor::TaskType::UI);
61 }
62
OnDisconnect()63 void OnDisconnect() override
64 {
65 ContainerScope scope(instanceId_);
66 auto pipeline = PipelineBase::GetCurrentContext();
67 CHECK_NULL_VOID(pipeline);
68 auto taskExecutor = pipeline->GetTaskExecutor();
69 CHECK_NULL_VOID(taskExecutor);
70 taskExecutor->PostTask(
71 [weak = hostPattern_]() {
72 auto pattern = weak.Upgrade();
73 CHECK_NULL_VOID(pattern);
74 pattern->OnDisconnect();
75 },
76 TaskExecutor::TaskType::UI);
77 }
78
OnExtensionDied()79 void OnExtensionDied() override
80 {
81 ContainerScope scope(instanceId_);
82 auto pipeline = PipelineBase::GetCurrentContext();
83 CHECK_NULL_VOID(pipeline);
84 auto taskExecutor = pipeline->GetTaskExecutor();
85 CHECK_NULL_VOID(taskExecutor);
86 taskExecutor->PostTask(
87 [weak = hostPattern_]() {
88 auto pattern = weak.Upgrade();
89 CHECK_NULL_VOID(pattern);
90 pattern->OnExtensionDied();
91 },
92 TaskExecutor::TaskType::UI);
93 }
94
OnAccessibilityEvent(const Accessibility::AccessibilityEventInfo & info,int64_t uiExtensionOffset)95 void OnAccessibilityEvent(const Accessibility::AccessibilityEventInfo& info, int64_t uiExtensionOffset) override
96 {
97 ContainerScope scope(instanceId_);
98 auto pipeline = PipelineBase::GetCurrentContext();
99 CHECK_NULL_VOID(pipeline);
100 auto taskExecutor = pipeline->GetTaskExecutor();
101 CHECK_NULL_VOID(taskExecutor);
102 taskExecutor->PostTask(
103 [weak = hostPattern_, info, uiExtensionOffset]() {
104 auto pattern = weak.Upgrade();
105 CHECK_NULL_VOID(pattern);
106 pattern->OnAccessibilityEvent(info, uiExtensionOffset);
107 },
108 TaskExecutor::TaskType::UI);
109 }
110
111 private:
112 int32_t instanceId_;
113 WeakPtr<UIExtensionPattern> hostPattern_;
114 };
115
116 /************************************************ Begin: Initialization ***********************************************/
SessionWrapperImpl(const WeakPtr<UIExtensionPattern> & hostPattern,int32_t instanceId,bool isTransferringCaller)117 SessionWrapperImpl::SessionWrapperImpl(
118 const WeakPtr<UIExtensionPattern>& hostPattern, int32_t instanceId, bool isTransferringCaller)
119 : hostPattern_(hostPattern), instanceId_(instanceId), isTransferringCaller_(isTransferringCaller)
120 {}
121
~SessionWrapperImpl()122 SessionWrapperImpl::~SessionWrapperImpl() {}
123
InitAllCallback()124 void SessionWrapperImpl::InitAllCallback()
125 {
126 CHECK_NULL_VOID(session_);
127 auto pipeline = PipelineBase::GetCurrentContext();
128 CHECK_NULL_VOID(pipeline);
129 auto taskExecutor = pipeline->GetTaskExecutor();
130 CHECK_NULL_VOID(taskExecutor);
131 auto sessionCallbacks = session_->GetExtensionSessionEventCallback();
132
133 foregroundCallback_ = [weak = hostPattern_, taskExecutor](OHOS::Rosen::WSError errcode) {
134 if (errcode != OHOS::Rosen::WSError::WS_OK) {
135 taskExecutor->PostTask(
136 [weak, errcode] {
137 auto pattern = weak.Upgrade();
138 CHECK_NULL_VOID(pattern);
139 std::string name = "start_ability_fail";
140 std::string message =
141 "Start ui extension ability failed, please check the want of UIextensionAbility.";
142 pattern->FireOnErrorCallback(static_cast<int32_t>(errcode), name, message);
143 },
144 TaskExecutor::TaskType::UI);
145 }
146 };
147 backgroundCallback_ = [weak = hostPattern_, taskExecutor](OHOS::Rosen::WSError errcode) {
148 if (errcode != OHOS::Rosen::WSError::WS_OK) {
149 taskExecutor->PostTask(
150 [weak, errcode] {
151 auto pattern = weak.Upgrade();
152 CHECK_NULL_VOID(pattern);
153 std::string name = "background_fail";
154 std::string message = "background ui extension ability failed, please check AMS log.";
155 pattern->FireOnErrorCallback(static_cast<int32_t>(errcode), name, message);
156 },
157 TaskExecutor::TaskType::UI);
158 }
159 };
160 destructionCallback_ = [weak = hostPattern_, taskExecutor](OHOS::Rosen::WSError errcode) {
161 if (errcode != OHOS::Rosen::WSError::WS_OK) {
162 taskExecutor->PostTask(
163 [weak, errcode] {
164 auto pattern = weak.Upgrade();
165 CHECK_NULL_VOID(pattern);
166 std::string name = "terminate_fail";
167 std::string message = "terminate ui extension ability failed, please check AMS log.";
168 pattern->FireOnErrorCallback(static_cast<int32_t>(errcode), name, message);
169 },
170 TaskExecutor::TaskType::UI);
171 }
172 };
173 sessionCallbacks->transferAbilityResultFunc_ = [weak = hostPattern_, taskExecutor](
174 int32_t code, const AAFwk::Want& want) {
175 taskExecutor->PostTask(
176 [weak, code, want]() {
177 auto pattern = weak.Upgrade();
178 CHECK_NULL_VOID(pattern);
179 pattern->FireOnResultCallback(code, want);
180 },
181 TaskExecutor::TaskType::UI);
182 };
183 sessionCallbacks->transferExtensionDataFunc_ = [weak = hostPattern_, taskExecutor](
184 const AAFwk::WantParams& params) {
185 taskExecutor->PostTask(
186 [weak, params]() {
187 auto pattern = weak.Upgrade();
188 CHECK_NULL_VOID(pattern);
189 pattern->FireOnReceiveCallback(params);
190 },
191 TaskExecutor::TaskType::UI);
192 };
193 sessionCallbacks->notifyRemoteReadyFunc_ = [weak = hostPattern_, taskExecutor]() {
194 taskExecutor->PostTask(
195 [weak]() {
196 auto pattern = weak.Upgrade();
197 CHECK_NULL_VOID(pattern);
198 pattern->FireOnRemoteReadyCallback();
199 },
200 TaskExecutor::TaskType::UI);
201 };
202 sessionCallbacks->notifySyncOnFunc_ = [weak = hostPattern_, taskExecutor]() {
203 taskExecutor->PostTask(
204 [weak]() {
205 auto pattern = weak.Upgrade();
206 CHECK_NULL_VOID(pattern);
207 pattern->FireSyncCallbacks();
208 },
209 TaskExecutor::TaskType::UI);
210 };
211 sessionCallbacks->notifyAsyncOnFunc_ = [weak = hostPattern_, taskExecutor]() {
212 taskExecutor->PostTask(
213 [weak]() {
214 auto pattern = weak.Upgrade();
215 CHECK_NULL_VOID(pattern);
216 pattern->FireAsyncCallbacks();
217 },
218 TaskExecutor::TaskType::UI);
219 };
220 sessionCallbacks->notifyBindModalFunc_ = [weak = hostPattern_, taskExecutor]() {
221 taskExecutor->PostSyncTask(
222 [weak]() {
223 auto pattern = weak.Upgrade();
224 CHECK_NULL_VOID(pattern);
225 pattern->FireBindModalCallback();
226 },
227 TaskExecutor::TaskType::UI);
228 };
229 sessionCallbacks->notifyGetAvoidAreaByTypeFunc_ = [instanceId = instanceId_](
230 Rosen::AvoidAreaType type) -> Rosen::AvoidArea {
231 Rosen::AvoidArea avoidArea;
232 auto container = Platform::AceContainer::GetContainer(instanceId);
233 CHECK_NULL_RETURN(container, avoidArea);
234 avoidArea = container->GetAvoidAreaByType(type);
235 return avoidArea;
236 };
237 }
238 /************************************************ End: Initialization *************************************************/
239
240 /************************************************ Begin: About session ************************************************/
CreateSession(const AAFwk::Want & want,bool isAsyncModalBinding)241 void SessionWrapperImpl::CreateSession(const AAFwk::Want& want, bool isAsyncModalBinding)
242 {
243 TAG_LOGI(AceLogTag::ACE_UIEXTENSIONCOMPONENT, "Create session: %{private}s", want.ToString().c_str());
244 const std::string occupiedAreaChangeKey("ability.want.params.IsNotifyOccupiedAreaChange");
245 isNotifyOccupiedAreaChange_ = want.GetBoolParam(occupiedAreaChangeKey, false);
246 auto container = AceType::DynamicCast<Platform::AceContainer>(Container::Current());
247 CHECK_NULL_VOID(container);
248 auto callerToken = container->GetToken();
249 auto parentToken = container->GetParentToken();
250 Rosen::SessionInfo extensionSessionInfo = {
251 .bundleName_ = want.GetElement().GetBundleName(),
252 .abilityName_ = want.GetElement().GetAbilityName(),
253 .callerToken_ = callerToken,
254 .rootToken_ = (isTransferringCaller_ && parentToken) ? parentToken : callerToken,
255 .want = std::make_shared<Want>(want),
256 .isAsyncModalBinding_ = isAsyncModalBinding,
257 };
258 session_ = Rosen::ExtensionSessionManager::GetInstance().RequestExtensionSession(extensionSessionInfo);
259 CHECK_NULL_VOID(session_);
260 lifecycleListener_ = std::make_shared<UIExtensionLifecycleListener>(instanceId_, hostPattern_);
261 session_->RegisterLifecycleListener(lifecycleListener_);
262 InitAllCallback();
263 }
264
DestroySession()265 void SessionWrapperImpl::DestroySession()
266 {
267 CHECK_NULL_VOID(session_);
268 session_->UnregisterLifecycleListener(lifecycleListener_);
269 session_ = nullptr;
270 }
271
IsSessionValid()272 bool SessionWrapperImpl::IsSessionValid()
273 {
274 return session_ != nullptr;
275 }
276
GetSessionId()277 int32_t SessionWrapperImpl::GetSessionId()
278 {
279 return session_ ? session_->GetPersistentId() : 0;
280 }
281
GetWant()282 const std::shared_ptr<AAFwk::Want> SessionWrapperImpl::GetWant()
283 {
284 return session_ ? session_->GetSessionInfo().want : nullptr;
285 }
286 /************************************************ End: About session **************************************************/
287
288 /************************************************ Begin: Synchronous interface for event notify ***********************/
NotifyFocusEventSync(bool isFocus)289 bool SessionWrapperImpl::NotifyFocusEventSync(bool isFocus)
290 {
291 return false;
292 }
NotifyFocusStateSync(bool focusState)293 bool SessionWrapperImpl::NotifyFocusStateSync(bool focusState)
294 {
295 return false;
296 }
297
NotifyBackPressedSync()298 bool SessionWrapperImpl::NotifyBackPressedSync()
299 {
300 CHECK_NULL_RETURN(session_, false);
301 bool isConsumed = false;
302 session_->TransferBackPressedEventForConsumed(isConsumed);
303 return isConsumed;
304 }
305
NotifyPointerEventSync(const std::shared_ptr<OHOS::MMI::PointerEvent> & pointerEvent)306 bool SessionWrapperImpl::NotifyPointerEventSync(const std::shared_ptr<OHOS::MMI::PointerEvent>& pointerEvent)
307 {
308 return false;
309 }
310
NotifyKeyEventSync(const std::shared_ptr<OHOS::MMI::KeyEvent> & keyEvent)311 bool SessionWrapperImpl::NotifyKeyEventSync(const std::shared_ptr<OHOS::MMI::KeyEvent>& keyEvent)
312 {
313 CHECK_NULL_RETURN(session_, false);
314 bool isConsumed = false;
315 session_->TransferKeyEventForConsumed(keyEvent, isConsumed);
316 return isConsumed;
317 }
318
NotifyAxisEventSync(const std::shared_ptr<OHOS::MMI::AxisEvent> & axisEvent)319 bool SessionWrapperImpl::NotifyAxisEventSync(const std::shared_ptr<OHOS::MMI::AxisEvent>& axisEvent)
320 {
321 return false;
322 }
323 /************************************************ End: Synchronous interface for event notify *************************/
324
325 /************************************************ Begin: Asynchronous interface for event notify **********************/
NotifyFocusEventAsync(bool isFocus)326 bool SessionWrapperImpl::NotifyFocusEventAsync(bool isFocus)
327 {
328 CHECK_NULL_RETURN(session_, false);
329 session_->TransferFocusActiveEvent(isFocus);
330 return true;
331 }
332
NotifyFocusStateAsync(bool focusState)333 bool SessionWrapperImpl::NotifyFocusStateAsync(bool focusState)
334 {
335 CHECK_NULL_RETURN(session_, false);
336 session_->TransferFocusStateEvent(focusState);
337 return true;
338 }
339
NotifyBackPressedAsync()340 bool SessionWrapperImpl::NotifyBackPressedAsync()
341 {
342 return false;
343 }
NotifyPointerEventAsync(const std::shared_ptr<OHOS::MMI::PointerEvent> & pointerEvent)344 bool SessionWrapperImpl::NotifyPointerEventAsync(const std::shared_ptr<OHOS::MMI::PointerEvent>& pointerEvent)
345 {
346 if (session_ && pointerEvent) {
347 session_->TransferPointerEvent(pointerEvent);
348 }
349 return false;
350 }
NotifyKeyEventAsync(const std::shared_ptr<OHOS::MMI::KeyEvent> & keyEvent)351 bool SessionWrapperImpl::NotifyKeyEventAsync(const std::shared_ptr<OHOS::MMI::KeyEvent>& keyEvent)
352 {
353 if (session_ && keyEvent) {
354 session_->TransferKeyEvent(keyEvent);
355 }
356 return false;
357 }
NotifyAxisEventAsync(const std::shared_ptr<OHOS::MMI::AxisEvent> & axisEvent)358 bool SessionWrapperImpl::NotifyAxisEventAsync(const std::shared_ptr<OHOS::MMI::AxisEvent>& axisEvent)
359 {
360 return false;
361 }
362 /************************************************ End: Asynchronous interface for event notify ************************/
363
364 /************************************************ Begin: The lifecycle interface **************************************/
NotifyCreate()365 void SessionWrapperImpl::NotifyCreate() {}
366
NotifyForeground()367 void SessionWrapperImpl::NotifyForeground()
368 {
369 TAG_LOGI(AceLogTag::ACE_UIEXTENSIONCOMPONENT, "Foreground: session is %{public}s", session_ ? "valid" : "invalid");
370 CHECK_NULL_VOID(session_);
371 auto pipeline = PipelineBase::GetCurrentContext();
372 CHECK_NULL_VOID(pipeline);
373 auto hostWindowId = pipeline->GetFocusWindowId();
374 Rosen::ExtensionSessionManager::GetInstance().RequestExtensionSessionActivation(
375 session_, hostWindowId, std::move(foregroundCallback_));
376 }
377
NotifyBackground()378 void SessionWrapperImpl::NotifyBackground()
379 {
380 TAG_LOGI(AceLogTag::ACE_UIEXTENSIONCOMPONENT, "Background: session is %{public}s", session_ ? "valid" : "invalid");
381 CHECK_NULL_VOID(session_);
382 Rosen::ExtensionSessionManager::GetInstance().RequestExtensionSessionBackground(
383 session_, std::move(backgroundCallback_));
384 }
NotifyDestroy()385 void SessionWrapperImpl::NotifyDestroy()
386 {
387 TAG_LOGI(AceLogTag::ACE_UIEXTENSIONCOMPONENT, "Destroy: session is %{public}s", session_ ? "valid" : "invalid");
388 CHECK_NULL_VOID(session_);
389 Rosen::ExtensionSessionManager::GetInstance().RequestExtensionSessionDestruction(
390 session_, std::move(destructionCallback_));
391 }
392
NotifyConfigurationUpdate()393 void SessionWrapperImpl::NotifyConfigurationUpdate() {}
394 /************************************************ End: The lifecycle interface ****************************************/
395
396 /************************************************ Begin: The interface about the accessibility ************************/
TransferExecuteAction(int64_t elementId,const std::map<std::string,std::string> & actionArguments,int32_t action,int64_t offset)397 bool SessionWrapperImpl::TransferExecuteAction(
398 int64_t elementId, const std::map<std::string, std::string>& actionArguments, int32_t action, int64_t offset)
399 {
400 CHECK_NULL_RETURN(session_, false);
401 return OHOS::Rosen::WSError::WS_OK == session_->TransferExecuteAction(elementId, actionArguments, action, offset);
402 }
403
SearchExtensionElementInfoByAccessibilityId(int64_t elementId,int32_t mode,int64_t baseParent,std::list<Accessibility::AccessibilityElementInfo> & output)404 void SessionWrapperImpl::SearchExtensionElementInfoByAccessibilityId(
405 int64_t elementId, int32_t mode, int64_t baseParent, std::list<Accessibility::AccessibilityElementInfo>& output)
406 {
407 CHECK_NULL_VOID(session_);
408 session_->TransferSearchElementInfo(elementId, mode, baseParent, output);
409 }
410
SearchElementInfosByText(int64_t elementId,const std::string & text,int64_t baseParent,std::list<Accessibility::AccessibilityElementInfo> & output)411 void SessionWrapperImpl::SearchElementInfosByText(int64_t elementId, const std::string& text, int64_t baseParent,
412 std::list<Accessibility::AccessibilityElementInfo>& output)
413 {
414 CHECK_NULL_VOID(session_);
415 session_->TransferSearchElementInfosByText(elementId, text, baseParent, output);
416 }
417
FindFocusedElementInfo(int64_t elementId,int32_t focusType,int64_t baseParent,Accessibility::AccessibilityElementInfo & output)418 void SessionWrapperImpl::FindFocusedElementInfo(
419 int64_t elementId, int32_t focusType, int64_t baseParent, Accessibility::AccessibilityElementInfo& output)
420 {
421 CHECK_NULL_VOID(session_);
422 session_->TransferFindFocusedElementInfo(elementId, focusType, baseParent, output);
423 }
424
FocusMoveSearch(int64_t elementId,int32_t direction,int64_t baseParent,Accessibility::AccessibilityElementInfo & output)425 void SessionWrapperImpl::FocusMoveSearch(
426 int64_t elementId, int32_t direction, int64_t baseParent, Accessibility::AccessibilityElementInfo& output)
427 {
428 CHECK_NULL_VOID(session_);
429 session_->TransferFocusMoveSearch(elementId, direction, baseParent, output);
430 }
431 /************************************************ Begin: The interface about the accessibility ************************/
432
433 /************************************************ Begin: The interface to control the display area ********************/
GetSurfaceNode() const434 std::shared_ptr<Rosen::RSSurfaceNode> SessionWrapperImpl::GetSurfaceNode() const
435 {
436 return session_ ? session_->GetSurfaceNode() : nullptr;
437 }
438
RefreshDisplayArea(const RectF & displayArea)439 void SessionWrapperImpl::RefreshDisplayArea(const RectF& displayArea)
440 {
441 CHECK_NULL_VOID(session_);
442 ContainerScope scope(instanceId_);
443 auto pipeline = PipelineBase::GetCurrentContext();
444 CHECK_NULL_VOID(pipeline);
445 auto curWindow = pipeline->GetCurrentWindowRect();
446 displayArea_ = displayArea + OffsetF(curWindow.Left(), curWindow.Top());
447 session_->UpdateRect({ std::round(displayArea_.Left()), std::round(displayArea_.Top()),
448 std::round(displayArea_.Width()), std::round(displayArea_.Height()) },
449 Rosen::SizeChangeReason::UNDEFINED);
450 }
451 /************************************************ End: The interface to control the display area **********************/
452
453 /************************************************ Begin: The interface to send the data for ArkTS *********************/
SendDataAsync(const AAFwk::WantParams & params) const454 void SessionWrapperImpl::SendDataAsync(const AAFwk::WantParams& params) const
455 {
456 TAG_LOGI(AceLogTag::ACE_UIEXTENSIONCOMPONENT, "Async: session is %{public}s", session_ ? "valid" : "invalid");
457 CHECK_NULL_VOID(session_);
458 session_->TransferComponentData(params);
459 }
460
SendDataSync(const AAFwk::WantParams & wantParams,AAFwk::WantParams & reWantParams) const461 int32_t SessionWrapperImpl::SendDataSync(const AAFwk::WantParams& wantParams, AAFwk::WantParams& reWantParams) const
462 {
463 TAG_LOGI(AceLogTag::ACE_UIEXTENSIONCOMPONENT, "Sync: session is %{public}s", session_ ? "valid" : "invalid");
464 Rosen::WSErrorCode transferCode = Rosen::WSErrorCode::WS_ERROR_TRANSFER_DATA_FAILED;
465 if (session_) {
466 transferCode = session_->TransferComponentDataSync(wantParams, reWantParams);
467 }
468 return static_cast<int32_t>(transferCode);
469 }
470 /************************************************ End: The interface to send the data for ArkTS ***********************/
471
472 /************************************************ Begin: The interface to control the avoid area **********************/
NotifyOriginAvoidArea(const Rosen::AvoidArea & avoidArea,uint32_t type) const473 void SessionWrapperImpl::NotifyOriginAvoidArea(const Rosen::AvoidArea& avoidArea, uint32_t type) const
474 {
475 TAG_LOGI(AceLogTag::ACE_UIEXTENSIONCOMPONENT, "AvoidArea: session is %{public}s", session_ ? "valid" : "invalid");
476 CHECK_NULL_VOID(session_);
477 session_->UpdateAvoidArea(sptr<Rosen::AvoidArea>::MakeSptr(avoidArea), static_cast<Rosen::AvoidAreaType>(type));
478 }
479
NotifyOccupiedAreaChangeInfo(sptr<Rosen::OccupiedAreaChangeInfo> info) const480 bool SessionWrapperImpl::NotifyOccupiedAreaChangeInfo(sptr<Rosen::OccupiedAreaChangeInfo> info) const
481 {
482 CHECK_NULL_RETURN(session_, false);
483 CHECK_NULL_RETURN(info, false);
484 CHECK_NULL_RETURN(isNotifyOccupiedAreaChange_, false);
485 int32_t keyboardHeight = static_cast<int32_t>(info->rect_.height_);
486 if (keyboardHeight > 0) {
487 ContainerScope scope(instanceId_);
488 auto pipeline = PipelineBase::GetCurrentContext();
489 CHECK_NULL_RETURN(pipeline, false);
490 auto curWindow = pipeline->GetCurrentWindowRect();
491 int32_t spaceWindow = std::max(curWindow.Bottom() - displayArea_.Bottom(), .0);
492 keyboardHeight = static_cast<int32_t>(std::max(keyboardHeight - spaceWindow, 0));
493 }
494 info->rect_.height_ = static_cast<uint32_t>(keyboardHeight);
495 session_->NotifyOccupiedAreaChangeInfo(info);
496 return true;
497 }
498 /************************************************ End: The interface to control the avoid area ************************/
499 } // namespace OHOS::Ace::NG
500