• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 "adapter/preview/entrance/ace_container.h"
17 
18 #include <functional>
19 
20 #ifndef ENABLE_ROSEN_BACKEND
21 #include "flutter/lib/ui/ui_dart_state.h"
22 
23 #include "adapter/preview/entrance/dir_asset_provider.h"
24 #include "core/common/flutter/flutter_asset_manager.h"
25 #include "core/common/flutter/flutter_task_executor.h"
26 #else // ENABLE_ROSEN_BACKEND == true
27 #include "adapter/preview/entrance/rs_dir_asset_provider.h"
28 #include "core/common/flutter/flutter_task_executor.h"
29 #include "core/common/rosen/rosen_asset_manager.h"
30 #endif
31 
32 #include "native_engine/native_engine.h"
33 
34 #include "adapter/preview/entrance/ace_application_info.h"
35 #include "adapter/preview/osal/stage_card_parser.h"
36 #include "base/log/ace_trace.h"
37 #include "base/log/event_report.h"
38 #include "base/log/log.h"
39 #include "base/utils/system_properties.h"
40 #include "base/utils/utils.h"
41 #include "bridge/card_frontend/card_frontend.h"
42 #include "bridge/card_frontend/card_frontend_declarative.h"
43 #include "bridge/card_frontend/form_frontend_declarative.h"
44 #include "bridge/common/utils/engine_helper.h"
45 #include "bridge/declarative_frontend/declarative_frontend.h"
46 #include "bridge/js_frontend/engine/common/js_engine_loader.h"
47 #include "bridge/js_frontend/js_frontend.h"
48 #include "core/common/ace_engine.h"
49 #include "core/common/ace_view.h"
50 #include "core/common/container_scope.h"
51 #include "core/common/platform_bridge.h"
52 #include "core/common/platform_window.h"
53 #include "core/common/text_field_manager.h"
54 #include "core/common/window.h"
55 #include "core/components/theme/app_theme.h"
56 #include "core/components/theme/theme_constants.h"
57 #include "core/components/theme/theme_manager_impl.h"
58 #include "core/components_ng/pattern/text_field/text_field_manager.h"
59 #include "core/components_ng/render/adapter/rosen_window.h"
60 #include "core/pipeline/base/element.h"
61 #include "core/pipeline/pipeline_context.h"
62 #include "core/pipeline_ng/pipeline_context.h"
63 #include "previewer/include/window.h"
64 
65 namespace OHOS::Ace::Platform {
66 namespace {
67 const char LANGUAGE_TAG[] = "language";
68 const char COUNTRY_TAG[] = "countryOrRegion";
69 const char DIRECTION_TAG[] = "dir";
70 const char UNICODE_SETTING_TAG[] = "unicodeSetting";
71 const char LOCALE_DIR_LTR[] = "ltr";
72 const char LOCALE_DIR_RTL[] = "rtl";
73 const char LOCALE_KEY[] = "locale";
74 } // namespace
75 
76 std::once_flag AceContainer::onceFlag_;
77 bool AceContainer::isComponentMode_ = false;
AceContainer(int32_t instanceId,FrontendType type,bool useNewPipeline,bool useCurrentEventRunner)78 AceContainer::AceContainer(int32_t instanceId, FrontendType type, bool useNewPipeline, bool useCurrentEventRunner)
79     : instanceId_(instanceId), messageBridge_(AceType::MakeRefPtr<PlatformBridge>()), type_(type)
80 {
81     LOGI("Using %{public}s pipeline context ...", (useNewPipeline ? "new" : "old"));
82     if (useNewPipeline) {
83         SetUseNewPipeline();
84     }
85     ThemeConstants::InitDeviceType();
86 #ifndef ENABLE_ROSEN_BACKEND
87     auto state = flutter::UIDartState::Current()->GetStateById(instanceId);
88     auto flutterTaskExecutor = Referenced::MakeRefPtr<FlutterTaskExecutor>(state->GetTaskRunners());
89     if (type_ != FrontendType::DECLARATIVE_JS && type_ != FrontendType::ETS_CARD) {
90         flutterTaskExecutor->InitJsThread();
91     }
92 #else
93     auto flutterTaskExecutor = Referenced::MakeRefPtr<FlutterTaskExecutor>();
94     flutterTaskExecutor->InitPlatformThread(useCurrentEventRunner);
95     // No need to create JS Thread for DECLARATIVE_JS
96     if (type_ != FrontendType::DECLARATIVE_JS && type_ != FrontendType::ETS_CARD) {
97         flutterTaskExecutor->InitJsThread();
98     } else {
99         GetSettings().useUIAsJSThread = true;
100     }
101 #endif
102     taskExecutor_ = flutterTaskExecutor;
103 }
104 
Initialize()105 void AceContainer::Initialize()
106 {
107     ContainerScope scope(instanceId_);
108     if (type_ != FrontendType::DECLARATIVE_JS && type_ != FrontendType::ETS_CARD) {
109         InitializeFrontend();
110     }
111 }
112 
Destroy()113 void AceContainer::Destroy()
114 {
115     ContainerScope scope(instanceId_);
116     LOGI("AceContainer::Destroy begin");
117     if (!pipelineContext_) {
118         LOGE("no context find in %{private}d container", instanceId_);
119         return;
120     }
121     if (!taskExecutor_) {
122         LOGE("no taskExecutor find in %{private}d container", instanceId_);
123         return;
124     }
125     auto weak = AceType::WeakClaim(AceType::RawPtr(pipelineContext_));
126     taskExecutor_->PostTask(
127         [weak]() {
128             auto context = weak.Upgrade();
129             if (context == nullptr) {
130                 LOGE("context is nullptr");
131                 return;
132             }
133             context->Destroy();
134         },
135         TaskExecutor::TaskType::UI);
136 
137     RefPtr<Frontend> frontend;
138     frontend_.Swap(frontend);
139     if (frontend && taskExecutor_) {
140         taskExecutor_->PostTask(
141             [frontend]() {
142                 frontend->UpdateState(Frontend::State::ON_DESTROY);
143                 frontend->Destroy();
144             },
145             TaskExecutor::TaskType::JS);
146     }
147 
148     messageBridge_.Reset();
149     resRegister_.Reset();
150     assetManager_.Reset();
151     pipelineContext_.Reset();
152     aceView_ = nullptr;
153     LOGI("AceContainer::Destroy end");
154 }
155 
DestroyView()156 void AceContainer::DestroyView()
157 {
158     if (aceView_ != nullptr) {
159         delete aceView_;
160         aceView_ = nullptr;
161     }
162 }
163 
InitializeFrontend()164 void AceContainer::InitializeFrontend()
165 {
166     if (type_ == FrontendType::JS) {
167         frontend_ = Frontend::Create();
168         auto jsFrontend = AceType::DynamicCast<JsFrontend>(frontend_);
169         auto jsEngine = Framework::JsEngineLoader::Get().CreateJsEngine(GetInstanceId());
170         EngineHelper::AddEngine(instanceId_, jsEngine);
171         jsFrontend->SetJsEngine(jsEngine);
172         jsFrontend->SetNeedDebugBreakPoint(AceApplicationInfo::GetInstance().IsNeedDebugBreakPoint());
173         jsFrontend->SetDebugVersion(AceApplicationInfo::GetInstance().IsDebugVersion());
174     } else if (type_ == FrontendType::DECLARATIVE_JS) {
175         frontend_ = AceType::MakeRefPtr<DeclarativeFrontend>();
176         auto declarativeFrontend = AceType::DynamicCast<DeclarativeFrontend>(frontend_);
177         auto& loader = Framework::JsEngineLoader::GetDeclarative();
178         RefPtr<Framework::JsEngine> jsEngine;
179         if (GetSettings().usingSharedRuntime) {
180             jsEngine = loader.CreateJsEngineUsingSharedRuntime(instanceId_, sharedRuntime_);
181         } else {
182             jsEngine = loader.CreateJsEngine(instanceId_);
183         }
184         EngineHelper::AddEngine(instanceId_, jsEngine);
185         declarativeFrontend->SetJsEngine(jsEngine);
186         declarativeFrontend->SetPageProfile(pageProfile_);
187     } else if (type_ == FrontendType::JS_CARD) {
188         AceApplicationInfo::GetInstance().SetCardType();
189         frontend_ = AceType::MakeRefPtr<CardFrontend>();
190     } else if (type_ == FrontendType::ETS_CARD) {
191         frontend_ = AceType::MakeRefPtr<FormFrontendDeclarative>();
192         auto cardFrontend = AceType::DynamicCast<FormFrontendDeclarative>(frontend_);
193         auto jsEngine = Framework::JsEngineLoader::GetDeclarative().CreateJsEngine(instanceId_);
194         EngineHelper::AddEngine(instanceId_, jsEngine);
195         cardFrontend->SetJsEngine(jsEngine);
196         cardFrontend->SetPageProfile(pageProfile_);
197         cardFrontend->SetRunningCardId(0);
198         cardFrontend->SetIsFormRender(true);
199         cardFrontend->SetTaskExecutor(taskExecutor_);
200         SetIsFRSCardContainer(true);
201     } else {
202         LOGE("Frontend type not supported");
203         return;
204     }
205     ACE_DCHECK(frontend_);
206     frontend_->DisallowPopLastPage();
207     frontend_->Initialize(type_, taskExecutor_);
208     if (assetManager_) {
209         frontend_->SetAssetManager(assetManager_);
210     }
211 }
212 
RunNativeEngineLoop()213 void AceContainer::RunNativeEngineLoop()
214 {
215     taskExecutor_->PostTask([frontend = frontend_]() { frontend->RunNativeEngineLoop(); }, TaskExecutor::TaskType::JS);
216     // After the JS thread executes frontend ->RunNativeEngineLoop(),
217     // it is thrown back into the Platform thread queue to form a loop.
218     taskExecutor_->PostTask([this]() { RunNativeEngineLoop(); }, TaskExecutor::TaskType::PLATFORM);
219 }
220 
InitializeStageAppConfig(const std::string & assetPath,const std::string & bundleName,const std::string & moduleName,const std::string & compileMode)221 void AceContainer::InitializeStageAppConfig(const std::string& assetPath, const std::string& bundleName,
222     const std::string& moduleName, const std::string& compileMode)
223 {
224     bool isBundle = (compileMode != "esmodule");
225     auto declarativeFrontend = AceType::DynamicCast<DeclarativeFrontend>(frontend_);
226     CHECK_NULL_VOID(declarativeFrontend);
227     declarativeFrontend->InitializeModuleSearcher(bundleName, moduleName, assetPath, isBundle);
228 
229     auto formFrontend = AceType::DynamicCast<FormFrontendDeclarative>(frontend_);
230     CHECK_NULL_VOID(formFrontend);
231     formFrontend->SetBundleName(bundleName);
232     formFrontend->SetModuleName(moduleName);
233     formFrontend->SetIsBundle(isBundle);
234 }
235 
SetStageCardConfig(const std::string & pageProfile,const std::string & selectUrl)236 void AceContainer::SetStageCardConfig(const std::string& pageProfile, const std::string& selectUrl)
237 {
238     std::string fullPageProfile = pageProfile + ".json";
239     std::string formConfigs;
240     RefPtr<StageCardParser> stageCardParser = AceType::MakeRefPtr<StageCardParser>();
241     if (!Framework::GetAssetContentImpl(assetManager_, fullPageProfile, formConfigs)) {
242         LOGI("Can not load the form config.");
243         return;
244     }
245     const std::string prefix("./js/");
246     stageCardParser->Parse(formConfigs, prefix + selectUrl);
247     auto cardFront = static_cast<CardFrontend*>(RawPtr(frontend_));
248     if (cardFront) {
249         cardFront->SetFormSrc(selectUrl);
250         cardFront->SetCardWindowConfig(stageCardParser->GetWindowConfig());
251     }
252 }
253 
InitializeCallback()254 void AceContainer::InitializeCallback()
255 {
256     ACE_FUNCTION_TRACE();
257 
258     ACE_DCHECK(aceView_ && taskExecutor_ && pipelineContext_);
259 
260     auto weak = AceType::WeakClaim(AceType::RawPtr(pipelineContext_));
261     auto&& touchEventCallback = [weak, id = instanceId_](
262                                     const TouchEvent& event, const std::function<void()>& ignoreMark) {
263         ContainerScope scope(id);
264         auto context = weak.Upgrade();
265         if (context == nullptr) {
266             LOGE("context is nullptr");
267             return;
268         }
269         context->GetTaskExecutor()->PostTask(
270             [context, event]() { context->OnTouchEvent(event); }, TaskExecutor::TaskType::UI);
271     };
272     aceView_->RegisterTouchEventCallback(touchEventCallback);
273 
274     auto&& keyEventCallback = [weak, id = instanceId_](const KeyEvent& event) {
275         ContainerScope scope(id);
276         auto context = weak.Upgrade();
277         if (context == nullptr) {
278             LOGE("context is nullptr");
279             return false;
280         }
281         bool result = false;
282         context->GetTaskExecutor()->PostSyncTask(
283             [context, event, &result]() { result = context->OnKeyEvent(event); }, TaskExecutor::TaskType::UI);
284         return result;
285     };
286     aceView_->RegisterKeyEventCallback(keyEventCallback);
287 
288     auto&& mouseEventCallback = [weak, id = instanceId_](
289                                     const MouseEvent& event, const std::function<void()>& ignoreMark) {
290         ContainerScope scope(id);
291         auto context = weak.Upgrade();
292         if (context == nullptr) {
293             LOGE("context is nullptr");
294             return;
295         }
296         context->GetTaskExecutor()->PostTask(
297             [context, event]() { context->OnMouseEvent(event); }, TaskExecutor::TaskType::UI);
298     };
299     aceView_->RegisterMouseEventCallback(mouseEventCallback);
300 
301     auto&& axisEventCallback = [weak, id = instanceId_](
302                                    const AxisEvent& event, const std::function<void()>& ignoreMark) {
303         ContainerScope scope(id);
304         auto context = weak.Upgrade();
305         if (context == nullptr) {
306             LOGE("context is nullptr");
307             return;
308         }
309         context->GetTaskExecutor()->PostTask(
310             [context, event]() { context->OnAxisEvent(event); }, TaskExecutor::TaskType::UI);
311     };
312     aceView_->RegisterAxisEventCallback(axisEventCallback);
313 
314     auto&& rotationEventCallback = [weak, id = instanceId_](const RotationEvent& event) {
315         ContainerScope scope(id);
316         auto context = weak.Upgrade();
317         if (context == nullptr) {
318             LOGE("context is nullptr");
319             return false;
320         }
321         bool result = false;
322         context->GetTaskExecutor()->PostSyncTask(
323             [context, event, &result]() { result = context->OnRotationEvent(event); }, TaskExecutor::TaskType::UI);
324         return result;
325     };
326     aceView_->RegisterRotationEventCallback(rotationEventCallback);
327 
328     auto&& cardViewPositionCallback = [weak, instanceId = instanceId_](int id, float offsetX, float offsetY) {
329         ContainerScope scope(instanceId);
330         auto context = AceType::DynamicCast<PipelineContext>(weak.Upgrade());
331         if (context == nullptr) {
332             LOGE("context is nullptr");
333             return;
334         }
335         context->GetTaskExecutor()->PostSyncTask(
336             [context, id, offsetX, offsetY]() { context->SetCardViewPosition(id, offsetX, offsetY); },
337             TaskExecutor::TaskType::UI);
338     };
339     aceView_->RegisterCardViewPositionCallback(cardViewPositionCallback);
340 
341     auto&& cardViewParamsCallback = [weak, id = instanceId_](const std::string& key, bool focus) {
342         ContainerScope scope(id);
343         auto context = AceType::DynamicCast<PipelineContext>(weak.Upgrade());
344         if (context == nullptr) {
345             LOGE("context is nullptr");
346             return;
347         }
348         context->GetTaskExecutor()->PostSyncTask(
349             [context, key, focus]() { context->SetCardViewAccessibilityParams(key, focus); },
350             TaskExecutor::TaskType::UI);
351     };
352     aceView_->RegisterCardViewAccessibilityParamsCallback(cardViewParamsCallback);
353 
354     auto&& viewChangeCallback = [weak, id = instanceId_](int32_t width, int32_t height, WindowSizeChangeReason type,
355                                     const std::shared_ptr<Rosen::RSTransaction>& rsTransaction) {
356         ContainerScope scope(id);
357         auto context = weak.Upgrade();
358         if (context == nullptr) {
359             LOGE("context is nullptr");
360             return;
361         }
362         ACE_SCOPED_TRACE("ViewChangeCallback(%d, %d)", width, height);
363         context->GetTaskExecutor()->PostTask(
364             [context, width, height, type, rsTransaction]() {
365                 context->OnSurfaceChanged(width, height, type, rsTransaction);
366             },
367             TaskExecutor::TaskType::UI);
368     };
369     aceView_->RegisterViewChangeCallback(viewChangeCallback);
370 
371     auto&& densityChangeCallback = [weak, id = instanceId_](double density) {
372         ContainerScope scope(id);
373         auto context = weak.Upgrade();
374         if (context == nullptr) {
375             LOGE("context is nullptr");
376             return;
377         }
378         ACE_SCOPED_TRACE("DensityChangeCallback(%lf)", density);
379         context->GetTaskExecutor()->PostTask(
380             [context, density]() { context->OnSurfaceDensityChanged(density); }, TaskExecutor::TaskType::UI);
381     };
382     aceView_->RegisterDensityChangeCallback(densityChangeCallback);
383 
384     auto&& systemBarHeightChangeCallback = [weak, id = instanceId_](double statusBar, double navigationBar) {
385         ContainerScope scope(id);
386         auto context = weak.Upgrade();
387         if (context == nullptr) {
388             LOGE("context is nullptr");
389             return;
390         }
391         ACE_SCOPED_TRACE("SystemBarHeightChangeCallback(%lf, %lf)", statusBar, navigationBar);
392         context->GetTaskExecutor()->PostTask(
393             [context, statusBar, navigationBar]() { context->OnSystemBarHeightChanged(statusBar, navigationBar); },
394             TaskExecutor::TaskType::UI);
395     };
396     aceView_->RegisterSystemBarHeightChangeCallback(systemBarHeightChangeCallback);
397 
398     auto&& surfaceDestroyCallback = [weak, id = instanceId_]() {
399         ContainerScope scope(id);
400         auto context = weak.Upgrade();
401         if (context == nullptr) {
402             LOGE("context is nullptr");
403             return;
404         }
405         context->GetTaskExecutor()->PostTask(
406             [context]() { context->OnSurfaceDestroyed(); }, TaskExecutor::TaskType::UI);
407     };
408     aceView_->RegisterSurfaceDestroyCallback(surfaceDestroyCallback);
409 
410     auto&& idleCallback = [weak, id = instanceId_](int64_t deadline) {
411         ContainerScope scope(id);
412         auto context = weak.Upgrade();
413         if (context == nullptr) {
414             LOGE("context is nullptr");
415             return;
416         }
417         context->GetTaskExecutor()->PostTask(
418             [context, deadline]() { context->OnIdle(deadline); }, TaskExecutor::TaskType::UI);
419     };
420     aceView_->RegisterIdleCallback(idleCallback);
421 }
422 
CreateContainer(int32_t instanceId,FrontendType type,bool useNewPipeline,bool useCurrentEventRunner)423 void AceContainer::CreateContainer(
424     int32_t instanceId, FrontendType type, bool useNewPipeline, bool useCurrentEventRunner)
425 {
426     auto aceContainer = AceType::MakeRefPtr<AceContainer>(instanceId, type, useNewPipeline, useCurrentEventRunner);
427     AceEngine::Get().AddContainer(aceContainer->GetInstanceId(), aceContainer);
428     aceContainer->Initialize();
429     ContainerScope scope(instanceId);
430     auto front = aceContainer->GetFrontend();
431     if (front) {
432         front->UpdateState(Frontend::State::ON_CREATE);
433         front->SetJsMessageDispatcher(aceContainer);
434     }
435     auto platMessageBridge = aceContainer->GetMessageBridge();
436     platMessageBridge->SetJsMessageDispatcher(aceContainer);
437 }
438 
DestroyContainer(int32_t instanceId)439 void AceContainer::DestroyContainer(int32_t instanceId)
440 {
441     auto container = AceEngine::Get().GetContainer(instanceId);
442     if (!container) {
443         LOGE("no AceContainer with id %{private}d in AceEngine", instanceId);
444         return;
445     }
446     container->Destroy();
447     // unregister watchdog before stop thread to avoid UI_BLOCK report
448     AceEngine::Get().UnRegisterFromWatchDog(instanceId);
449     auto taskExecutor = container->GetTaskExecutor();
450     if (taskExecutor) {
451         taskExecutor->PostSyncTask([] { LOGI("Wait UI thread..."); }, TaskExecutor::TaskType::UI);
452         taskExecutor->PostSyncTask([] { LOGI("Wait JS thread..."); }, TaskExecutor::TaskType::JS);
453     }
454     container->DestroyView(); // Stop all threads(ui,gpu,io) for current ability.
455     EngineHelper::RemoveEngine(instanceId);
456     AceEngine::Get().RemoveContainer(instanceId);
457 }
458 
RunPage(int32_t instanceId,int32_t pageId,const std::string & url,const std::string & params)459 bool AceContainer::RunPage(int32_t instanceId, int32_t pageId, const std::string& url, const std::string& params)
460 {
461     ACE_FUNCTION_TRACE();
462     auto container = AceEngine::Get().GetContainer(instanceId);
463     if (!container) {
464         return false;
465     }
466 
467     ContainerScope scope(instanceId);
468     auto front = container->GetFrontend();
469     if (front) {
470         auto type = front->GetType();
471         if ((type == FrontendType::JS) || (type == FrontendType::DECLARATIVE_JS) || (type == FrontendType::JS_CARD) ||
472             (type == FrontendType::ETS_CARD)) {
473             front->RunPage(pageId, url, params);
474             return true;
475         } else {
476             LOGE("Frontend type not supported when runpage");
477             EventReport::SendAppStartException(AppStartExcepType::FRONTEND_TYPE_ERR);
478             return false;
479         }
480     }
481     return false;
482 }
483 
UpdateResourceConfiguration(const std::string & jsonStr)484 void AceContainer::UpdateResourceConfiguration(const std::string& jsonStr)
485 {
486     ContainerScope scope(instanceId_);
487     uint32_t updateFlags = 0;
488     auto resConfig = resourceInfo_.GetResourceConfiguration();
489     if (!resConfig.UpdateFromJsonString(jsonStr, updateFlags) || !updateFlags) {
490         return;
491     }
492     resourceInfo_.SetResourceConfiguration(resConfig);
493     if (ResourceConfiguration::TestFlag(updateFlags, ResourceConfiguration::COLOR_MODE_UPDATED_FLAG)) {
494         SystemProperties::SetColorMode(resConfig.GetColorMode());
495         if (frontend_) {
496             frontend_->SetColorMode(resConfig.GetColorMode());
497         }
498     }
499     if (!pipelineContext_) {
500         return;
501     }
502     auto themeManager = pipelineContext_->GetThemeManager();
503     if (!themeManager) {
504         return;
505     }
506     themeManager->UpdateConfig(resConfig);
507     taskExecutor_->PostTask(
508         [weakThemeManager = WeakPtr<ThemeManager>(themeManager), colorScheme = colorScheme_, config = resConfig,
509             weakContext = WeakPtr<PipelineBase>(pipelineContext_)]() {
510             auto themeManager = weakThemeManager.Upgrade();
511             auto context = weakContext.Upgrade();
512             if (!themeManager || !context) {
513                 return;
514             }
515             themeManager->LoadResourceThemes();
516             themeManager->ParseSystemTheme();
517             themeManager->SetColorScheme(colorScheme);
518             context->RefreshRootBgColor();
519             context->UpdateFontWeightScale();
520             context->SetFontScale(config.GetFontRatio());
521         },
522         TaskExecutor::TaskType::UI);
523     if (frontend_) {
524         frontend_->RebuildAllPages();
525     }
526 }
527 
NativeOnConfigurationUpdated(int32_t instanceId)528 void AceContainer::NativeOnConfigurationUpdated(int32_t instanceId)
529 {
530     auto container = GetContainerInstance(instanceId);
531     if (!container) {
532         return;
533     }
534     ContainerScope scope(instanceId);
535     auto front = container->GetFrontend();
536     if (!front) {
537         return;
538     }
539 
540     std::unique_ptr<JsonValue> value = JsonUtil::Create(true);
541     value->Put("fontScale", container->GetResourceConfiguration().GetFontRatio());
542     value->Put("colorMode", SystemProperties::GetColorMode() == ColorMode::LIGHT ? "light" : "dark");
543     auto declarativeFrontend = AceType::DynamicCast<DeclarativeFrontend>(front);
544     if (declarativeFrontend) {
545         container->UpdateResourceConfiguration(value->ToString());
546         declarativeFrontend->OnConfigurationUpdated(value->ToString());
547         return;
548     }
549 
550     std::unique_ptr<JsonValue> localeValue = JsonUtil::Create(false);
551     localeValue->Put(LANGUAGE_TAG, AceApplicationInfo::GetInstance().GetLanguage().c_str());
552     localeValue->Put(COUNTRY_TAG, AceApplicationInfo::GetInstance().GetCountryOrRegion().c_str());
553     localeValue->Put(
554         DIRECTION_TAG, AceApplicationInfo::GetInstance().IsRightToLeft() ? LOCALE_DIR_RTL : LOCALE_DIR_LTR);
555     localeValue->Put(UNICODE_SETTING_TAG, AceApplicationInfo::GetInstance().GetUnicodeSetting().c_str());
556     value->Put(LOCALE_KEY, localeValue);
557     front->OnConfigurationUpdated(value->ToString());
558 }
559 
Dispatch(const std::string & group,std::vector<uint8_t> && data,int32_t id,bool replyToComponent) const560 void AceContainer::Dispatch(
561     const std::string& group, std::vector<uint8_t>&& data, int32_t id, bool replyToComponent) const
562 {}
563 
FetchResponse(const ResponseData responseData,const int32_t callbackId) const564 void AceContainer::FetchResponse(const ResponseData responseData, const int32_t callbackId) const
565 {
566     auto container = AceType::DynamicCast<AceContainer>(AceEngine::Get().GetContainer(0));
567     if (!container) {
568         LOGE("FetchResponse container is null!");
569         return;
570     }
571     ContainerScope scope(instanceId_);
572     auto front = container->GetFrontend();
573     auto type = container->GetType();
574     if (type == FrontendType::JS) {
575         auto jsFrontend = AceType::DynamicCast<JsFrontend>(front);
576         if (jsFrontend) {
577             jsFrontend->TransferJsResponseDataPreview(callbackId, ACTION_SUCCESS, responseData);
578         }
579     } else if (type == FrontendType::DECLARATIVE_JS) {
580         auto declarativeFrontend = AceType::DynamicCast<DeclarativeFrontend>(front);
581         if (declarativeFrontend) {
582             declarativeFrontend->TransferJsResponseDataPreview(callbackId, ACTION_SUCCESS, responseData);
583         }
584     } else {
585         LOGE("Frontend type not supported");
586         return;
587     }
588 }
589 
CallCurlFunction(const RequestData requestData,const int32_t callbackId) const590 void AceContainer::CallCurlFunction(const RequestData requestData, const int32_t callbackId) const
591 {
592     auto container = AceType::DynamicCast<AceContainer>(AceEngine::Get().GetContainer(ACE_INSTANCE_ID));
593     if (!container) {
594         LOGE("CallCurlFunction container is null!");
595         return;
596     }
597 
598     ContainerScope scope(instanceId_);
599     taskExecutor_->PostTask(
600         [container, requestData, callbackId]() mutable {
601             ResponseData responseData;
602             if (FetchManager::GetInstance().Fetch(requestData, callbackId, responseData)) {
603                 container->FetchResponse(responseData, callbackId);
604             }
605         },
606         TaskExecutor::TaskType::BACKGROUND);
607 }
608 
DispatchPluginError(int32_t callbackId,int32_t errorCode,std::string && errorMessage) const609 void AceContainer::DispatchPluginError(int32_t callbackId, int32_t errorCode, std::string&& errorMessage) const
610 {
611     auto front = GetFrontend();
612     if (!front) {
613         LOGE("the front jni is nullptr");
614         return;
615     }
616 
617     ContainerScope scope(instanceId_);
618     taskExecutor_->PostTask(
619         [front, callbackId, errorCode, errorMessage = std::move(errorMessage)]() mutable {
620             front->TransferJsPluginGetError(callbackId, errorCode, std::move(errorMessage));
621         },
622         TaskExecutor::TaskType::BACKGROUND);
623 }
624 
AddRouterChangeCallback(int32_t instanceId,const OnRouterChangeCallback & onRouterChangeCallback)625 void AceContainer::AddRouterChangeCallback(int32_t instanceId, const OnRouterChangeCallback& onRouterChangeCallback)
626 {
627     auto container = GetContainerInstance(instanceId);
628     if (!container) {
629         return;
630     }
631     ContainerScope scope(instanceId);
632     if (!container->pipelineContext_) {
633         LOGE("container pipelineContext not init");
634         return;
635     }
636     container->pipelineContext_->AddRouterChangeCallback(onRouterChangeCallback);
637 }
638 
639 #ifndef ENABLE_ROSEN_BACKEND
AddAssetPath(int32_t instanceId,const std::string & packagePath,const std::vector<std::string> & paths)640 void AceContainer::AddAssetPath(
641     int32_t instanceId, const std::string& packagePath, const std::vector<std::string>& paths)
642 {
643     auto container = GetContainerInstance(instanceId);
644     CHECK_NULL_VOID(container);
645 
646     if (!container->assetManager_) {
647         RefPtr<FlutterAssetManager> flutterAssetManager = Referenced::MakeRefPtr<FlutterAssetManager>();
648         container->assetManager_ = flutterAssetManager;
649         if (container->frontend_) {
650             container->frontend_->SetAssetManager(flutterAssetManager);
651         }
652     }
653 
654     for (const auto& path : paths) {
655         LOGD("Current path is: %{private}s", path.c_str());
656         auto dirAssetProvider = AceType::MakeRefPtr<DirAssetProvider>(
657             path, std::make_unique<flutter::DirectoryAssetBundle>(
658                       fml::OpenDirectory(path.c_str(), false, fml::FilePermission::kRead)));
659         container->assetManager_->PushBack(std::move(dirAssetProvider));
660     }
661 }
662 #else
AddAssetPath(int32_t instanceId,const std::string & packagePath,const std::vector<std::string> & paths)663 void AceContainer::AddAssetPath(
664     int32_t instanceId, const std::string& packagePath, const std::vector<std::string>& paths)
665 {
666     auto container = GetContainerInstance(instanceId);
667     CHECK_NULL_VOID(container);
668 
669     if (!container->assetManager_) {
670         RefPtr<RSAssetManager> rsAssetManager = Referenced::MakeRefPtr<RSAssetManager>();
671         container->assetManager_ = rsAssetManager;
672         if (container->frontend_) {
673             container->frontend_->SetAssetManager(rsAssetManager);
674         }
675     }
676 
677     for (const auto& path : paths) {
678         LOGD("Current path is: %{private}s", path.c_str());
679         auto dirAssetProvider = AceType::MakeRefPtr<RSDirAssetProvider>(path);
680         container->assetManager_->PushBack(std::move(dirAssetProvider));
681     }
682 }
683 #endif
684 
SetResourcesPathAndThemeStyle(int32_t instanceId,const std::string & systemResourcesPath,const std::string & appResourcesPath,const int32_t & themeId,const ColorMode & colorMode)685 void AceContainer::SetResourcesPathAndThemeStyle(int32_t instanceId, const std::string& systemResourcesPath,
686     const std::string& appResourcesPath, const int32_t& themeId, const ColorMode& colorMode)
687 {
688     auto container = GetContainerInstance(instanceId);
689     if (!container) {
690         return;
691     }
692     ContainerScope scope(instanceId);
693     auto resConfig = container->resourceInfo_.GetResourceConfiguration();
694     resConfig.SetColorMode(static_cast<OHOS::Ace::ColorMode>(colorMode));
695     container->resourceInfo_.SetResourceConfiguration(resConfig);
696     container->resourceInfo_.SetPackagePath(appResourcesPath);
697     container->resourceInfo_.SetSystemPackagePath(systemResourcesPath);
698     container->resourceInfo_.SetThemeId(themeId);
699 }
700 
UpdateDeviceConfig(const DeviceConfig & deviceConfig)701 void AceContainer::UpdateDeviceConfig(const DeviceConfig& deviceConfig)
702 {
703     ContainerScope scope(instanceId_);
704     SystemProperties::InitDeviceType(deviceConfig.deviceType);
705     SystemProperties::SetDeviceOrientation(deviceConfig.orientation == DeviceOrientation::PORTRAIT ? 0 : 1);
706     SystemProperties::SetResolution(deviceConfig.density);
707     SystemProperties::SetColorMode(deviceConfig.colorMode);
708     auto resConfig = resourceInfo_.GetResourceConfiguration();
709     if (resConfig.GetDeviceType() == deviceConfig.deviceType &&
710         resConfig.GetOrientation() == deviceConfig.orientation && resConfig.GetDensity() == deviceConfig.density &&
711         resConfig.GetColorMode() == deviceConfig.colorMode && resConfig.GetFontRatio() == deviceConfig.fontRatio) {
712         return;
713     } else {
714         resConfig.SetDeviceType(deviceConfig.deviceType);
715         resConfig.SetOrientation(deviceConfig.orientation);
716         resConfig.SetDensity(deviceConfig.density);
717         resConfig.SetColorMode(deviceConfig.colorMode);
718         resConfig.SetFontRatio(deviceConfig.fontRatio);
719         if (frontend_) {
720             frontend_->SetColorMode(deviceConfig.colorMode);
721         }
722     }
723     resourceInfo_.SetResourceConfiguration(resConfig);
724     if (!pipelineContext_) {
725         return;
726     }
727     auto themeManager = pipelineContext_->GetThemeManager();
728     if (!themeManager) {
729         return;
730     }
731     themeManager->UpdateConfig(resConfig);
732     taskExecutor_->PostTask(
733         [weakThemeManager = WeakPtr<ThemeManager>(themeManager), colorScheme = colorScheme_,
734             weakContext = WeakPtr<PipelineBase>(pipelineContext_)]() {
735             auto themeManager = weakThemeManager.Upgrade();
736             auto context = weakContext.Upgrade();
737             if (!themeManager || !context) {
738                 return;
739             }
740             themeManager->LoadResourceThemes();
741             themeManager->ParseSystemTheme();
742             themeManager->SetColorScheme(colorScheme);
743             context->RefreshRootBgColor();
744         },
745         TaskExecutor::TaskType::UI);
746 }
747 
748 #ifndef ENABLE_ROSEN_BACKEND
SetView(AceViewPreview * view,double density,int32_t width,int32_t height)749 void AceContainer::SetView(AceViewPreview* view, double density, int32_t width, int32_t height)
750 {
751     if (view == nullptr) {
752         return;
753     }
754 
755     auto container = AceType::DynamicCast<AceContainer>(AceEngine::Get().GetContainer(view->GetInstanceId()));
756     if (!container) {
757         return;
758     }
759     auto platformWindow = PlatformWindow::Create(view);
760     if (!platformWindow) {
761         LOGE("Create PlatformWindow failed!");
762         return;
763     }
764 
765     std::unique_ptr<Window> window = std::make_unique<Window>(std::move(platformWindow));
766     container->AttachView(std::move(window), view, density, width, height);
767 }
768 #else
SetView(AceViewPreview * view,sptr<Rosen::Window> rsWindow,double density,int32_t width,int32_t height,UIEnvCallback callback)769 void AceContainer::SetView(AceViewPreview* view, sptr<Rosen::Window> rsWindow, double density, int32_t width,
770     int32_t height, UIEnvCallback callback)
771 {
772     CHECK_NULL_VOID(view);
773     auto container = AceType::DynamicCast<AceContainer>(AceEngine::Get().GetContainer(view->GetInstanceId()));
774     CHECK_NULL_VOID(container);
775     auto taskExecutor = container->GetTaskExecutor();
776     CHECK_NULL_VOID(taskExecutor);
777     auto window = std::make_unique<NG::RosenWindow>(rsWindow, taskExecutor, view->GetInstanceId());
778     container->AttachView(std::move(window), view, density, width, height, callback);
779 }
780 #endif
781 
782 #ifndef ENABLE_ROSEN_BACKEND
AttachView(std::unique_ptr<Window> window,AceViewPreview * view,double density,int32_t width,int32_t height)783 void AceContainer::AttachView(
784     std::unique_ptr<Window> window, AceViewPreview* view, double density, int32_t width, int32_t height)
785 {
786     ContainerScope scope(instanceId_);
787     aceView_ = view;
788     auto instanceId = aceView_->GetInstanceId();
789 
790     auto state = flutter::UIDartState::Current()->GetStateById(instanceId);
791     ACE_DCHECK(state != nullptr);
792     auto flutterTaskExecutor = AceType::DynamicCast<FlutterTaskExecutor>(taskExecutor_);
793     flutterTaskExecutor->InitOtherThreads(state->GetTaskRunners());
794     if (type_ == FrontendType::DECLARATIVE_JS) {
795         // For DECLARATIVE_JS frontend display UI in JS thread temporarily.
796         flutterTaskExecutor->InitJsThread(false);
797         InitializeFrontend();
798         auto front = GetFrontend();
799         if (front) {
800             front->UpdateState(Frontend::State::ON_CREATE);
801             front->SetJsMessageDispatcher(AceType::Claim(this));
802         }
803     }
804     resRegister_ = aceView_->GetPlatformResRegister();
805     auto pipelineContext = AceType::MakeRefPtr<PipelineContext>(
806         std::move(window), taskExecutor_, assetManager_, resRegister_, frontend_, instanceId);
807     pipelineContext->SetRootSize(density, width, height);
808     pipelineContext->SetTextFieldManager(AceType::MakeRefPtr<TextFieldManager>());
809     pipelineContext->SetIsRightToLeft(AceApplicationInfo::GetInstance().IsRightToLeft());
810     pipelineContext->SetMessageBridge(messageBridge_);
811     pipelineContext->SetWindowModal(windowModal_);
812     pipelineContext->SetDrawDelegate(aceView_->GetDrawDelegate());
813     pipelineContext->SetIsJsCard(type_ == FrontendType::JS_CARD);
814     pipelineContext_ = pipelineContext;
815     InitializeCallback();
816 
817     ThemeConstants::InitDeviceType();
818     // Only init global resource here, construct theme in UI thread
819     auto themeManager = AceType::MakeRefPtr<ThemeManagerImpl>();
820     if (themeManager) {
821         pipelineContext_->SetThemeManager(themeManager);
822         // Init resource, load theme map.
823         themeManager->InitResource(resourceInfo_);
824         themeManager->LoadSystemTheme(resourceInfo_.GetThemeId());
825         taskExecutor_->PostTask(
826             [themeManager, assetManager = assetManager_, colorScheme = colorScheme_, aceView = aceView_]() {
827                 themeManager->ParseSystemTheme();
828                 themeManager->SetColorScheme(colorScheme);
829                 themeManager->LoadCustomTheme(assetManager);
830                 // get background color from theme
831                 aceView->SetBackgroundColor(themeManager->GetBackgroundColor());
832             },
833             TaskExecutor::TaskType::UI);
834     }
835 
836     auto weak = AceType::WeakClaim(AceType::RawPtr(pipelineContext_));
837     taskExecutor_->PostTask(
838         [weak]() {
839             auto context = weak.Upgrade();
840             if (context == nullptr) {
841                 LOGE("context is nullptr");
842                 return;
843             }
844             context->SetupRootElement();
845         },
846         TaskExecutor::TaskType::UI);
847     aceView_->Launch();
848 
849     frontend_->AttachPipelineContext(pipelineContext_);
850     auto cardFronted = AceType::DynamicCast<CardFrontend>(frontend_);
851     if (cardFronted) {
852         cardFronted->SetDensity(static_cast<double>(density));
853         taskExecutor_->PostTask(
854             [weak, width, height]() {
855                 auto context = weak.Upgrade();
856                 if (context == nullptr) {
857                     LOGE("context is nullptr");
858                     return;
859                 }
860                 context->OnSurfaceChanged(width, height);
861             },
862             TaskExecutor::TaskType::UI);
863     }
864 
865     AceEngine::Get().RegisterToWatchDog(instanceId, taskExecutor_, GetSettings().useUIAsJSThread);
866 }
867 #else
AttachView(std::unique_ptr<Window> window,AceViewPreview * view,double density,int32_t width,int32_t height,UIEnvCallback callback)868 void AceContainer::AttachView(std::unique_ptr<Window> window, AceViewPreview* view, double density, int32_t width,
869     int32_t height, UIEnvCallback callback)
870 {
871     ContainerScope scope(instanceId_);
872     aceView_ = view;
873     auto instanceId = aceView_->GetInstanceId();
874 
875     auto flutterTaskExecutor = AceType::DynamicCast<FlutterTaskExecutor>(taskExecutor_);
876     CHECK_NULL_VOID(flutterTaskExecutor);
877     flutterTaskExecutor->InitOtherThreads(aceView_->GetThreadModel());
878     if (type_ == FrontendType::DECLARATIVE_JS || type_ == FrontendType::ETS_CARD) {
879         // For DECLARATIVE_JS frontend display UI in JS thread temporarily.
880         flutterTaskExecutor->InitJsThread(false);
881         InitializeFrontend();
882         auto front = AceType::DynamicCast<DeclarativeFrontend>(GetFrontend());
883         if (front) {
884             front->UpdateState(Frontend::State::ON_CREATE);
885             front->SetJsMessageDispatcher(AceType::Claim(this));
886             auto weak = WeakPtr(front->GetJsEngine());
887             taskExecutor_->PostTask(
888                 [weak, containerSdkPath = containerSdkPath_]() {
889                     auto jsEngine = weak.Upgrade();
890                     CHECK_NULL_VOID(jsEngine);
891                     auto* nativeEngine = jsEngine->GetNativeEngine();
892                     CHECK_NULL_VOID(nativeEngine);
893                     auto* moduleManager = nativeEngine->GetModuleManager();
894                     CHECK_NULL_VOID(moduleManager);
895                     moduleManager->SetPreviewSearchPath(containerSdkPath);
896                 },
897                 TaskExecutor::TaskType::JS);
898         }
899     }
900     resRegister_ = aceView_->GetPlatformResRegister();
901     if (useNewPipeline_) {
902         LOGI("New pipeline version creating...");
903         pipelineContext_ = AceType::MakeRefPtr<NG::PipelineContext>(
904             std::move(window), taskExecutor_, assetManager_, resRegister_, frontend_, instanceId);
905         pipelineContext_->SetTextFieldManager(AceType::MakeRefPtr<NG::TextFieldManagerNG>());
906     } else {
907         pipelineContext_ = AceType::MakeRefPtr<PipelineContext>(
908             std::move(window), taskExecutor_, assetManager_, resRegister_, frontend_, instanceId);
909         pipelineContext_->SetTextFieldManager(AceType::MakeRefPtr<TextFieldManager>());
910     }
911     pipelineContext_->SetRootSize(density, width, height);
912     pipelineContext_->SetIsRightToLeft(AceApplicationInfo::GetInstance().IsRightToLeft());
913     pipelineContext_->SetMessageBridge(messageBridge_);
914     pipelineContext_->SetWindowModal(windowModal_);
915     pipelineContext_->SetDrawDelegate(aceView_->GetDrawDelegate());
916     pipelineContext_->SetIsJsCard(type_ == FrontendType::JS_CARD);
917     if (installationFree_ && !isComponentMode_) {
918         LOGD("installationFree:%{public}d, labelId:%{public}d", installationFree_, labelId_);
919         pipelineContext_->SetInstallationFree(installationFree_);
920         pipelineContext_->SetAppLabelId(labelId_);
921     }
922     pipelineContext_->OnShow();
923     InitializeCallback();
924 
925     auto cardFrontend = AceType::DynamicCast<FormFrontendDeclarative>(frontend_);
926     if (cardFrontend) {
927         pipelineContext_->SetIsFormRender(true);
928         cardFrontend->SetLoadCardCallBack(WeakPtr<PipelineBase>(pipelineContext_));
929     }
930 
931     ThemeConstants::InitDeviceType();
932     // Only init global resource here, construct theme in UI thread
933     auto themeManager = AceType::MakeRefPtr<ThemeManagerImpl>();
934     if (themeManager) {
935         pipelineContext_->SetThemeManager(themeManager);
936         // Init resource, load theme map.
937         themeManager->InitResource(resourceInfo_);
938         themeManager->LoadSystemTheme(resourceInfo_.GetThemeId());
939         taskExecutor_->PostTask(
940             [themeManager, assetManager = assetManager_, colorScheme = colorScheme_, aceView = aceView_]() {
941                 themeManager->ParseSystemTheme();
942                 themeManager->SetColorScheme(colorScheme);
943                 themeManager->LoadCustomTheme(assetManager);
944                 // get background color from theme
945                 aceView->SetBackgroundColor(themeManager->GetBackgroundColor());
946             },
947             TaskExecutor::TaskType::UI);
948     }
949     if (!useNewPipeline_) {
950         taskExecutor_->PostTask(
951             [context = pipelineContext_, callback]() {
952                 CHECK_NULL_VOID(callback);
953                 callback(AceType::DynamicCast<PipelineContext>(context));
954             },
955             TaskExecutor::TaskType::UI);
956     }
957 
958     auto weak = AceType::WeakClaim(AceType::RawPtr(pipelineContext_));
959     taskExecutor_->PostTask(
960         [weak]() {
961             auto context = weak.Upgrade();
962             if (context == nullptr) {
963                 LOGE("context is nullptr");
964                 return;
965             }
966             context->SetupRootElement();
967         },
968         TaskExecutor::TaskType::UI);
969     aceView_->Launch();
970 
971     frontend_->AttachPipelineContext(pipelineContext_);
972     auto cardFronted = AceType::DynamicCast<CardFrontend>(frontend_);
973     if (cardFronted) {
974         cardFronted->SetDensity(static_cast<double>(density));
975         taskExecutor_->PostTask(
976             [weak, width, height]() {
977                 auto context = weak.Upgrade();
978                 if (context == nullptr) {
979                     LOGE("context is nullptr");
980                     return;
981                 }
982                 context->OnSurfaceChanged(width, height);
983             },
984             TaskExecutor::TaskType::UI);
985     }
986 
987     AceEngine::Get().RegisterToWatchDog(instanceId, taskExecutor_, GetSettings().useUIAsJSThread);
988 }
989 #endif
990 
GetContainerInstance(int32_t instanceId)991 RefPtr<AceContainer> AceContainer::GetContainerInstance(int32_t instanceId)
992 {
993     auto container = AceType::DynamicCast<AceContainer>(AceEngine::Get().GetContainer(instanceId));
994     return container;
995 }
996 
GetContentInfo(int32_t instanceId)997 std::string AceContainer::GetContentInfo(int32_t instanceId)
998 {
999     auto container = AceEngine::Get().GetContainer(instanceId);
1000     CHECK_NULL_RETURN_NOLOG(container, "");
1001     ContainerScope scope(instanceId);
1002     auto front = container->GetFrontend();
1003     CHECK_NULL_RETURN_NOLOG(front, "");
1004     return front->GetContentInfo();
1005 }
1006 
LoadDocument(const std::string & url,const std::string & componentName)1007 void AceContainer::LoadDocument(const std::string& url, const std::string& componentName)
1008 {
1009     ContainerScope scope(instanceId_);
1010     if (type_ != FrontendType::DECLARATIVE_JS) {
1011         LOGE("component preview not supported");
1012         return;
1013     }
1014     auto frontend = AceType::DynamicCast<OHOS::Ace::DeclarativeFrontend>(frontend_);
1015     if (!frontend) {
1016         LOGE("frontend is null, AceContainer::LoadDocument failed");
1017         return;
1018     }
1019     auto jsEngine = frontend->GetJsEngine();
1020     if (!jsEngine) {
1021         LOGE("jsEngine is null, AceContainer::LoadDocument failed");
1022         return;
1023     }
1024     taskExecutor_->PostTask(
1025         [front = frontend, componentName, url, jsEngine]() {
1026             front->SetPagePath(url);
1027             jsEngine->ReplaceJSContent(url, componentName);
1028         },
1029         TaskExecutor::TaskType::JS);
1030 }
1031 } // namespace OHOS::Ace::Platform
1032