• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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