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