1 /*
2 * Copyright (c) 2021-2022 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 "adapter/ohos/entrance/ace_container.h"
17
18 #include "ability_info.h"
19 #include "flutter/lib/ui/ui_dart_state.h"
20
21 #include "adapter/ohos/entrance/ace_application_info.h"
22 #include "adapter/ohos/entrance/data_ability_helper_standard.h"
23 #include "adapter/ohos/entrance/file_asset_provider.h"
24 #include "base/log/ace_trace.h"
25 #include "base/log/event_report.h"
26 #include "base/log/frame_report.h"
27 #include "base/log/log.h"
28 #include "base/subwindow/subwindow_manager.h"
29 #include "base/utils/system_properties.h"
30 #include "base/utils/utils.h"
31 #include "core/common/ace_engine.h"
32 #include "core/common/connect_server_manager.h"
33 #include "core/common/container_scope.h"
34 #include "core/common/flutter/flutter_asset_manager.h"
35 #include "core/common/flutter/flutter_task_executor.h"
36 #include "core/common/hdc_register.h"
37 #include "core/common/platform_window.h"
38 #include "core/common/text_field_manager.h"
39 #include "core/common/watch_dog.h"
40 #include "core/common/window.h"
41 #include "core/components/theme/app_theme.h"
42 #include "core/components/theme/theme_constants.h"
43 #include "core/components/theme/theme_manager.h"
44 #include "core/pipeline/base/element.h"
45 #include "core/pipeline/pipeline_context.h"
46 #include "frameworks/bridge/card_frontend/card_frontend.h"
47 #include "frameworks/bridge/common/utils/engine_helper.h"
48 #include "frameworks/bridge/declarative_frontend/declarative_frontend.h"
49 #include "frameworks/bridge/js_frontend/engine/common/js_engine_loader.h"
50 #include "frameworks/bridge/js_frontend/js_frontend.h"
51
52 namespace OHOS::Ace::Platform {
53 namespace {
54
55 constexpr char QUICK_JS_ENGINE_SHARED_LIB[] = "libace_engine_qjs.z.so";
56 constexpr char ARK_ENGINE_SHARED_LIB[] = "libace_engine_ark.z.so";
57 constexpr char DECLARATIVE_JS_ENGINE_SHARED_LIB[] = "libace_engine_declarative.z.so";
58 constexpr char DECLARATIVE_ARK_ENGINE_SHARED_LIB[] = "libace_engine_declarative_ark.z.so";
59
60 #ifdef _ARM64_
61 const std::string ASSET_LIBARCH_PATH = "/lib/arm64";
62 #else
63 const std::string ASSET_LIBARCH_PATH = "/lib/arm";
64 #endif
65
GetEngineSharedLibrary(bool isArkApp)66 const char* GetEngineSharedLibrary(bool isArkApp)
67 {
68 if (isArkApp) {
69 return ARK_ENGINE_SHARED_LIB;
70 } else {
71 return QUICK_JS_ENGINE_SHARED_LIB;
72 }
73 }
74
GetDeclarativeSharedLibrary(bool isArkApp)75 const char* GetDeclarativeSharedLibrary(bool isArkApp)
76 {
77 if (isArkApp) {
78 return DECLARATIVE_ARK_ENGINE_SHARED_LIB;
79 } else {
80 return DECLARATIVE_JS_ENGINE_SHARED_LIB;
81 }
82 }
83
84 } // namespace
85
AceContainer(int32_t instanceId,FrontendType type,bool isArkApp,std::shared_ptr<OHOS::AppExecFwk::Ability> aceAbility,std::unique_ptr<PlatformEventCallback> callback,bool useCurrentEventRunner)86 AceContainer::AceContainer(int32_t instanceId, FrontendType type, bool isArkApp,
87 std::shared_ptr<OHOS::AppExecFwk::Ability> aceAbility, std::unique_ptr<PlatformEventCallback> callback,
88 bool useCurrentEventRunner)
89 : instanceId_(instanceId), type_(type), isArkApp_(isArkApp), aceAbility_(aceAbility),
90 useCurrentEventRunner_(useCurrentEventRunner)
91 {
92 ACE_DCHECK(callback);
93 InitializeTask();
94 platformEventCallback_ = std::move(callback);
95 useStageModel_ = false;
96 }
97
AceContainer(int32_t instanceId,FrontendType type,bool isArkApp,std::weak_ptr<OHOS::AbilityRuntime::Context> runtimeContext,std::weak_ptr<OHOS::AppExecFwk::AbilityInfo> abilityInfo,std::unique_ptr<PlatformEventCallback> callback,bool useCurrentEventRunner,bool isSubAceContainer)98 AceContainer::AceContainer(int32_t instanceId, FrontendType type, bool isArkApp,
99 std::weak_ptr<OHOS::AbilityRuntime::Context> runtimeContext,
100 std::weak_ptr<OHOS::AppExecFwk::AbilityInfo> abilityInfo, std::unique_ptr<PlatformEventCallback> callback,
101 bool useCurrentEventRunner, bool isSubAceContainer)
102 : instanceId_(instanceId), type_(type), isArkApp_(isArkApp), runtimeContext_(runtimeContext),
103 abilityInfo_(abilityInfo), useCurrentEventRunner_(useCurrentEventRunner), isSubContainer_(isSubAceContainer)
104 {
105 ACE_DCHECK(callback);
106 if (!isSubContainer_) {
107 InitializeTask();
108 }
109 platformEventCallback_ = std::move(callback);
110 useStageModel_ = true;
111 }
112
InitializeTask()113 void AceContainer::InitializeTask()
114 {
115 auto flutterTaskExecutor = Referenced::MakeRefPtr<FlutterTaskExecutor>();
116 flutterTaskExecutor->InitPlatformThread(useCurrentEventRunner_);
117 taskExecutor_ = flutterTaskExecutor;
118 // No need to create JS Thread for DECLARATIVE_JS
119 if (type_ == FrontendType::DECLARATIVE_JS) {
120 GetSettings().useUIAsJSThread = true;
121 } else {
122 flutterTaskExecutor->InitJsThread();
123 }
124 }
125
Initialize()126 void AceContainer::Initialize()
127 {
128 ContainerScope scope(instanceId_);
129 // For DECLARATIVE_JS frontend use UI as JS Thread, so InitializeFrontend after UI thread created.
130 if (type_ != FrontendType::DECLARATIVE_JS) {
131 InitializeFrontend();
132 }
133 }
134
Destroy()135 void AceContainer::Destroy()
136 {
137 ContainerScope scope(instanceId_);
138 if (pipelineContext_ && taskExecutor_) {
139 if (taskExecutor_) {
140 // 1. Destroy Pipeline on UI thread.
141 RefPtr<PipelineContext> context;
142 context.Swap(pipelineContext_);
143 taskExecutor_->PostTask([context]() { context->Destroy(); }, TaskExecutor::TaskType::UI);
144
145 if (isSubContainer_) {
146 // SubAcecontainer just return.
147 return;
148 }
149 // 2. Destroy Frontend on JS thread.
150 RefPtr<Frontend> frontend;
151 frontend_.Swap(frontend);
152 taskExecutor_->PostTask(
153 [frontend]() {
154 frontend->UpdateState(Frontend::State::ON_DESTROY);
155 frontend->Destroy();
156 },
157 TaskExecutor::TaskType::JS);
158 }
159 }
160 resRegister_.Reset();
161 assetManager_.Reset();
162 }
163
DestroyView()164 void AceContainer::DestroyView()
165 {
166 ContainerScope scope(instanceId_);
167 if (aceView_ != nullptr) {
168 delete aceView_;
169 aceView_ = nullptr;
170 }
171 }
172
InitializeFrontend()173 void AceContainer::InitializeFrontend()
174 {
175 auto aceAbility = aceAbility_.lock();
176 if (type_ == FrontendType::JS) {
177 frontend_ = Frontend::Create();
178 auto jsFrontend = AceType::DynamicCast<JsFrontend>(frontend_);
179 auto& loader = Framework::JsEngineLoader::Get(GetEngineSharedLibrary(isArkApp_));
180 auto jsEngine = loader.CreateJsEngine(instanceId_);
181 jsEngine->AddExtraNativeObject("ability", aceAbility.get());
182 EngineHelper::AddEngine(instanceId_, jsEngine);
183 jsFrontend->SetJsEngine(jsEngine);
184 jsFrontend->SetNeedDebugBreakPoint(AceApplicationInfo::GetInstance().IsNeedDebugBreakPoint());
185 jsFrontend->SetDebugVersion(AceApplicationInfo::GetInstance().IsDebugVersion());
186 } else if (type_ == FrontendType::JS_CARD) {
187 AceApplicationInfo::GetInstance().SetCardType();
188 frontend_ = AceType::MakeRefPtr<CardFrontend>();
189 } else if (type_ == FrontendType::DECLARATIVE_JS) {
190 if (!isSubContainer_) {
191 frontend_ = AceType::MakeRefPtr<DeclarativeFrontend>();
192 auto declarativeFrontend = AceType::DynamicCast<DeclarativeFrontend>(frontend_);
193 auto& loader = Framework::JsEngineLoader::GetDeclarative(GetDeclarativeSharedLibrary(isArkApp_));
194 RefPtr<Framework::JsEngine> jsEngine;
195 if (GetSettings().usingSharedRuntime) {
196 jsEngine = loader.CreateJsEngineUsingSharedRuntime(instanceId_, sharedRuntime_);
197 LOGI("Create engine using runtime, engine %{public}p", RawPtr(jsEngine));
198 } else {
199 jsEngine = loader.CreateJsEngine(instanceId_);
200 }
201 jsEngine->AddExtraNativeObject("ability", aceAbility.get());
202 EngineHelper::AddEngine(instanceId_, jsEngine);
203 declarativeFrontend->SetJsEngine(jsEngine);
204 declarativeFrontend->SetPageProfile(pageProfile_);
205 declarativeFrontend->SetNeedDebugBreakPoint(AceApplicationInfo::GetInstance().IsNeedDebugBreakPoint());
206 declarativeFrontend->SetDebugVersion(AceApplicationInfo::GetInstance().IsDebugVersion());
207 } else {
208 frontend_ = OHOS::Ace::Platform::AceContainer::GetContainer(parentId_)->GetFrontend();
209 return;
210 }
211 } else {
212 LOGE("Frontend type not supported");
213 EventReport::SendAppStartException(AppStartExcepType::FRONTEND_TYPE_ERR);
214 return;
215 }
216 ACE_DCHECK(frontend_);
217 auto abilityInfo = abilityInfo_.lock();
218 std::shared_ptr<AppExecFwk::AbilityInfo> info = aceAbility ? aceAbility->GetAbilityInfo() : abilityInfo;
219 if (info && info->isLauncherAbility) {
220 frontend_->DisallowPopLastPage();
221 }
222 frontend_->Initialize(type_, taskExecutor_);
223 }
224
GetContainer(int32_t instanceId)225 RefPtr<AceContainer> AceContainer::GetContainer(int32_t instanceId)
226 {
227 auto container = AceEngine::Get().GetContainer(instanceId);
228 if (container != nullptr) {
229 auto aceContainer = AceType::DynamicCast<AceContainer>(container);
230 return aceContainer;
231 } else {
232 return nullptr;
233 }
234 }
235
OnBackPressed(int32_t instanceId)236 bool AceContainer::OnBackPressed(int32_t instanceId)
237 {
238 auto container = AceEngine::Get().GetContainer(instanceId);
239 if (!container) {
240 return false;
241 }
242
243 // When the container is for menu, it need close the menu first.
244 if (container->IsSubContainer()) {
245 SubwindowManager::GetInstance()->CloseMenu();
246 return true;
247 }
248 ContainerScope scope(instanceId);
249 auto context = container->GetPipelineContext();
250 if (!context) {
251 return false;
252 }
253 return context->CallRouterBackToPopPage();
254 }
255
OnShow(int32_t instanceId)256 void AceContainer::OnShow(int32_t instanceId)
257 {
258 auto container = AceEngine::Get().GetContainer(instanceId);
259 if (!container) {
260 return;
261 }
262
263 ContainerScope scope(instanceId);
264 auto front = container->GetFrontend();
265
266 // When it is subContainer, no need call the OnShow, because the frontend is the same the parent container.
267 if (front && !container->IsSubContainer()) {
268 front->UpdateState(Frontend::State::ON_SHOW);
269 front->OnShow();
270 }
271 auto context = container->GetPipelineContext();
272 if (!context) {
273 return;
274 }
275 context->OnShow();
276 }
277
OnHide(int32_t instanceId)278 void AceContainer::OnHide(int32_t instanceId)
279 {
280 auto container = AceEngine::Get().GetContainer(instanceId);
281 if (!container) {
282 return;
283 }
284 ContainerScope scope(instanceId);
285 auto front = container->GetFrontend();
286
287 // When it is subContainer, no need call the OnHide, because the frontend is the same the parent container.
288 if (front && !container->IsSubContainer()) {
289 front->UpdateState(Frontend::State::ON_HIDE);
290 front->OnHide();
291 auto taskExecutor = container->GetTaskExecutor();
292 if (taskExecutor) {
293 taskExecutor->PostTask([front]() { front->TriggerGarbageCollection(); }, TaskExecutor::TaskType::JS);
294 }
295 }
296 auto context = container->GetPipelineContext();
297 if (!context) {
298 return;
299 }
300 context->OnHide();
301 }
302
OnActive(int32_t instanceId)303 void AceContainer::OnActive(int32_t instanceId)
304 {
305 auto container = AceEngine::Get().GetContainer(instanceId);
306 if (!container) {
307 LOGE("container is null, OnActive failed.");
308 return;
309 }
310
311 ContainerScope scope(instanceId);
312 auto front = container->GetFrontend();
313
314 // When it is subContainer, no need call the OnActive, because the frontend is the same the parent container.
315 if (front && !container->IsSubContainer()) {
316 front->OnActive();
317 }
318 // TODO: remove it after ability fix onshow lifecyle.
319 auto context = container->GetPipelineContext();
320 if (!context) {
321 return;
322 }
323 }
324
OnInactive(int32_t instanceId)325 void AceContainer::OnInactive(int32_t instanceId)
326 {
327 auto container = AceEngine::Get().GetContainer(instanceId);
328 if (!container) {
329 return;
330 }
331 ContainerScope scope(instanceId);
332 auto front = container->GetFrontend();
333
334 // When it is subContainer, no need call the OnInactive, because the frontend is the same the parent container.
335 if (front && !container->IsSubContainer()) {
336 front->OnInactive();
337 }
338 // TODO: remove it after ability fix onshow lifecyle.
339 auto context = container->GetPipelineContext();
340 if (!context) {
341 return;
342 }
343 context->GetTaskExecutor()->PostTask([context]() { context->RootLostFocus(); }, TaskExecutor::TaskType::UI);
344 }
345
OnStartContinuation(int32_t instanceId)346 bool AceContainer::OnStartContinuation(int32_t instanceId)
347 {
348 auto container = AceEngine::Get().GetContainer(instanceId);
349 if (!container) {
350 LOGI("container is null, OnStartContinuation failed.");
351 return false;
352 }
353
354 ContainerScope scope(instanceId);
355 auto front = container->GetFrontend();
356 if (!front) {
357 LOGI("front is null, OnStartContinuation failed.");
358 return false;
359 }
360 return front->OnStartContinuation();
361 }
362
OnSaveData(int32_t instanceId)363 std::string AceContainer::OnSaveData(int32_t instanceId)
364 {
365 std::string result = "false";
366 auto container = AceEngine::Get().GetContainer(instanceId);
367 if (!container) {
368 LOGI("container is null, OnSaveData failed.");
369 return result;
370 }
371
372 ContainerScope scope(instanceId);
373 auto front = container->GetFrontend();
374 if (!front) {
375 LOGI("front is null, OnSaveData failed.");
376 return result;
377 }
378 front->OnSaveData(result);
379 return result;
380 }
381
OnRestoreData(int32_t instanceId,const std::string & data)382 bool AceContainer::OnRestoreData(int32_t instanceId, const std::string& data)
383 {
384 auto container = AceEngine::Get().GetContainer(instanceId);
385 if (!container) {
386 LOGI("container is null, OnRestoreData failed.");
387 return false;
388 }
389
390 ContainerScope scope(instanceId);
391 auto front = container->GetFrontend();
392 if (!front) {
393 LOGI("front is null, OnRestoreData failed.");
394 return false;
395 }
396 return front->OnRestoreData(data);
397 }
398
OnCompleteContinuation(int32_t instanceId,int result)399 void AceContainer::OnCompleteContinuation(int32_t instanceId, int result)
400 {
401 auto container = AceEngine::Get().GetContainer(instanceId);
402 if (!container) {
403 LOGI("container is null, OnCompleteContinuation failed.");
404 return;
405 }
406
407 ContainerScope scope(instanceId);
408 auto front = container->GetFrontend();
409 if (!front) {
410 LOGI("front is null, OnCompleteContinuation failed.");
411 return;
412 }
413 front->OnCompleteContinuation(result);
414 }
415
OnRemoteTerminated(int32_t instanceId)416 void AceContainer::OnRemoteTerminated(int32_t instanceId)
417 {
418 auto container = AceEngine::Get().GetContainer(instanceId);
419 if (!container) {
420 LOGI("container is null, OnRemoteTerminated failed.");
421 return;
422 }
423
424 ContainerScope scope(instanceId);
425 auto front = container->GetFrontend();
426 if (!front) {
427 LOGI("front is null, OnRemoteTerminated failed.");
428 return;
429 }
430 front->OnRemoteTerminated();
431 }
432
OnConfigurationUpdated(int32_t instanceId,const std::string & configuration)433 void AceContainer::OnConfigurationUpdated(int32_t instanceId, const std::string& configuration)
434 {
435 auto container = AceEngine::Get().GetContainer(instanceId);
436 if (!container) {
437 LOGI("container is null, OnConfigurationUpdated failed.");
438 return;
439 }
440
441 ContainerScope scope(instanceId);
442 auto front = container->GetFrontend();
443 if (!front) {
444 LOGI("front is null, OnConfigurationUpdated failed.");
445 return;
446 }
447 front->OnConfigurationUpdated(configuration);
448 }
449
OnNewRequest(int32_t instanceId,const std::string & data)450 void AceContainer::OnNewRequest(int32_t instanceId, const std::string& data)
451 {
452 auto container = AceEngine::Get().GetContainer(instanceId);
453 if (!container) {
454 return;
455 }
456
457 ContainerScope scope(instanceId);
458 auto front = container->GetFrontend();
459 if (front) {
460 front->OnNewRequest(data);
461 }
462 }
463
InitializeCallback()464 void AceContainer::InitializeCallback()
465 {
466 ACE_FUNCTION_TRACE();
467
468 ACE_DCHECK(aceView_ && taskExecutor_ && pipelineContext_);
469 auto&& touchEventCallback = [context = pipelineContext_, id = instanceId_](const TouchEvent& event) {
470 ContainerScope scope(id);
471 context->GetTaskExecutor()->PostTask(
472 [context, event]() {
473 context->OnTouchEvent(event);
474 context->NotifyDispatchTouchEventDismiss(event);
475 },
476 TaskExecutor::TaskType::UI);
477 };
478 aceView_->RegisterTouchEventCallback(touchEventCallback);
479
480 auto&& keyEventCallback = [context = pipelineContext_, id = instanceId_](const KeyEvent& event) {
481 ContainerScope scope(id);
482 bool result = false;
483 context->GetTaskExecutor()->PostSyncTask(
484 [context, event, &result]() { result = context->OnKeyEvent(event); }, TaskExecutor::TaskType::UI);
485 return result;
486 };
487 aceView_->RegisterKeyEventCallback(keyEventCallback);
488
489 auto&& mouseEventCallback = [context = pipelineContext_, id = instanceId_](const MouseEvent& event) {
490 ContainerScope scope(id);
491 context->GetTaskExecutor()->PostTask(
492 [context, event]() { context->OnMouseEvent(event); }, TaskExecutor::TaskType::UI);
493 };
494 aceView_->RegisterMouseEventCallback(mouseEventCallback);
495
496 auto&& axisEventCallback = [context = pipelineContext_, id = instanceId_](const AxisEvent& event) {
497 ContainerScope scope(id);
498 context->GetTaskExecutor()->PostTask(
499 [context, event]() { context->OnAxisEvent(event); }, TaskExecutor::TaskType::UI);
500 };
501 aceView_->RegisterAxisEventCallback(axisEventCallback);
502
503 auto&& rotationEventCallback = [context = pipelineContext_, id = instanceId_](const RotationEvent& event) {
504 ContainerScope scope(id);
505 bool result = false;
506 context->GetTaskExecutor()->PostSyncTask(
507 [context, event, &result]() { result = context->OnRotationEvent(event); }, TaskExecutor::TaskType::UI);
508 return result;
509 };
510 aceView_->RegisterRotationEventCallback(rotationEventCallback);
511
512 auto&& viewChangeCallback = [context = pipelineContext_, id = instanceId_](
513 int32_t width, int32_t height, WindowSizeChangeReason type) {
514 ContainerScope scope(id);
515 ACE_SCOPED_TRACE("ViewChangeCallback(%d, %d)", width, height);
516 context->GetTaskExecutor()->PostTask(
517 [context, width, height, type]() { context->OnSurfaceChanged(width, height, type); },
518 TaskExecutor::TaskType::UI);
519 };
520 aceView_->RegisterViewChangeCallback(viewChangeCallback);
521
522 auto&& densityChangeCallback = [context = pipelineContext_, id = instanceId_](double density) {
523 ContainerScope scope(id);
524 ACE_SCOPED_TRACE("DensityChangeCallback(%lf)", density);
525 context->GetTaskExecutor()->PostTask(
526 [context, density]() { context->OnSurfaceDensityChanged(density); }, TaskExecutor::TaskType::UI);
527 };
528 aceView_->RegisterDensityChangeCallback(densityChangeCallback);
529
530 auto&& systemBarHeightChangeCallback = [context = pipelineContext_, id = instanceId_](
531 double statusBar, double navigationBar) {
532 ContainerScope scope(id);
533 ACE_SCOPED_TRACE("SystemBarHeightChangeCallback(%lf, %lf)", statusBar, navigationBar);
534 context->GetTaskExecutor()->PostTask(
535 [context, statusBar, navigationBar]() { context->OnSystemBarHeightChanged(statusBar, navigationBar); },
536 TaskExecutor::TaskType::UI);
537 };
538 aceView_->RegisterSystemBarHeightChangeCallback(systemBarHeightChangeCallback);
539
540 auto&& surfaceDestroyCallback = [context = pipelineContext_, id = instanceId_]() {
541 ContainerScope scope(id);
542 context->GetTaskExecutor()->PostTask(
543 [context]() { context->OnSurfaceDestroyed(); }, TaskExecutor::TaskType::UI);
544 };
545 aceView_->RegisterSurfaceDestroyCallback(surfaceDestroyCallback);
546
547 auto&& dragEventCallback = [context = pipelineContext_, id = instanceId_](
548 int32_t x, int32_t y, const DragEventAction& action) {
549 ContainerScope scope(id);
550 context->GetTaskExecutor()->PostTask(
551 [context, x, y, action]() { context->OnDragEvent(x, y, action); }, TaskExecutor::TaskType::UI);
552 };
553 aceView_->RegisterDragEventCallback(dragEventCallback);
554 }
555
CreateContainer(int32_t instanceId,FrontendType type,bool isArkApp,std::string instanceName,std::shared_ptr<OHOS::AppExecFwk::Ability> aceAbility,std::unique_ptr<PlatformEventCallback> callback,bool useCurrentEventRunner)556 void AceContainer::CreateContainer(int32_t instanceId, FrontendType type, bool isArkApp, std::string instanceName,
557 std::shared_ptr<OHOS::AppExecFwk::Ability> aceAbility, std::unique_ptr<PlatformEventCallback> callback,
558 bool useCurrentEventRunner)
559 {
560 auto aceContainer = AceType::MakeRefPtr<AceContainer>(
561 instanceId, type, isArkApp, aceAbility, std::move(callback), useCurrentEventRunner);
562 AceEngine::Get().AddContainer(instanceId, aceContainer);
563
564 HdcRegister::Get().StartHdcRegister(instanceId);
565 ConnectServerManager::Get().AddInstance(instanceId);
566 aceContainer->Initialize();
567 ContainerScope scope(instanceId);
568 auto front = aceContainer->GetFrontend();
569 if (front) {
570 front->UpdateState(Frontend::State::ON_CREATE);
571 front->SetJsMessageDispatcher(aceContainer);
572 }
573
574 auto jsFront = AceType::DynamicCast<JsFrontend>(front);
575 if (!jsFront) {
576 return;
577 }
578 jsFront->SetInstanceName(instanceName.c_str());
579 }
580
DestroyContainer(int32_t instanceId)581 void AceContainer::DestroyContainer(int32_t instanceId)
582 {
583 auto container = AceEngine::Get().GetContainer(instanceId);
584 if (!container) {
585 LOGE("no AceContainer with id %{private}d in AceEngine", instanceId);
586 return;
587 }
588 HdcRegister::Get().StopHdcRegister(instanceId);
589 container->Destroy();
590 auto taskExecutor = container->GetTaskExecutor();
591 if (taskExecutor) {
592 taskExecutor->PostSyncTask([] { LOGI("Wait UI thread..."); }, TaskExecutor::TaskType::UI);
593 taskExecutor->PostSyncTask([] { LOGI("Wait JS thread..."); }, TaskExecutor::TaskType::JS);
594 }
595 container->DestroyView(); // Stop all threads(ui,gpu,io) for current ability.
596 if (taskExecutor) {
597 taskExecutor->PostTask([instanceId] {
598 LOGI("Remove on Platform thread...");
599 EngineHelper::RemoveEngine(instanceId);
600 AceEngine::Get().RemoveContainer(instanceId);
601 ConnectServerManager::Get().RemoveInstance(instanceId);
602 }, TaskExecutor::TaskType::PLATFORM);
603 }
604 }
605
SetView(AceView * view,double density,int32_t width,int32_t height,int32_t windowId,UIEnvCallback callback)606 void AceContainer::SetView(
607 AceView* view, double density, int32_t width, int32_t height, int32_t windowId, UIEnvCallback callback)
608 {
609 if (view == nullptr) {
610 return;
611 }
612
613 auto container = AceType::DynamicCast<AceContainer>(AceEngine::Get().GetContainer(view->GetInstanceId()));
614 if (!container) {
615 return;
616 }
617 auto platformWindow = PlatformWindow::Create(view);
618 if (!platformWindow) {
619 LOGE("Create PlatformWindow failed!");
620 return;
621 }
622 std::unique_ptr<Window> window = std::make_unique<Window>(std::move(platformWindow));
623 container->AttachView(std::move(window), view, density, width, height, windowId, callback);
624 }
625
SetUIWindow(int32_t instanceId,sptr<OHOS::Rosen::Window> uiWindow)626 void AceContainer::SetUIWindow(int32_t instanceId, sptr<OHOS::Rosen::Window> uiWindow)
627 {
628 if (uiWindow == nullptr) {
629 return;
630 }
631
632 auto container = AceType::DynamicCast<AceContainer>(AceEngine::Get().GetContainer(instanceId));
633 if (!container) {
634 return;
635 }
636 container->SetUIWindowInner(uiWindow);
637 }
638
GetUIWindow(int32_t instanceId)639 sptr<OHOS::Rosen::Window> AceContainer::GetUIWindow(int32_t instanceId)
640 {
641 auto container = AceType::DynamicCast<AceContainer>(AceEngine::Get().GetContainer(instanceId));
642 if (!container) {
643 return nullptr;
644 }
645 return container->GetUIWindowInner();
646 }
647
GetAbility(int32_t instanceId)648 OHOS::AppExecFwk::Ability* AceContainer::GetAbility(int32_t instanceId)
649 {
650 auto container = AceType::DynamicCast<AceContainer>(AceEngine::Get().GetContainer(instanceId));
651 if (!container) {
652 return nullptr;
653 }
654 return container->GetAbilityInner().lock().get();
655 }
656
RunPage(int32_t instanceId,int32_t pageId,const std::string & content,const std::string & params)657 bool AceContainer::RunPage(int32_t instanceId, int32_t pageId, const std::string& content, const std::string& params)
658 {
659 auto container = AceEngine::Get().GetContainer(instanceId);
660 if (!container) {
661 return false;
662 }
663 ContainerScope scope(instanceId);
664 auto front = container->GetFrontend();
665 if (front) {
666 LOGI("RunPage content=[%{private}s]", content.c_str());
667 front->RunPage(pageId, content, params);
668 return true;
669 }
670 return false;
671 }
672
PushPage(int32_t instanceId,const std::string & content,const std::string & params)673 bool AceContainer::PushPage(int32_t instanceId, const std::string& content, const std::string& params)
674 {
675 auto container = AceEngine::Get().GetContainer(instanceId);
676 if (!container) {
677 return false;
678 }
679 ContainerScope scope(instanceId);
680 auto front = container->GetFrontend();
681 if (front) {
682 front->PushPage(content, params);
683 return true;
684 }
685 return false;
686 }
687
UpdatePage(int32_t instanceId,int32_t pageId,const std::string & content)688 bool AceContainer::UpdatePage(int32_t instanceId, int32_t pageId, const std::string& content)
689 {
690 auto container = AceEngine::Get().GetContainer(instanceId);
691 if (!container) {
692 return false;
693 }
694 ContainerScope scope(instanceId);
695 auto context = container->GetPipelineContext();
696 if (!context) {
697 return false;
698 }
699 return context->CallRouterBackToPopPage();
700 }
701
Dispatch(const std::string & group,std::vector<uint8_t> && data,int32_t id,bool replyToComponent) const702 void AceContainer::Dispatch(
703 const std::string& group, std::vector<uint8_t>&& data, int32_t id, bool replyToComponent) const
704 {
705 return;
706 }
707
DispatchPluginError(int32_t callbackId,int32_t errorCode,std::string && errorMessage) const708 void AceContainer::DispatchPluginError(int32_t callbackId, int32_t errorCode, std::string&& errorMessage) const
709 {
710 auto front = GetFrontend();
711 if (!front) {
712 LOGE("the front is nullptr");
713 return;
714 }
715
716 ContainerScope scope(instanceId_);
717 taskExecutor_->PostTask(
718 [front, callbackId, errorCode, errorMessage = std::move(errorMessage)]() mutable {
719 front->TransferJsPluginGetError(callbackId, errorCode, std::move(errorMessage));
720 },
721 TaskExecutor::TaskType::BACKGROUND);
722 }
723
Dump(const std::vector<std::string> & params)724 bool AceContainer::Dump(const std::vector<std::string>& params)
725 {
726 ContainerScope scope(instanceId_);
727 if (aceView_ && aceView_->Dump(params)) {
728 return true;
729 }
730
731 if (pipelineContext_) {
732 pipelineContext_->Dump(params);
733 return true;
734 }
735 return false;
736 }
737
TriggerGarbageCollection()738 void AceContainer::TriggerGarbageCollection()
739 {
740 ContainerScope scope(instanceId_);
741 #if !defined(OHOS_PLATFORM) || !defined(ENABLE_NATIVE_VIEW)
742 // GPU and IO thread is standalone while disable native view
743 taskExecutor_->PostTask([] { PurgeMallocCache(); }, TaskExecutor::TaskType::GPU);
744 taskExecutor_->PostTask([] { PurgeMallocCache(); }, TaskExecutor::TaskType::IO);
745 #endif
746 taskExecutor_->PostTask([] { PurgeMallocCache(); }, TaskExecutor::TaskType::UI);
747 taskExecutor_->PostTask(
748 [frontend = WeakPtr<Frontend>(frontend_)] {
749 auto sp = frontend.Upgrade();
750 if (sp) {
751 sp->TriggerGarbageCollection();
752 }
753 PurgeMallocCache();
754 },
755 TaskExecutor::TaskType::JS);
756 }
757
SetContentStorage(NativeReference * storage,NativeReference * context)758 void AceContainer::SetContentStorage(NativeReference* storage, NativeReference* context)
759 {
760 auto declarativeFrontend = AceType::DynamicCast<DeclarativeFrontend>(frontend_);
761 auto jsEngine = declarativeFrontend->GetJsEngine();
762 if (context) {
763 jsEngine->SetContext(instanceId_, context);
764 }
765 if (storage) {
766 jsEngine->SetContentStorage(instanceId_, storage);
767 }
768 }
769
AddAssetPath(int32_t instanceId,const std::string & packagePath,const std::vector<std::string> & paths)770 void AceContainer::AddAssetPath(
771 int32_t instanceId, const std::string& packagePath, const std::vector<std::string>& paths)
772 {
773 auto container = AceType::DynamicCast<AceContainer>(AceEngine::Get().GetContainer(instanceId));
774 if (!container) {
775 return;
776 }
777
778 RefPtr<FlutterAssetManager> flutterAssetManager;
779 if (container->assetManager_) {
780 flutterAssetManager = AceType::DynamicCast<FlutterAssetManager>(container->assetManager_);
781 } else {
782 flutterAssetManager = Referenced::MakeRefPtr<FlutterAssetManager>();
783 container->assetManager_ = flutterAssetManager;
784 if (container->type_ != FrontendType::DECLARATIVE_JS) {
785 container->frontend_->SetAssetManager(flutterAssetManager);
786 }
787 }
788 if (flutterAssetManager && !packagePath.empty()) {
789 auto assetProvider = AceType::MakeRefPtr<FileAssetProvider>();
790 if (assetProvider->Initialize(packagePath, paths)) {
791 LOGI("Push AssetProvider to queue.");
792 flutterAssetManager->PushBack(std::move(assetProvider));
793 }
794 }
795 }
796
AddLibPath(int32_t instanceId,const std::string & libPath)797 void AceContainer::AddLibPath(int32_t instanceId, const std::string& libPath)
798 {
799 auto container = AceType::DynamicCast<AceContainer>(AceEngine::Get().GetContainer(instanceId));
800 if (!container) {
801 return;
802 }
803
804 RefPtr<FlutterAssetManager> flutterAssetManager;
805 if (container->assetManager_) {
806 flutterAssetManager = AceType::DynamicCast<FlutterAssetManager>(container->assetManager_);
807 } else {
808 flutterAssetManager = Referenced::MakeRefPtr<FlutterAssetManager>();
809 container->assetManager_ = flutterAssetManager;
810 if (container->type_ != FrontendType::DECLARATIVE_JS) {
811 container->frontend_->SetAssetManager(flutterAssetManager);
812 }
813 }
814 if (flutterAssetManager) {
815 flutterAssetManager->SetLibPath(libPath);
816 }
817 }
818
AttachView(std::unique_ptr<Window> window,AceView * view,double density,int32_t width,int32_t height,int32_t windowId,UIEnvCallback callback)819 void AceContainer::AttachView(std::unique_ptr<Window> window, AceView* view, double density, int32_t width,
820 int32_t height, int32_t windowId, UIEnvCallback callback)
821 {
822 aceView_ = view;
823 auto instanceId = aceView_->GetInstanceId();
824 auto flutterTaskExecutor = AceType::DynamicCast<FlutterTaskExecutor>(taskExecutor_);
825 if (!isSubContainer_) {
826 auto state = flutter::UIDartState::Current()->GetStateById(instanceId);
827 ACE_DCHECK(state != nullptr);
828 flutterTaskExecutor->InitOtherThreads(state->GetTaskRunners());
829 if (GetSettings().usePlatformAsUIThread) {
830 ContainerScope::SetScopeNotify([](int32_t id) { flutter::UIDartState::Current()->SetCurInstance(id); });
831 }
832 }
833 ContainerScope scope(instanceId);
834 if (type_ == FrontendType::DECLARATIVE_JS) {
835 // For DECLARATIVE_JS frontend display UI in JS thread temporarily.
836 flutterTaskExecutor->InitJsThread(false);
837 InitializeFrontend();
838 auto front = GetFrontend();
839 if (front) {
840 front->UpdateState(Frontend::State::ON_CREATE);
841 front->SetJsMessageDispatcher(AceType::Claim(this));
842 front->SetAssetManager(assetManager_);
843 }
844 } else if (type_ != FrontendType::JS_CARD) {
845 aceView_->SetCreateTime(createTime_);
846 }
847 resRegister_ = aceView_->GetPlatformResRegister();
848 pipelineContext_ = AceType::MakeRefPtr<PipelineContext>(
849 std::move(window), taskExecutor_, assetManager_, resRegister_, frontend_, instanceId);
850 pipelineContext_->SetRootSize(density, width, height);
851 pipelineContext_->SetTextFieldManager(AceType::MakeRefPtr<TextFieldManager>());
852 pipelineContext_->SetIsRightToLeft(AceApplicationInfo::GetInstance().IsRightToLeft());
853 pipelineContext_->SetWindowModal(windowModal_);
854 pipelineContext_->SetDrawDelegate(aceView_->GetDrawDelegate());
855 pipelineContext_->SetWindowId(windowId);
856 if (isSubContainer_) {
857 pipelineContext_->SetIsSubPipeline(true);
858 }
859 InitializeCallback();
860
861 auto&& finishEventHandler = [weak = WeakClaim(this), instanceId] {
862 auto container = weak.Upgrade();
863 if (!container) {
864 LOGE("FinishEventHandler container is null!");
865 return;
866 }
867 ContainerScope scope(instanceId);
868 auto context = container->GetPipelineContext();
869 if (!context) {
870 LOGE("FinishEventHandler context is null!");
871 return;
872 }
873 context->GetTaskExecutor()->PostTask(
874 [weak = WeakPtr<AceContainer>(container)] {
875 auto container = weak.Upgrade();
876 if (!container) {
877 LOGE("Finish task, container is null!");
878 return;
879 }
880 container->OnFinish();
881 },
882 TaskExecutor::TaskType::PLATFORM);
883 };
884 pipelineContext_->SetFinishEventHandler(finishEventHandler);
885
886 auto&& setStatusBarEventHandler = [weak = WeakClaim(this), instanceId](const Color& color) {
887 auto container = weak.Upgrade();
888 if (!container) {
889 LOGE("StatusBarEventHandler container is null!");
890 return;
891 }
892 ContainerScope scope(instanceId);
893 auto context = container->GetPipelineContext();
894 if (!context) {
895 LOGE("StatusBarEventHandler context is null!");
896 return;
897 }
898 context->GetTaskExecutor()->PostTask(
899 [weak, color = color.GetValue()]() {
900 auto container = weak.Upgrade();
901 if (!container) {
902 LOGE("StatusBarEventHandler container is null!");
903 return;
904 }
905 if (container->platformEventCallback_) {
906 container->platformEventCallback_->OnStatusBarBgColorChanged(color);
907 }
908 },
909 TaskExecutor::TaskType::PLATFORM);
910 };
911 pipelineContext_->SetStatusBarEventHandler(setStatusBarEventHandler);
912
913 taskExecutor_->PostTask([] { FrameReport::GetInstance().Init(); }, TaskExecutor::TaskType::UI);
914
915 ThemeConstants::InitDeviceType();
916 // Load custom style at UI thread before frontend attach, to make sure style can be loaded before building dom tree.
917 auto themeManager = AceType::MakeRefPtr<ThemeManager>();
918 if (themeManager) {
919 pipelineContext_->SetThemeManager(themeManager);
920 // Init resource
921 themeManager->InitResource(resourceInfo_);
922 taskExecutor_->PostTask(
923 [themeManager, assetManager = assetManager_, colorScheme = colorScheme_] {
924 themeManager->SetColorScheme(colorScheme);
925 themeManager->LoadCustomTheme(assetManager);
926 },
927 TaskExecutor::TaskType::UI);
928 }
929 taskExecutor_->PostTask(
930 [context = pipelineContext_, callback, isSubContainer = isSubContainer_]() {
931 if (callback != nullptr) {
932 callback(context);
933 }
934 if (!isSubContainer) {
935 context->SetupRootElement();
936 }
937 },
938 TaskExecutor::TaskType::UI);
939 aceView_->Launch();
940
941 // Only MainWindow instance will be registered to watch dog.
942 if (!isSubContainer_) {
943 if (!AceApplicationInfo::GetInstance().IsNeedDebugBreakPoint()) {
944 AceEngine::Get().RegisterToWatchDog(instanceId, taskExecutor_, GetSettings().useUIAsJSThread);
945 }
946 frontend_->AttachPipelineContext(pipelineContext_);
947 } else {
948 auto declarativeFrontend = AceType::DynamicCast<DeclarativeFrontend>(frontend_);
949 if (declarativeFrontend) {
950 declarativeFrontend->AttachSubPipelineContext(pipelineContext_);
951 }
952 return;
953 }
954
955 auto dataAbilityHelperImpl = [ability = GetAbilityInner(), runtimeContext = runtimeContext_,
956 useStageModel = useStageModel_]() {
957 return AceType::MakeRefPtr<DataAbilityHelperStandard>(ability.lock(), runtimeContext.lock(), useStageModel);
958 };
959 auto dataProviderManager = MakeRefPtr<DataProviderManagerStandard>(dataAbilityHelperImpl);
960 pipelineContext_->SetDataProviderManager(dataProviderManager);
961 }
962
SetUIWindowInner(sptr<OHOS::Rosen::Window> uiWindow)963 void AceContainer::SetUIWindowInner(sptr<OHOS::Rosen::Window> uiWindow)
964 {
965 uiWindow_ = uiWindow;
966 }
967
GetUIWindowInner() const968 sptr<OHOS::Rosen::Window> AceContainer::GetUIWindowInner() const
969 {
970 return uiWindow_;
971 }
972
GetAbilityInner() const973 std::weak_ptr<OHOS::AppExecFwk::Ability> AceContainer::GetAbilityInner() const
974 {
975 return aceAbility_;
976 }
977
SetFontScale(int32_t instanceId,float fontScale)978 void AceContainer::SetFontScale(int32_t instanceId, float fontScale)
979 {
980 auto container = AceEngine::Get().GetContainer(instanceId);
981 if (!container) {
982 return;
983 }
984 ContainerScope scope(instanceId);
985 auto pipelineContext = container->GetPipelineContext();
986 if (!pipelineContext) {
987 LOGE("fail to set font style due to context is null");
988 return;
989 }
990 pipelineContext->SetFontScale(fontScale);
991 }
992
SetWindowStyle(int32_t instanceId,WindowModal windowModal,ColorScheme colorScheme)993 void AceContainer::SetWindowStyle(int32_t instanceId, WindowModal windowModal, ColorScheme colorScheme)
994 {
995 auto container = AceType::DynamicCast<AceContainer>(AceEngine::Get().GetContainer(instanceId));
996 if (!container) {
997 return;
998 }
999 ContainerScope scope(instanceId);
1000 container->SetWindowModal(windowModal);
1001 container->SetColorScheme(colorScheme);
1002 }
1003
SetDialogCallback(int32_t instanceId,FrontendDialogCallback callback)1004 void AceContainer::SetDialogCallback(int32_t instanceId, FrontendDialogCallback callback)
1005 {
1006 auto container = AceEngine::Get().GetContainer(instanceId);
1007 if (!container) {
1008 return;
1009 }
1010 auto front = container->GetFrontend();
1011 if (front && front->GetType() == FrontendType::JS) {
1012 front->SetDialogCallback(callback);
1013 }
1014 }
1015
RestoreRouterStack(int32_t instanceId,const std::string & contentInfo)1016 std::string AceContainer::RestoreRouterStack(int32_t instanceId, const std::string& contentInfo)
1017 {
1018 auto container = AceEngine::Get().GetContainer(instanceId);
1019 if (!container) {
1020 return "";
1021 }
1022 ContainerScope scope(instanceId);
1023 auto front = container->GetFrontend();
1024 if (front) {
1025 return front->RestoreRouterStack(contentInfo);
1026 } else {
1027 return "";
1028 }
1029 }
1030
GetContentInfo(int32_t instanceId)1031 std::string AceContainer::GetContentInfo(int32_t instanceId)
1032 {
1033 auto container = AceEngine::Get().GetContainer(instanceId);
1034 if (!container) {
1035 return "";
1036 }
1037 ContainerScope scope(instanceId);
1038 auto front = container->GetFrontend();
1039 if (front) {
1040 return front->GetContentInfo();
1041 } else {
1042 return "";
1043 }
1044 }
1045
InitializeSubContainer(int32_t parentContainerId)1046 void AceContainer::InitializeSubContainer(int32_t parentContainerId)
1047 {
1048 auto taskExec = AceEngine::Get().GetContainer(parentContainerId)->GetTaskExecutor();
1049 taskExecutor_ = AceType::DynamicCast<FlutterTaskExecutor>(std::move(taskExec));
1050 GetSettings().useUIAsJSThread = true;
1051 }
1052 } // namespace OHOS::Ace::Platform
1053