1 /*
2 * Copyright (c) 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/ui_content_impl.h"
17
18 #include <ui/rs_surface_node.h>
19 #include <ui/rs_ui_director.h>
20
21 #include "include/core/SkFontMgr.h"
22
23 #include "adapter/ohos/entrance/ace_new_pipe_judgement.h"
24 #include "adapter/ohos/entrance/platform_event_callback.h"
25 #include "adapter/preview/entrance/ace_application_info.h"
26 #include "adapter/preview/entrance/ace_container.h"
27 #include "adapter/preview/entrance/clipboard/clipboard_impl.h"
28 #include "adapter/preview/entrance/clipboard/clipboard_proxy_impl.h"
29 #include "adapter/preview/entrance/event_dispatcher.h"
30 #include "adapter/preview/entrance/rs_dir_asset_provider.h"
31 #include "adapter/preview/external/multimodalinput/axis_event.h"
32 #include "adapter/preview/external/multimodalinput/key_event.h"
33 #include "adapter/preview/external/multimodalinput/pointer_event.h"
34 #include "adapter/preview/inspector/inspector_client.h"
35 #include "frameworks/base/log/log.h"
36 #include "frameworks/base/utils/utils.h"
37 #include "frameworks/bridge/common/utils/utils.h"
38 #include "frameworks/bridge/js_frontend/js_frontend.h"
39 #ifdef INIT_ICU_DATA_PATH
40 #include "unicode/putil.h"
41 #endif
42
43 #include "frameworks/simulator/common/include/context.h"
44
45 namespace OHOS::Ace {
46
47 using namespace Platform;
48
49 namespace {
50
51 constexpr int32_t UNUSED_PAGE_ID = 1;
52
53 #ifdef WINDOWS_PLATFORM
54 constexpr char DELIMITER[] = "\\";
55 constexpr char ASSET_PATH_SHARE_STAGE[] = "resources\\base\\profile";
56 #else
57 constexpr char DELIMITER[] = "/";
58 constexpr char ASSET_PATH_SHARE_STAGE[] = "resources/base/profile";
59 #endif
60
SetFontMgrConfig(const std::string & containerSdkPath)61 void SetFontMgrConfig(const std::string& containerSdkPath)
62 {
63 // To check if use ohos or container fonts.
64 std::string runtimeOS = "OHOS_Container";
65 std::string containerFontBasePath = containerSdkPath + DELIMITER + "resources" + DELIMITER + "fonts" + DELIMITER;
66 RSDirAssetProvider dirAsset(containerFontBasePath);
67 std::vector<std::string> fileList;
68 dirAsset.GetAssetList("", fileList);
69 if (containerSdkPath.empty() || fileList.empty()) {
70 runtimeOS = "OHOS";
71 containerFontBasePath = "";
72 }
73 LOGI("Runtime OS is %{public}s, and the container fontBasePath is %{public}s", runtimeOS.c_str(),
74 containerFontBasePath.c_str());
75 SkFontMgr::SetFontMgrConfig(runtimeOS, containerFontBasePath);
76 }
77
78 } // namespace
79
80 using ContentFinishCallback = std::function<void()>;
81 using ContentStartAbilityCallback = std::function<void(const std::string& address)>;
82 class ContentEventCallback final : public PlatformEventCallback {
83 public:
ContentEventCallback(ContentFinishCallback onFinish)84 explicit ContentEventCallback(ContentFinishCallback onFinish) : onFinish_(onFinish) {}
ContentEventCallback(ContentFinishCallback onFinish,ContentStartAbilityCallback onStartAbility)85 ContentEventCallback(ContentFinishCallback onFinish, ContentStartAbilityCallback onStartAbility)
86 : onFinish_(onFinish), onStartAbility_(onStartAbility)
87 {}
88 ~ContentEventCallback() override = default;
89
OnFinish() const90 void OnFinish() const override
91 {
92 LOGI("UIContent OnFinish");
93 CHECK_NULL_VOID_NOLOG(onFinish_);
94 onFinish_();
95 }
96
OnStartAbility(const std::string & address)97 void OnStartAbility(const std::string& address) override
98 {
99 LOGI("UIContent OnStartAbility");
100 CHECK_NULL_VOID_NOLOG(onStartAbility_);
101 onStartAbility_(address);
102 }
103
OnStatusBarBgColorChanged(uint32_t color)104 void OnStatusBarBgColorChanged(uint32_t color) override
105 {
106 LOGI("UIContent OnStatusBarBgColorChanged");
107 }
108
109 private:
110 ContentFinishCallback onFinish_;
111 ContentStartAbilityCallback onStartAbility_;
112 };
113
114 class DragWindowListener : public OHOS::Rosen::IWindowDragListener {
115 public:
DragWindowListener(int32_t instanceId)116 explicit DragWindowListener(int32_t instanceId) : instanceId_(instanceId) {}
117 ~DragWindowListener() = default;
OnDrag(int32_t x,int32_t y,OHOS::Rosen::DragEvent event)118 void OnDrag(int32_t x, int32_t y, OHOS::Rosen::DragEvent event)
119 {
120 LOGI("[Engine Log] The feature is not supported on the previewer, and instanceId_ = %{public}d", instanceId_);
121 }
122
123 private:
124 int32_t instanceId_ = -1;
125 };
126
127 class TouchOutsideListener : public OHOS::Rosen::ITouchOutsideListener {
128 public:
TouchOutsideListener(int32_t instanceId)129 explicit TouchOutsideListener(int32_t instanceId) : instanceId_(instanceId) {}
130 ~TouchOutsideListener() = default;
131
OnTouchOutside() const132 void OnTouchOutside() const
133 {
134 LOGI("[Engine Log] The feature is not supported on the previewer, and instanceId_ = %{public}d", instanceId_);
135 }
136
137 private:
138 int32_t instanceId_ = -1;
139 };
140
OHOS_ACE_CreateUIContent(void * context,void * runtime)141 extern "C" ACE_FORCE_EXPORT void* OHOS_ACE_CreateUIContent(void* context, void* runtime)
142 {
143 LOGI("Ace lib loaded, CreateUIContent.");
144 return new UIContentImpl(reinterpret_cast<OHOS::AbilityRuntime::Context*>(context), runtime);
145 }
146
OHOS_ACE_CreateFormContent(void * context,void * runtime,bool isCard)147 extern "C" ACE_FORCE_EXPORT void* OHOS_ACE_CreateFormContent(void* context, void* runtime, bool isCard)
148 {
149 LOGI("Ace lib loaded, CreateFormUIContent.");
150 return new UIContentImpl(reinterpret_cast<OHOS::AbilityRuntime::Context*>(context), runtime, isCard);
151 }
152
OHOS_ACE_CreateSubWindowUIContent(void * ability)153 extern "C" ACE_FORCE_EXPORT void* OHOS_ACE_CreateSubWindowUIContent(void* ability)
154 {
155 LOGI("Ace lib loaded, Create SubWindowUIContent.");
156 return new UIContentImpl(reinterpret_cast<OHOS::AppExecFwk::Ability*>(ability));
157 }
158
UIContentImpl(OHOS::AbilityRuntime::Context * context,void * runtime)159 UIContentImpl::UIContentImpl(OHOS::AbilityRuntime::Context* context, void* runtime)
160 : instanceId_(ACE_INSTANCE_ID), runtime_(runtime)
161 {
162 // 基于Options的方式传递参数
163 auto options = context->GetOptions();
164 assetPath_ = options.assetPath;
165 systemResourcesPath_ = options.systemResourcePath;
166 appResourcesPath_ = options.appResourcePath;
167 containerSdkPath_ = options.containerSdkPath;
168 language_ = options.language;
169 region_ = options.region;
170 script_ = options.script;
171 themeId_ = options.themeId;
172 deviceWidth_ = options.deviceWidth;
173 deviceHeight_ = options.deviceHeight;
174 isRound_ = options.isRound;
175 onRouterChange_ = options.onRouterChange;
176 deviceConfig_.orientation = static_cast<DeviceOrientation>(options.deviceConfig.orientation);
177 deviceConfig_.deviceType = static_cast<DeviceType>(options.deviceConfig.deviceType);
178 deviceConfig_.colorMode = static_cast<ColorMode>(options.deviceConfig.colorMode);
179 deviceConfig_.density = options.deviceConfig.density;
180 deviceConfig_.fontRatio = options.deviceConfig.fontRatio;
181
182 bundleName_ = options.bundleName;
183 compatibleVersion_ = options.compatibleVersion;
184 installationFree_ = options.installationFree;
185 labelId_ = options.labelId;
186 moduleName_ = options.moduleName;
187 compileMode_ = options.compileMode;
188 pageProfile_ = options.pageProfile;
189 const std::string profilePrefix = "$profile:";
190 if (pageProfile_.compare(0, profilePrefix.size(), profilePrefix) == 0) {
191 pageProfile_ = pageProfile_.substr(profilePrefix.length()).append(".json");
192 }
193 auto targetVersion = options.targetVersion;
194 auto releaseType = options.releaseType;
195 bool enablePartialUpdate = options.enablePartialUpdate;
196 useNewPipeline_ = AceNewPipeJudgement::QueryAceNewPipeEnabledStage(
197 "", compatibleVersion_, targetVersion, releaseType, !enablePartialUpdate);
198 }
199
UIContentImpl(OHOS::AbilityRuntime::Context * context,void * runtime,bool isCard)200 UIContentImpl::UIContentImpl(OHOS::AbilityRuntime::Context* context, void* runtime, bool isCard)
201 : instanceId_(ACE_INSTANCE_ID), runtime_(runtime), isFormRender_(isCard)
202 {
203 LOGI("The constructor is used to support ets card, isFormRender_ = %{public}d", isFormRender_);
204 }
205
UIContentImpl(OHOS::AppExecFwk::Ability * ability)206 UIContentImpl::UIContentImpl(OHOS::AppExecFwk::Ability* ability) : instanceId_(ACE_INSTANCE_ID) {}
207
DestroyUIDirector()208 void UIContentImpl::DestroyUIDirector()
209 {
210 auto container = AceContainer::GetContainerInstance(instanceId_);
211 CHECK_NULL_VOID_NOLOG(container);
212 auto pipelineContext = AceType::DynamicCast<PipelineContext>(container->GetPipelineContext());
213 CHECK_NULL_VOID_NOLOG(pipelineContext);
214 auto rsUIDirector = pipelineContext->GetRSUIDirector();
215 CHECK_NULL_VOID_NOLOG(rsUIDirector);
216 rsUIDirector->Destroy();
217 }
218
DestroyCallback() const219 void UIContentImpl::DestroyCallback() const
220 {
221 auto container = AceContainer::GetContainerInstance(instanceId_);
222 CHECK_NULL_VOID(container);
223 auto pipelineContext = container->GetPipelineContext();
224 CHECK_NULL_VOID(pipelineContext);
225 pipelineContext->SetNextFrameLayoutCallback(nullptr);
226 }
227
Initialize(OHOS::Rosen::Window * window,const std::string & url,NativeValue * storage)228 void UIContentImpl::Initialize(OHOS::Rosen::Window* window, const std::string& url, NativeValue* storage)
229 {
230 CommonInitialize(window, url, storage);
231 AceContainer::RunPage(instanceId_, UNUSED_PAGE_ID, url, "");
232 }
233
GetContentInfo() const234 std::string UIContentImpl::GetContentInfo() const
235 {
236 LOGI("UIContent GetContentInfo");
237 return AceContainer::GetContentInfo(instanceId_);
238 }
239
CommonInitialize(OHOS::Rosen::Window * window,const std::string & contentInfo,NativeValue * storage)240 void UIContentImpl::CommonInitialize(OHOS::Rosen::Window* window, const std::string& contentInfo, NativeValue* storage)
241 {
242 static std::once_flag onceFlag;
243 std::call_once(onceFlag, []() {
244 LOGI("Initialize for current process.");
245 #ifdef INIT_ICU_DATA_PATH
246 std::string icuPath = ".";
247 u_setDataDirectory(icuPath.c_str());
248 #endif
249 Container::UpdateCurrent(INSTANCE_ID_PLATFORM);
250 ClipboardProxy::GetInstance()->SetDelegate(std::make_unique<Platform::ClipboardProxyImpl>());
251 });
252 rsWindow_ = window;
253
254 AceApplicationInfo::GetInstance().SetLocale(language_, region_, script_, "");
255 SetFontMgrConfig(containerSdkPath_);
256 EventDispatcher::GetInstance().Initialize();
257 SystemProperties::SetExtSurfaceEnabled(!containerSdkPath_.empty());
258 SystemProperties::InitDeviceInfo(deviceWidth_, deviceHeight_,
259 deviceConfig_.orientation == DeviceOrientation::PORTRAIT ? 0 : 1, deviceConfig_.density, isRound_);
260 SystemProperties::InitDeviceType(deviceConfig_.deviceType);
261 SystemProperties::SetColorMode(deviceConfig_.colorMode);
262 LOGI("CreateContainer with JSDECLARATIVE frontend");
263 AceContainer::CreateContainer(instanceId_, FrontendType::DECLARATIVE_JS, useNewPipeline_);
264 auto container = AceContainer::GetContainerInstance(instanceId_);
265 CHECK_NULL_VOID(container);
266 container->SetContainerSdkPath(containerSdkPath_);
267 container->SetIsFRSCardContainer(false);
268 if (runtime_) {
269 container->GetSettings().SetUsingSharedRuntime(true);
270 container->SetSharedRuntime(runtime_);
271 } else {
272 container->GetSettings().SetUsingSharedRuntime(false);
273 }
274 container->SetInstallationFree(installationFree_);
275 container->SetLabelId(labelId_);
276 auto config = container->GetResourceConfiguration();
277 config.SetDeviceType(SystemProperties::GetDeviceType());
278 config.SetOrientation(SystemProperties::GetDeviceOrientation());
279 config.SetDensity(SystemProperties::GetResolution());
280 config.SetColorMode(SystemProperties::GetColorMode());
281 config.SetFontRatio(deviceConfig_.fontRatio);
282 container->SetResourceConfiguration(config);
283 container->SetPageProfile(pageProfile_);
284 std::vector<std::string> paths;
285 paths.push_back(assetPath_);
286 std::string appResourcesPath(appResourcesPath_);
287 if (!OHOS::Ace::Framework::EndWith(appResourcesPath, DELIMITER)) {
288 appResourcesPath.append(DELIMITER);
289 }
290 paths.push_back(appResourcesPath);
291 paths.push_back(appResourcesPath + ASSET_PATH_SHARE_STAGE);
292 if (!containerSdkPath_.empty()) {
293 paths.push_back(containerSdkPath_);
294 }
295 AceContainer::AddAssetPath(instanceId_, "", paths);
296 AceContainer::SetResourcesPathAndThemeStyle(
297 instanceId_, systemResourcesPath_ + "/entry", appResourcesPath_, themeId_, deviceConfig_.colorMode);
298
299 auto view = AceViewPreview::CreateView(instanceId_, false, container->GetSettings().usePlatformAsUIThread);
300 UIEnvCallback callback = [window = rsWindow_, id = instanceId_](
301 const OHOS::Ace::RefPtr<PipelineContext>& context) mutable {
302 CHECK_NULL_VOID(context);
303 CHECK_NULL_VOID(window);
304 auto director = OHOS::Rosen::RSUIDirector::Create();
305 CHECK_NULL_VOID(director);
306 director->SetRSSurfaceNode(window->GetSurfaceNode());
307 auto container = AceContainer::GetContainerInstance(id);
308 CHECK_NULL_VOID(container);
309 auto func = [taskExecutor = container->GetTaskExecutor(), id](const std::function<void()>& task) {
310 CHECK_NULL_VOID(taskExecutor);
311 ContainerScope scope(id);
312 taskExecutor->PostTask(task, TaskExecutor::TaskType::UI);
313 };
314 director->SetUITaskRunner(func);
315 director->Init();
316 context->SetRSUIDirector(director);
317 };
318 AceContainer::SetView(view, rsWindow_, deviceConfig_.density, deviceWidth_, deviceHeight_, callback);
319 // Drive the native engine with the platform thread.
320 container->RunNativeEngineLoop();
321 auto pipelineContext = container->GetPipelineContext();
322 if (pipelineContext) {
323 LOGI("Set MinPlatformVersion to %{public}d", compatibleVersion_);
324 pipelineContext->SetMinPlatformVersion(compatibleVersion_);
325 }
326 container->InitializeStageAppConfig(assetPath_, bundleName_, moduleName_, compileMode_);
327 AceContainer::AddRouterChangeCallback(instanceId_, onRouterChange_);
328 // Should make it possible to update surface changes by using viewWidth and viewHeight.
329 view->NotifySurfaceChanged(deviceWidth_, deviceHeight_);
330 view->NotifyDensityChanged(deviceConfig_.density);
331 }
332
Destroy()333 void UIContentImpl::Destroy()
334 {
335 LOGI("UIContentImpl: window destroy");
336 AceContainer::DestroyContainer(instanceId_);
337 }
338
GetBackgroundColor()339 uint32_t UIContentImpl::GetBackgroundColor()
340 {
341 auto container = AceContainer::GetContainerInstance(instanceId_);
342 CHECK_NULL_RETURN(container, 0x000000);
343 auto taskExecutor = container->GetTaskExecutor();
344 CHECK_NULL_RETURN(taskExecutor, 0x000000);
345 ContainerScope scope(instanceId_);
346 uint32_t bgColor = 0x000000;
347 taskExecutor->PostSyncTask(
348 [&bgColor, container]() {
349 CHECK_NULL_VOID(container);
350 auto pipelineContext = container->GetPipelineContext();
351 CHECK_NULL_VOID(pipelineContext);
352 bgColor = pipelineContext->GetAppBgColor().GetValue();
353 },
354 TaskExecutor::TaskType::UI);
355
356 LOGI("UIContentImpl::GetBackgroundColor, value is %{public}u", bgColor);
357 return bgColor;
358 }
359
SetBackgroundColor(uint32_t color)360 void UIContentImpl::SetBackgroundColor(uint32_t color)
361 {
362 LOGI("UIContentImpl: SetBackgroundColor color is %{public}u", color);
363 auto container = AceContainer::GetContainerInstance(instanceId_);
364 CHECK_NULL_VOID(container);
365 ContainerScope scope(instanceId_);
366 auto taskExecutor = container->GetTaskExecutor();
367 CHECK_NULL_VOID(taskExecutor);
368 taskExecutor->PostSyncTask(
369 [container, bgColor = color]() {
370 auto pipelineContext = container->GetPipelineContext();
371 CHECK_NULL_VOID(pipelineContext);
372 pipelineContext->SetAppBgColor(Color(bgColor));
373 },
374 TaskExecutor::TaskType::UI);
375 }
376
ProcessBackPressed()377 bool UIContentImpl::ProcessBackPressed()
378 {
379 LOGI("Process Back Pressed Event");
380 return EventDispatcher::GetInstance().DispatchBackPressedEvent();
381 }
382
ProcessPointerEvent(const std::shared_ptr<OHOS::MMI::PointerEvent> & pointerEvent)383 bool UIContentImpl::ProcessPointerEvent(const std::shared_ptr<OHOS::MMI::PointerEvent>& pointerEvent)
384 {
385 LOGI("Process MMI::PointerEvent");
386 return EventDispatcher::GetInstance().DispatchTouchEvent(pointerEvent);
387 }
388
ProcessKeyEvent(const std::shared_ptr<OHOS::MMI::KeyEvent> & keyEvent)389 bool UIContentImpl::ProcessKeyEvent(const std::shared_ptr<OHOS::MMI::KeyEvent>& keyEvent)
390 {
391 LOGI("Process MMI::KeyEvent");
392 return EventDispatcher::GetInstance().DispatchKeyEvent(keyEvent);
393 }
394
ProcessAxisEvent(const std::shared_ptr<OHOS::MMI::AxisEvent> & axisEvent)395 bool UIContentImpl::ProcessAxisEvent(const std::shared_ptr<OHOS::MMI::AxisEvent>& axisEvent)
396 {
397 LOGI("Process MMI::AxisEvent");
398 return false;
399 }
400
ProcessVsyncEvent(uint64_t timeStampNanos)401 bool UIContentImpl::ProcessVsyncEvent(uint64_t timeStampNanos)
402 {
403 LOGI("Process VsyncEvent");
404 return false;
405 }
406
UpdateConfiguration(const std::shared_ptr<OHOS::AppExecFwk::Configuration> & config)407 void UIContentImpl::UpdateConfiguration(const std::shared_ptr<OHOS::AppExecFwk::Configuration>& config) {}
408
UpdateViewportConfig(const ViewportConfig & config,OHOS::Rosen::WindowSizeChangeReason reason,const std::shared_ptr<OHOS::Rosen::RSTransaction> & rsTransaction)409 void UIContentImpl::UpdateViewportConfig(const ViewportConfig& config, OHOS::Rosen::WindowSizeChangeReason reason,
410 const std::shared_ptr<OHOS::Rosen::RSTransaction>& rsTransaction)
411 {
412 LOGI("ViewportConfig: %{public}s", config.ToString().c_str());
413 auto container = AceContainer::GetContainerInstance(instanceId_);
414 CHECK_NULL_VOID(container);
415 auto viewPtr = container->GetAceView();
416 CHECK_NULL_VOID(viewPtr);
417 SystemProperties::InitDeviceInfo(
418 config.Width(), config.Height(), config.Height() >= config.Width() ? 0 : 1, config.Density(), false);
419 deviceConfig_.orientation =
420 config.Height() >= config.Width() ? DeviceOrientation::PORTRAIT : DeviceOrientation::LANDSCAPE;
421 deviceConfig_.density = config.Density();
422 // Unlike the real machine, previewer require updating device configuration information to change window size.
423 container->UpdateDeviceConfig(deviceConfig_);
424 viewPtr->NotifyDensityChanged(config.Density());
425 viewPtr->NotifySurfaceChanged(config.Width(), config.Height());
426 }
427
DumpInfo(const std::vector<std::string> & params,std::vector<std::string> & info)428 void UIContentImpl::DumpInfo(const std::vector<std::string>& params, std::vector<std::string>& info)
429 {
430 auto container = AceContainer::GetContainerInstance(instanceId_);
431 CHECK_NULL_VOID(container);
432 container->Dump(params, info);
433 }
434
SetNextFrameLayoutCallback(std::function<void ()> && callback)435 void UIContentImpl::SetNextFrameLayoutCallback(std::function<void()>&& callback)
436 {
437 CHECK_NULL_VOID(callback);
438 auto container = AceContainer::GetContainerInstance(instanceId_);
439 CHECK_NULL_VOID(container);
440 auto pipelineContext = container->GetPipelineContext();
441 CHECK_NULL_VOID(pipelineContext);
442 pipelineContext->SetNextFrameLayoutCallback(std::move(callback));
443 }
444
NotifyMemoryLevel(int32_t level)445 void UIContentImpl::NotifyMemoryLevel(int32_t level)
446 {
447 LOGI("Receive Memory level notification, level: %{public}d", level);
448 auto container = AceContainer::GetContainerInstance(instanceId_);
449 CHECK_NULL_VOID(container);
450 auto pipelineContext = container->GetPipelineContext();
451 CHECK_NULL_VOID(pipelineContext);
452 ContainerScope scope(instanceId_);
453 pipelineContext->NotifyMemoryLevel(level);
454 }
455
CreateModalUIExtension(const AAFwk::Want & want,const ModalUIExtensionCallbacks & callbacks)456 int32_t UIContentImpl::CreateModalUIExtension(const AAFwk::Want& want, const ModalUIExtensionCallbacks& callbacks)
457 {
458 return 0;
459 }
460
CloseModalUIExtension(int32_t sessionId)461 void UIContentImpl::CloseModalUIExtension(int32_t sessionId) {}
462 } // namespace OHOS::Ace
463