• 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_ability.h"
17 
18 #ifdef INIT_ICU_DATA_PATH
19 #include "unicode/putil.h"
20 #endif
21 
22 #include "third_party/skia/include/core/SkFontMgr.h"
23 
24 #include "adapter/preview/entrance/ace_application_info.h"
25 #include "adapter/preview/entrance/ace_container.h"
26 #include "adapter/preview/entrance/event_dispatcher.h"
27 #include "adapter/preview/inspector/inspector_client.h"
28 #include "frameworks/bridge/common/utils/utils.h"
29 #include "frameworks/bridge/js_frontend/js_frontend.h"
30 
31 #ifndef ENABLE_ROSEN_BACKEND
32 #include "frameworks/core/components/common/painter/flutter_svg_painter.h"
33 #endif
34 
35 namespace OHOS::Ace::Platform {
36 
37 std::atomic<bool> AceAbility::loopRunning_ = true;
38 
39 namespace {
40 
41 // JS frontend maintain the page ID self, so it's useless to pass page ID from platform
42 // layer, neither Android/OpenHarmony or Windows, we should delete here usage when Java delete it.
43 constexpr int32_t UNUSED_PAGE_ID = 1;
44 
45 constexpr char ASSET_PATH_SHARE[] = "share";
46 #ifdef WINDOWS_PLATFORM
47 constexpr char DELIMITER[] = "\\";
48 constexpr char ASSET_PATH_SHARE_STAGE[] = "resources\\base\\profile";
49 #else
50 constexpr char DELIMITER[] = "/";
51 constexpr char ASSET_PATH_SHARE_STAGE[] = "resources/base/profile";
52 #endif
53 
54 #ifdef USE_GLFW_WINDOW
55 // Screen Density Coefficient/Base Density = Resolution/ppi
56 constexpr double SCREEN_DENSITY_COEFFICIENT_PHONE = 1080.0 * 160.0 / 480.0;
57 constexpr double SCREEN_DENSITY_COEFFICIENT_WATCH = 466.0 * 160 / 320.0;
58 constexpr double SCREEN_DENSITY_COEFFICIENT_TABLE = 2560.0 * 160.0 / 280.0;
59 constexpr double SCREEN_DENSITY_COEFFICIENT_TV = 3840.0 * 160.0 / 640.0;
60 
AdaptDeviceType(AceRunArgs & runArgs)61 void AdaptDeviceType(AceRunArgs& runArgs)
62 {
63     if (runArgs.deviceConfig.deviceType == DeviceType::PHONE) {
64         runArgs.deviceConfig.density = runArgs.deviceWidth / SCREEN_DENSITY_COEFFICIENT_PHONE;
65     } else if (runArgs.deviceConfig.deviceType == DeviceType::WATCH) {
66         runArgs.deviceConfig.density = runArgs.deviceWidth / SCREEN_DENSITY_COEFFICIENT_WATCH;
67     } else if (runArgs.deviceConfig.deviceType == DeviceType::TABLET) {
68         runArgs.deviceConfig.density = runArgs.deviceWidth / SCREEN_DENSITY_COEFFICIENT_TABLE;
69     } else if (runArgs.deviceConfig.deviceType == DeviceType::TV) {
70         runArgs.deviceConfig.density = runArgs.deviceWidth / SCREEN_DENSITY_COEFFICIENT_TV;
71     } else {
72         LOGE("DeviceType not supported");
73     }
74 }
75 #endif
76 
SetFontMgrConfig(const std::string & containerSdkPath)77 void SetFontMgrConfig(const std::string& containerSdkPath)
78 {
79     // To check if use ohos or container fonts.
80     std::string runtimeOS;
81     std::string containerFontBasePath;
82     if (containerSdkPath.empty()) {
83         runtimeOS = "OHOS";
84     } else {
85         runtimeOS = "OHOS_Container";
86         containerFontBasePath = containerSdkPath + DELIMITER + "resources" + DELIMITER + "fonts" + DELIMITER;
87     }
88     LOGI("Runtime OS is %{public}s, and the container fontBasePath is %{public}s", runtimeOS.c_str(),
89         containerFontBasePath.c_str());
90     SkFontMgr::SetFontMgrConfig(runtimeOS, containerFontBasePath);
91 }
92 
GetCustomAssetPath(std::string assetPath)93 std::string GetCustomAssetPath(std::string assetPath)
94 {
95     if (assetPath.empty()) {
96         LOGE("AssetPath is null.");
97         return std::string();
98     }
99     std::string customAssetPath;
100     if (OHOS::Ace::Framework::EndWith(assetPath, DELIMITER)) {
101         assetPath = assetPath.substr(0, assetPath.size() - 1);
102     }
103     customAssetPath = assetPath.substr(0, assetPath.find_last_of(DELIMITER) + 1);
104     return customAssetPath;
105 }
106 
107 } // namespace
108 
AceAbility(const AceRunArgs & runArgs)109 AceAbility::AceAbility(const AceRunArgs& runArgs) : runArgs_(runArgs)
110 {
111     static std::once_flag onceFlag;
112     std::call_once(onceFlag, []() {
113         LOGI("Initialize for current process.");
114         Container::UpdateCurrent(INSTANCE_ID_PLATFORM);
115     });
116 
117     if (runArgs_.aceVersion == AceVersion::ACE_1_0) {
118         if (runArgs_.formsEnabled) {
119             LOGI("CreateContainer with JS_CARD frontend");
120             AceContainer::CreateContainer(ACE_INSTANCE_ID, FrontendType::JS_CARD, runArgs_);
121         } else {
122             LOGI("CreateContainer with JS frontend");
123             AceContainer::CreateContainer(ACE_INSTANCE_ID, FrontendType::JS, runArgs_);
124         }
125     } else if (runArgs_.aceVersion == AceVersion::ACE_2_0) {
126         if (runArgs_.formsEnabled) {
127             LOGI("CreateContainer with ETS_CARD frontend");
128             AceContainer::CreateContainer(ACE_INSTANCE_ID, FrontendType::ETS_CARD, runArgs_);
129         } else {
130             LOGI("CreateContainer with JSDECLARATIVE frontend");
131             AceContainer::CreateContainer(ACE_INSTANCE_ID, FrontendType::DECLARATIVE_JS, runArgs_);
132         }
133     } else {
134         LOGE("UnKnown frontend type");
135     }
136     auto container = AceContainer::GetContainerInstance(ACE_INSTANCE_ID);
137     if (!container) {
138         LOGE("container is null, set configuration failed.");
139         return;
140     }
141     container->InitDeviceInfo(ACE_INSTANCE_ID, runArgs);
142     SetConfigChanges(runArgs.configChanges);
143     auto resConfig = container->GetResourceConfiguration();
144     resConfig.SetOrientation(SystemProperties::GetDeviceOrientation());
145     resConfig.SetDensity(SystemProperties::GetResolution());
146     resConfig.SetDeviceType(SystemProperties::GetDeviceType());
147     container->SetResourceConfiguration(resConfig);
148 }
149 
150 #ifndef ENABLE_ROSEN_BACKEND
~AceAbility()151 AceAbility::~AceAbility()
152 {
153     if (controller_) {
154         FlutterDesktopDestroyWindow(controller_);
155     }
156     FlutterDesktopTerminate();
157 }
158 #else
~AceAbility()159 AceAbility::~AceAbility()
160 {
161     if (controller_ != nullptr) {
162         controller_->DestroyWindow();
163         controller_->Terminate();
164     }
165 }
166 #endif
167 
168 namespace {
DumpAceRunArgs(const AceRunArgs & runArgs)169 inline void DumpAceRunArgs(const AceRunArgs& runArgs)
170 {
171 #ifdef ACE_DEBUG
172     LOGI("runArgs.pageProfile: %{private}s", runArgs.pageProfile.c_str());
173     LOGI("runArgs.asset: %{private}s", runArgs.assetPath.c_str());
174     LOGI("runArgs.systemResources: %{private}s", runArgs.systemResourcesPath.c_str());
175     LOGI("runArgs.appResources: %{private}s", runArgs.appResourcesPath.c_str());
176     LOGI("runArgs.themeId: %{private}u", runArgs.themeId);
177     LOGI("runArgs.deviceConfig.orientation: %{private}d", static_cast<int>(runArgs.deviceConfig.orientation));
178     LOGI("runArgs.deviceConfig.density: %{private}lf", runArgs.deviceConfig.density);
179     LOGI("runArgs.deviceConfig.deviceType: %{private}d", static_cast<int>(runArgs.deviceConfig.deviceType));
180     LOGI("runArgs.deviceConfig.fontRatio: %{private}lf", runArgs.deviceConfig.fontRatio);
181     LOGI("runArgs.deviceConfig.colorMode: %{private}d", static_cast<int>(runArgs.deviceConfig.colorMode));
182     LOGI("runArgs.url: %{private}s", runArgs.url.c_str());
183     LOGI("runArgs.windowTitle: %{private}s", runArgs.windowTitle.c_str());
184     LOGI("runArgs.isRound: %{private}s", runArgs.isRound ? "true" : "false");
185     LOGI("runArgs.viewWidth: %{private}d", runArgs.viewWidth);
186     LOGI("runArgs.viewHeight: %{private}d", runArgs.viewHeight);
187     LOGI("runArgs.deviceWidth: %{private}d", runArgs.deviceWidth);
188     LOGI("runArgs.deviceHeight: %{private}d", runArgs.deviceHeight);
189 #endif
190 }
191 } // namespace
192 
193 #ifndef ENABLE_ROSEN_BACKEND
CreateInstance(AceRunArgs & runArgs)194 std::unique_ptr<AceAbility> AceAbility::CreateInstance(AceRunArgs& runArgs)
195 {
196     DumpAceRunArgs(runArgs);
197     LOGI("Start create AceAbility instance");
198     bool initSucceeded = FlutterDesktopInit();
199     if (!initSucceeded) {
200         LOGE("Could not create window; AceDesktopInit failed.");
201         return nullptr;
202     }
203     AceApplicationInfo::GetInstance().SetLocale(runArgs.language, runArgs.region, runArgs.script, "");
204 
205     SetFontMgrConfig(runArgs.containerSdkPath);
206 
207     auto controller = FlutterDesktopCreateWindow(
208         runArgs.deviceWidth, runArgs.deviceHeight, runArgs.windowTitle.c_str(), runArgs.onRender);
209     EventDispatcher::GetInstance().SetGlfwWindowController(controller);
210     EventDispatcher::GetInstance().Initialize();
211     auto aceAbility = std::make_unique<AceAbility>(runArgs);
212     aceAbility->SetGlfwWindowController(controller);
213     return aceAbility;
214 }
215 #else
CreateInstance(AceRunArgs & runArgs)216 std::unique_ptr<AceAbility> AceAbility::CreateInstance(AceRunArgs& runArgs)
217 {
218     DumpAceRunArgs(runArgs);
219     LOGI("Start create AceAbility instance");
220     bool initSucceeded = FlutterDesktopInit();
221     if (!initSucceeded) {
222         LOGE("Could not create window; AceDesktopInit failed.");
223         return nullptr;
224     }
225     AceApplicationInfo::GetInstance().SetLocale(runArgs.language, runArgs.region, runArgs.script, "");
226 
227     SetFontMgrConfig(runArgs.containerSdkPath);
228 
229     auto controller = FlutterDesktopCreateWindow(
230         runArgs.deviceWidth, runArgs.deviceHeight, runArgs.windowTitle.c_str(), runArgs.onRender);
231 
232     const auto& ctx = OHOS::Rosen::GlfwRenderContext::GetGlobal();
233     if (ctx != nullptr) {
234         ctx->InitFrom(FlutterDesktopGetWindow(controller));
235     }
236 
237     EventDispatcher::GetInstance().Initialize();
238     auto aceAbility = std::make_unique<AceAbility>(runArgs);
239     aceAbility->SetGlfwWindowController(ctx);
240     aceAbility->SetFlutterWindowControllerRef(controller);
241     return aceAbility;
242 }
243 #endif
244 
245 #ifndef ENABLE_ROSEN_BACKEND
InitEnv()246 void AceAbility::InitEnv()
247 {
248 #ifdef INIT_ICU_DATA_PATH
249     std::string icuPath = ".";
250     u_setDataDirectory(icuPath.c_str());
251 #endif
252     std::vector<std::string> paths;
253     paths.push_back(runArgs_.assetPath);
254     std::string appResourcesPath(runArgs_.appResourcesPath);
255     if (!OHOS::Ace::Framework::EndWith(appResourcesPath, DELIMITER)) {
256         appResourcesPath.append(DELIMITER);
257     }
258     if (runArgs_.projectModel == ProjectModel::STAGE) {
259         paths.push_back(appResourcesPath);
260         paths.push_back(appResourcesPath + ASSET_PATH_SHARE_STAGE);
261     } else {
262         paths.push_back(GetCustomAssetPath(runArgs_.assetPath) + ASSET_PATH_SHARE);
263     }
264     AceContainer::AddAssetPath(ACE_INSTANCE_ID, "", paths);
265     auto container = AceContainer::GetContainerInstance(ACE_INSTANCE_ID);
266     CHECK_NULL_VOID(container);
267     if (runArgs_.projectModel == ProjectModel::STAGE) {
268         if (runArgs_.formsEnabled) {
269             container->SetStageCardConfig(runArgs_.pageProfile, runArgs_.url);
270         } else {
271             container->SetPageProfile((runArgs_.pageProfile.empty() ? "" : runArgs_.pageProfile + ".json"));
272         }
273     }
274     AceContainer::SetResourcesPathAndThemeStyle(ACE_INSTANCE_ID, runArgs_.systemResourcesPath,
275         runArgs_.appResourcesPath, runArgs_.themeId, runArgs_.deviceConfig.colorMode);
276 
277     auto view = new FlutterAceView(ACE_INSTANCE_ID);
278     if (runArgs_.aceVersion == AceVersion::ACE_2_0) {
279         AceContainer::SetView(view, runArgs_.deviceConfig.density, runArgs_.deviceWidth, runArgs_.deviceHeight);
280         AceContainer::RunPage(ACE_INSTANCE_ID, UNUSED_PAGE_ID, runArgs_.url, "");
281     } else {
282         AceContainer::RunPage(ACE_INSTANCE_ID, UNUSED_PAGE_ID, runArgs_.url, "");
283         AceContainer::SetView(view, runArgs_.deviceConfig.density, runArgs_.deviceWidth, runArgs_.deviceHeight);
284     }
285     if (runArgs_.projectModel == ProjectModel::STAGE) {
286         container->InitializeStageAppConfig(runArgs_.assetPath, runArgs_.formsEnabled);
287     }
288     AceContainer::AddRouterChangeCallback(ACE_INSTANCE_ID, runArgs_.onRouterChange);
289     OHOS::Ace::Framework::InspectorClient::GetInstance().RegisterFastPreviewErrorCallback(runArgs_.onError);
290     // Should make it possible to update surface changes by using viewWidth and viewHeight.
291     view->NotifySurfaceChanged(runArgs_.deviceWidth, runArgs_.deviceHeight);
292     view->NotifyDensityChanged(runArgs_.deviceConfig.density);
293 }
294 #else
InitEnv()295 void AceAbility::InitEnv()
296 {
297 #ifdef INIT_ICU_DATA_PATH
298     std::string icuPath = ".";
299     u_setDataDirectory(icuPath.c_str());
300 #endif
301     std::vector<std::string> paths;
302     paths.push_back(runArgs_.assetPath);
303     std::string appResourcesPath(runArgs_.appResourcesPath);
304     if (!OHOS::Ace::Framework::EndWith(appResourcesPath, DELIMITER)) {
305         appResourcesPath.append(DELIMITER);
306     }
307     if (runArgs_.projectModel == ProjectModel::STAGE) {
308         // eTS Card
309         if (runArgs_.aceVersion == AceVersion::ACE_2_0 && runArgs_.formsEnabled) {
310             paths.push_back(runArgs_.assetPath + DELIMITER + "ets");
311         }
312         paths.push_back(appResourcesPath);
313         paths.push_back(appResourcesPath + ASSET_PATH_SHARE_STAGE);
314     } else {
315         paths.push_back(GetCustomAssetPath(runArgs_.assetPath) + ASSET_PATH_SHARE);
316     }
317     AceContainer::AddAssetPath(ACE_INSTANCE_ID, "", paths);
318     auto container = AceContainer::GetContainerInstance(ACE_INSTANCE_ID);
319     CHECK_NULL_VOID(container);
320     if (runArgs_.projectModel == ProjectModel::STAGE) {
321         if (runArgs_.formsEnabled) {
322             container->SetStageCardConfig(runArgs_.pageProfile, runArgs_.url);
323         } else {
324             container->SetPageProfile((runArgs_.pageProfile.empty() ? "" : runArgs_.pageProfile + ".json"));
325         }
326     }
327     AceContainer::SetResourcesPathAndThemeStyle(ACE_INSTANCE_ID, runArgs_.systemResourcesPath,
328         runArgs_.appResourcesPath, runArgs_.themeId, runArgs_.deviceConfig.colorMode);
329 
330     auto view = new RSAceView(ACE_INSTANCE_ID);
331     if (runArgs_.aceVersion == AceVersion::ACE_2_0) {
332         AceContainer::SetView(view, runArgs_.deviceConfig.density, runArgs_.deviceWidth, runArgs_.deviceHeight, runArgs_.onRender);
333         AceContainer::RunPage(ACE_INSTANCE_ID, UNUSED_PAGE_ID, runArgs_.url, "");
334     } else {
335         AceContainer::RunPage(ACE_INSTANCE_ID, UNUSED_PAGE_ID, runArgs_.url, "");
336         AceContainer::SetView(view, runArgs_.deviceConfig.density, runArgs_.deviceWidth, runArgs_.deviceHeight, runArgs_.onRender);
337     }
338     if (runArgs_.projectModel == ProjectModel::STAGE) {
339         container->InitializeStageAppConfig(runArgs_.assetPath, runArgs_.formsEnabled);
340     }
341     AceContainer::AddRouterChangeCallback(ACE_INSTANCE_ID, runArgs_.onRouterChange);
342     OHOS::Ace::Framework::InspectorClient::GetInstance().RegisterFastPreviewErrorCallback(runArgs_.onError);
343     // Should make it possible to update surface changes by using viewWidth and viewHeight.
344     view->NotifySurfaceChanged(runArgs_.deviceWidth, runArgs_.deviceHeight);
345     view->NotifyDensityChanged(runArgs_.deviceConfig.density);
346 }
347 #endif
348 
Start()349 void AceAbility::Start()
350 {
351     RunEventLoop();
352 }
353 
Stop()354 void AceAbility::Stop()
355 {
356     auto container = AceContainer::GetContainerInstance(ACE_INSTANCE_ID);
357     if (!container) {
358         return;
359     }
360 
361     container->GetTaskExecutor()->PostTask([]() { loopRunning_ = false; }, TaskExecutor::TaskType::PLATFORM);
362 }
363 
364 #ifndef ENABLE_ROSEN_BACKEND
RunEventLoop()365 void AceAbility::RunEventLoop()
366 {
367     while (!FlutterDesktopWindowShouldClose(controller_) && loopRunning_) {
368         FlutterDesktopWaitForEvents(controller_);
369 #ifdef USE_GLFW_WINDOW
370         auto window = FlutterDesktopGetWindow(controller_);
371         int width;
372         int height;
373         FlutterDesktopGetWindowSize(window, &width, &height);
374         if (width != runArgs_.deviceWidth || height != runArgs_.deviceHeight) {
375             AdaptDeviceType(runArgs_);
376             SurfaceChanged(runArgs_.deviceConfig.orientation, runArgs_.deviceConfig.density, width, height);
377         }
378 #endif
379         auto container = AceContainer::GetContainerInstance(ACE_INSTANCE_ID);
380         if (container) {
381             container->RunNativeEngineLoop();
382         }
383 
384         std::this_thread::sleep_for(std::chrono::milliseconds(1));
385     }
386     loopRunning_ = true;
387 
388     // Currently exit loop is only to restart the AceContainer for real-time preview case.
389     // Previewer background thread will release the AceAbility instance and create new one,
390     // then call the InitEnv() and Start() again.
391     auto container = AceContainer::GetContainerInstance(ACE_INSTANCE_ID);
392     if (!container) {
393         LOGE("container is null");
394         FlutterDesktopDestroyWindow(controller_);
395         controller_ = nullptr;
396         return;
397     }
398     auto viewPtr = container->GetAceView();
399     AceContainer::DestroyContainer(ACE_INSTANCE_ID);
400 
401     FlutterDesktopDestroyWindow(controller_);
402     if (viewPtr != nullptr) {
403         delete viewPtr;
404         viewPtr = nullptr;
405     }
406     controller_ = nullptr;
407 }
408 #else
RunEventLoop()409 void AceAbility::RunEventLoop()
410 {
411     while (controller_ != nullptr && !controller_->WindowShouldClose() && loopRunning_) {
412         if (windowControllerRef_) {
413             FlutterDesktopWaitForEvents(windowControllerRef_);
414         }
415         controller_->PollEvents();
416 
417 #ifdef USE_GLFW_WINDOW
418         int32_t width;
419         int32_t height;
420         controller_->GetWindowSize(width, height);
421         if (width != runArgs_.deviceWidth || height != runArgs_.deviceHeight) {
422             AdaptDeviceType(runArgs_);
423             SurfaceChanged(runArgs_.deviceConfig.orientation, runArgs_.deviceConfig.density, width, height);
424         }
425 #endif
426 
427         auto container = AceContainer::GetContainerInstance(ACE_INSTANCE_ID);
428         if (container) {
429             container->RunNativeEngineLoop();
430         }
431 
432         std::this_thread::sleep_for(std::chrono::milliseconds(1));
433     }
434     loopRunning_ = true;
435 
436     // Currently exit loop is only to restart the AceContainer for real-time preview case.
437     // Previewer background thread will release the AceAbility instance and create new one,
438     // then call the InitEnv() and Start() again.
439     auto container = AceContainer::GetContainerInstance(ACE_INSTANCE_ID);
440     if (!container) {
441         LOGE("container is null");
442         if (controller_ != nullptr) {
443             controller_->DestroyWindow();
444         }
445         controller_ = nullptr;
446         return;
447     }
448     auto viewPtr = container->GetAceView();
449     AceContainer::DestroyContainer(ACE_INSTANCE_ID);
450 
451     if (controller_ != nullptr) {
452         controller_->DestroyWindow();
453     }
454     if (viewPtr != nullptr) {
455         delete viewPtr;
456         viewPtr = nullptr;
457     }
458     controller_ = nullptr;
459 }
460 #endif
461 
SetConfigChanges(const std::string & configChanges)462 void AceAbility::SetConfigChanges(const std::string& configChanges)
463 {
464     if (configChanges == "") {
465         return;
466     }
467     std::vector<std::string> configChangesSplitter;
468     OHOS::Ace::StringUtils::StringSplitter(configChanges, ',', configChangesSplitter);
469     for (const auto& singleConfig : configChangesSplitter) {
470         if (singleConfig == "locale") {
471             configChanges_.watchLocale = true;
472             continue;
473         } else if (singleConfig == "layout") {
474             configChanges_.watchLayout = true;
475             continue;
476         } else if (singleConfig == "fontSize") {
477             configChanges_.watchFontSize = true;
478             continue;
479         } else if (singleConfig == "orientation") {
480             configChanges_.watchOrientation = true;
481             continue;
482         } else if (singleConfig == "density") {
483             configChanges_.watchDensity = true;
484             continue;
485         } else {
486             LOGW("unsupported config %{public}s", singleConfig.c_str());
487         }
488     }
489 }
490 
OnConfigurationChanged(const DeviceConfig & newConfig)491 void AceAbility::OnConfigurationChanged(const DeviceConfig& newConfig)
492 {
493     if (newConfig.colorMode == runArgs_.deviceConfig.colorMode) {
494         return;
495     }
496     int32_t width = runArgs_.deviceWidth;
497     int32_t height = runArgs_.deviceHeight;
498     SurfaceChanged(runArgs_.deviceConfig.orientation, runArgs_.deviceConfig.density, width, height);
499     auto container = AceContainer::GetContainerInstance(ACE_INSTANCE_ID);
500     if (!container) {
501         LOGE("container is null, change configuration failed.");
502         return;
503     }
504     container->UpdateDeviceConfig(newConfig);
505     runArgs_.deviceConfig.colorMode = newConfig.colorMode;
506     if (container->GetType() == FrontendType::DECLARATIVE_JS) {
507         container->NativeOnConfigurationUpdated(ACE_INSTANCE_ID);
508     }
509 }
510 
SurfaceChanged(const DeviceOrientation & orientation,const double & resolution,int32_t & width,int32_t & height)511 void AceAbility::SurfaceChanged(
512     const DeviceOrientation& orientation, const double& resolution, int32_t& width, int32_t& height)
513 {
514     auto container = AceContainer::GetContainerInstance(ACE_INSTANCE_ID);
515     if (!container) {
516         LOGE("container is null, SurfaceChanged failed.");
517         return;
518     }
519 
520     auto viewPtr = container->GetAceView();
521     if (viewPtr == nullptr) {
522         LOGE("aceView is null, SurfaceChanged failed.");
523         return;
524     }
525     // Need to change the window resolution and then change the rendering resolution. Otherwise, the image may not adapt
526     // to the new window after the window is modified.
527     auto context = container->GetPipelineContext();
528     if (context == nullptr) {
529         LOGE("context is null, SurfaceChanged failed.");
530         return;
531     }
532 #ifndef ENABLE_ROSEN_BACKEND
533     auto window = FlutterDesktopGetWindow(controller_);
534     context->GetTaskExecutor()->PostSyncTask(
535         [window, &width, &height]() { FlutterDesktopSetWindowSize(window, width, height); },
536         TaskExecutor::TaskType::PLATFORM);
537 #else
538     context->GetTaskExecutor()->PostSyncTask(
539         [this, width, height]() {
540             if (controller_ != nullptr) {
541                 controller_->SetWindowSize(width, height);
542             }
543         },
544         TaskExecutor::TaskType::PLATFORM);
545 #endif
546     SystemProperties::InitDeviceInfo(
547         width, height, orientation == DeviceOrientation::PORTRAIT ? 0 : 1, resolution, runArgs_.isRound);
548     DeviceConfig deviceConfig = runArgs_.deviceConfig;
549     deviceConfig.orientation = orientation;
550     deviceConfig.density = resolution;
551     container->UpdateDeviceConfig(deviceConfig);
552     viewPtr->NotifyDensityChanged(resolution);
553     viewPtr->NotifySurfaceChanged(width, height);
554     if ((orientation != runArgs_.deviceConfig.orientation && configChanges_.watchOrientation) ||
555         (resolution != runArgs_.deviceConfig.density && configChanges_.watchDensity) ||
556         ((width != runArgs_.deviceWidth || height != runArgs_.deviceHeight) && configChanges_.watchLayout)) {
557         container->NativeOnConfigurationUpdated(ACE_INSTANCE_ID);
558     }
559     runArgs_.deviceConfig.orientation = orientation;
560     runArgs_.deviceConfig.density = resolution;
561     runArgs_.deviceWidth = width;
562     runArgs_.deviceHeight = height;
563 }
564 
ReplacePage(const std::string & url,const std::string & params)565 void AceAbility::ReplacePage(const std::string& url, const std::string& params)
566 {
567     auto container = AceContainer::GetContainerInstance(ACE_INSTANCE_ID);
568     if (!container) {
569         LOGE("container is null");
570         return;
571     }
572     container->GetFrontend()->ReplacePage(url, params);
573 }
574 
LoadDocument(const std::string & url,const std::string & componentName,SystemParams & systemParams)575 void AceAbility::LoadDocument(const std::string& url, const std::string& componentName, SystemParams& systemParams)
576 {
577     AceApplicationInfo::GetInstance().ChangeLocale(systemParams.language, systemParams.region);
578     runArgs_.isRound = systemParams.isRound;
579     SurfaceChanged(systemParams.orientation, systemParams.density, systemParams.deviceWidth, systemParams.deviceHeight);
580     DeviceConfig deviceConfig = {
581         .orientation = systemParams.orientation,
582         .density = systemParams.density,
583         .deviceType = systemParams.deviceType,
584         .colorMode = systemParams.colorMode,
585     };
586     OnConfigurationChanged(deviceConfig);
587     auto container = AceContainer::GetContainerInstance(ACE_INSTANCE_ID);
588     if (!container) {
589         LOGE("container is null");
590         return;
591     }
592     container->LoadDocument(url, componentName);
593 }
594 
GetJSONTree()595 std::string AceAbility::GetJSONTree()
596 {
597     std::string jsonTreeStr;
598     auto container = AceContainer::GetContainerInstance(ACE_INSTANCE_ID);
599     CHECK_NULL_RETURN(container, "");
600     auto taskExecutor = container->GetTaskExecutor();
601     CHECK_NULL_RETURN(taskExecutor, "");
602     taskExecutor->PostSyncTask([&jsonTreeStr] {
603             OHOS::Ace::Framework::InspectorClient::GetInstance().AssembleJSONTreeStr(jsonTreeStr);
604         }, TaskExecutor::TaskType::UI);
605     return jsonTreeStr;
606 }
607 
GetDefaultJSONTree()608 std::string AceAbility::GetDefaultJSONTree()
609 {
610     std::string defaultJsonTreeStr;
611     auto container = AceContainer::GetContainerInstance(ACE_INSTANCE_ID);
612     CHECK_NULL_RETURN(container, "");
613     auto taskExecutor = container->GetTaskExecutor();
614     CHECK_NULL_RETURN(taskExecutor, "");
615     taskExecutor->PostSyncTask([&defaultJsonTreeStr] {
616             OHOS::Ace::Framework::InspectorClient::GetInstance().AssembleDefaultJSONTreeStr(defaultJsonTreeStr);
617         }, TaskExecutor::TaskType::UI);
618     return defaultJsonTreeStr;
619 }
620 
OperateComponent(const std::string & attrsJson)621 bool AceAbility::OperateComponent(const std::string& attrsJson)
622 {
623     LOGD("OperateComponent attrsJson %{public}s", attrsJson.c_str());
624     auto root = JsonUtil::ParseJsonString(attrsJson);
625     if (!root || !root->IsValid()) {
626         LOGE("the attrsJson is illegal json format");
627         return false;
628     }
629 
630     auto container = AceContainer::GetContainerInstance(ACE_INSTANCE_ID);
631     if (!container) {
632         return false;
633     }
634     auto taskExecutor = container->GetTaskExecutor();
635     if (!taskExecutor) {
636         return false;
637     }
638     taskExecutor->PostTask(
639         [attrsJson, instanceId = ACE_INSTANCE_ID] {
640             ContainerScope scope(instanceId);
641             bool result = OHOS::Ace::Framework::InspectorClient::GetInstance().OperateComponent(attrsJson);
642             if (!result) {
643                 OHOS::Ace::Framework::InspectorClient::GetInstance().CallFastPreviewErrorCallback(attrsJson);
644             }
645         },
646         TaskExecutor::TaskType::UI);
647     return true;
648 }
649 
650 } // namespace OHOS::Ace::Platform
651