1 /*
2 * Copyright (c) 2025 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 "ability_info.h"
17 #include "ability_context.h"
18 #include "ui_extension_context.h"
19
20 #include "adapter/ohos/entrance/ace_container.h"
21 #include "adapter/ohos/entrance/ace_application_info.h"
22 #include "adapter/ohos/entrance/ace_view_ohos.h"
23 #include "adapter/ohos/entrance/hap_asset_provider_impl.h"
24 #include "adapter/ohos/entrance/file_asset_provider_impl.h"
25 #include "frameworks/base/i18n/localization.h"
26 #include "frameworks/core/common/ace_engine.h"
27 #include "frameworks/core/common/ace_view.h"
28 #include "frameworks/core/common/asset_manager_impl.h"
29 #include "frameworks/core/common/window_free_container.h"
30 #include "frameworks/core/components_ng/render/adapter/rosen_window.h"
31
32 namespace OHOS::Ace::Platform {
33 namespace {
34 static RefPtr<Platform::AceContainer> g_WindowFreeContainer = nullptr;
35
36 constexpr char ABS_BUNDLE_CODE_PATH[] = "/data/app/el1/bundle/public/";
37 constexpr char LOCAL_BUNDLE_CODE_PATH[] = "/data/storage/el1/bundle/";
38 constexpr char FILE_SEPARATOR[] = "/";
39
40 }
41
42 class PseudoEventCallback final : public Platform::PlatformEventCallback {
43 public:
44 PseudoEventCallback() = default;
45 virtual ~PseudoEventCallback() = default;
OnFinish() const46 void OnFinish() const override {}
OnStatusBarBgColorChanged(uint32_t)47 void OnStatusBarBgColorChanged(uint32_t) override {}
48 };
49
InitAssetManager(RefPtr<AssetManagerImpl> & assetManagerImpl,std::shared_ptr<OHOS::AppExecFwk::AbilityInfo> info,std::shared_ptr<OHOS::AbilityRuntime::Context> context)50 void InitAssetManager(RefPtr<AssetManagerImpl> &assetManagerImpl, std::shared_ptr<OHOS::AppExecFwk::AbilityInfo> info,
51 std::shared_ptr<OHOS::AbilityRuntime::Context> context)
52 {
53 if (!assetManagerImpl) {
54 return;
55 }
56
57 bool isModelJson = info != nullptr ? info->isModuleJson : false;
58 if (!isModelJson) {
59 LOGW("The application doesn't use module.json5.");
60 return;
61 }
62
63 std::string moduleName = info != nullptr ? info->moduleName : "";
64 auto appInfo = context != nullptr ? context->GetApplicationInfo() : nullptr;
65 auto hapModuleInfo = context != nullptr ? context->GetHapModuleInfo() : nullptr;
66 auto bundleName = info != nullptr ? info->bundleName : "";
67 std::string resPath;
68
69 std::string hapPath = info != nullptr ? info->hapPath : "";
70 // first use hap provider
71 if (!hapPath.empty()) {
72 auto hapAssetProviderImpl = AceType::MakeRefPtr<HapAssetProviderImpl>();
73 if (hapAssetProviderImpl->Initialize(hapPath, { "", "ets/", "resources/base/profile/" })) {
74 assetManagerImpl->PushBack(std::move(hapAssetProviderImpl));
75 }
76 }
77
78 if (appInfo) {
79 std::vector<OHOS::AppExecFwk::ModuleInfo> moduleList = appInfo->moduleInfos;
80 for (const auto& module : moduleList) {
81 if (module.moduleName == moduleName) {
82 std::regex pattern(ABS_BUNDLE_CODE_PATH + bundleName + FILE_SEPARATOR);
83 auto moduleSourceDir =
84 std::regex_replace(module.moduleSourceDir, pattern, LOCAL_BUNDLE_CODE_PATH);
85 resPath = moduleSourceDir + "/";
86 break;
87 }
88 }
89 }
90
91 // second use file provider, will remove later
92 auto assetBasePathStr = { std::string("ets/"), std::string("resources/base/profile/") };
93 if (!resPath.empty()) {
94 auto assetProvider = AceType::MakeRefPtr<FileAssetProviderImpl>();
95 if (assetProvider->Initialize(resPath, assetBasePathStr)) {
96 assetManagerImpl->PushBack(std::move(assetProvider));
97 }
98 }
99 }
100
GetAbilityInfo(std::shared_ptr<OHOS::AbilityRuntime::Context> & context,std::string & tempDir)101 std::shared_ptr<OHOS::AppExecFwk::AbilityInfo> GetAbilityInfo(std::shared_ptr<OHOS::AbilityRuntime::Context>& context,
102 std::string& tempDir)
103 {
104 std::shared_ptr<OHOS::AppExecFwk::AbilityInfo> info;
105 auto abilityContext = OHOS::AbilityRuntime::Context::ConvertTo<OHOS::AbilityRuntime::AbilityContext>(context);
106 if (abilityContext) {
107 info = abilityContext->GetAbilityInfo();
108 tempDir = abilityContext->GetTempDir();
109 return info;
110 }
111
112 auto extensionContext =
113 OHOS::AbilityRuntime::Context::ConvertTo<OHOS::AbilityRuntime::ExtensionContext>(context);
114 if (extensionContext) {
115 info = extensionContext->GetAbilityInfo();
116 }
117 return info;
118 }
119
GetHapPath(std::shared_ptr<OHOS::AppExecFwk::AbilityInfo> & info)120 std::string GetHapPath(std::shared_ptr<OHOS::AppExecFwk::AbilityInfo>& info)
121 {
122 std::string hapPath;
123 std::string moduleHapPath = info != nullptr ? info->hapPath : "";
124 if (moduleHapPath.empty()) {
125 return hapPath;
126 }
127
128 if (moduleHapPath.find(ABS_BUNDLE_CODE_PATH) == std::string::npos) {
129 hapPath = moduleHapPath;
130 } else {
131 auto pos = moduleHapPath.find_last_of('/');
132 if (pos != std::string::npos) {
133 hapPath = LOCAL_BUNDLE_CODE_PATH + moduleHapPath.substr(pos + 1);
134 }
135 }
136 return hapPath;
137 }
138
InitLocalizationIfNeeded(std::shared_ptr<OHOS::AbilityRuntime::Context> & context)139 void InitLocalizationIfNeeded(std::shared_ptr<OHOS::AbilityRuntime::Context>& context)
140 {
141 if (Localization::GetInstance()->IsInit()) {
142 return;
143 }
144
145 std::unique_ptr<Global::Resource::ResConfig> resConfig(Global::Resource::CreateResConfig());
146 auto resourceManager = context->GetResourceManager();
147 if (resourceManager == nullptr) {
148 return;
149 }
150
151 resourceManager->GetResConfig(*resConfig);
152 auto localeInfo = resConfig->GetLocaleInfo();
153 Platform::AceApplicationInfoImpl::GetInstance().SetResourceManager(resourceManager);
154 if (localeInfo != nullptr) {
155 auto language = localeInfo->getLanguage();
156 auto region = localeInfo->getCountry();
157 auto script = localeInfo->getScript();
158 AceApplicationInfo::GetInstance().SetLocale((language == nullptr) ? "" : language,
159 (region == nullptr) ? "" : region, (script == nullptr) ? "" : script, "");
160 }
161 }
162
GetDensity()163 double GetDensity()
164 {
165 double density = 1.0;
166 auto defaultDisplay = Rosen::DisplayManager::GetInstance().GetDefaultDisplay();
167 if (defaultDisplay) {
168 auto temp = defaultDisplay->GetVirtualPixelRatio();
169 if (!NearEqual(temp, 1.0f)) {
170 density = temp;
171 }
172 }
173 return density;
174 }
175
CreateWindowFreeContainer(void * runtime,void * ctx)176 RefPtr<Container> WindowFreeContainer::CreateWindowFreeContainer(void *runtime, void *ctx)
177 {
178 if (g_WindowFreeContainer) {
179 return g_WindowFreeContainer;
180 }
181 CHECK_NULL_RETURN(runtime, nullptr);
182 CHECK_NULL_RETURN(ctx, nullptr);
183 int32_t instanceId = Container::GenerateId<WINDOW_FREE_CONTAINER>();
184
185 std::shared_ptr<OHOS::AbilityRuntime::Context> context =
186 (static_cast<std::weak_ptr<AbilityRuntime::Context>*>(ctx))->lock();
187 CHECK_NULL_RETURN(context, nullptr);
188 std::string tempDir;
189 std::shared_ptr<OHOS::AppExecFwk::AbilityInfo> info = GetAbilityInfo(context, tempDir);
190 auto container = AceType::MakeRefPtr<Platform::AceContainer>(instanceId, FrontendType::DECLARATIVE_JS,
191 context, info, std::make_unique<PseudoEventCallback>(), false, false, true);
192 if (!container) {
193 LOGW("Create container failed.");
194 return container;
195 }
196
197 AceEngine::Get().AddContainer(instanceId, container);
198 g_WindowFreeContainer = container;
199
200 container->SetSharedRuntime(runtime);
201 container->GetSettings().SetUsingSharedRuntime(true);
202 container->GetSettings().usePlatformAsUIThread = true;
203 container->GetSettings().useUIAsJSThread = true;
204
205 container->Initialize();
206 container->SetBundlePath(context->GetBundleCodeDir());
207 container->SetFilesDataPath(context->GetFilesDir());
208 std::string hapPath = GetHapPath(info);
209 container->SetHapPath(hapPath);
210 container->SetTempDir(tempDir);
211
212 ContainerScope scope(instanceId);
213 InitLocalizationIfNeeded(context);
214 RefPtr<AssetManagerImpl> assetManagerImpl;
215 InitAssetManager(assetManagerImpl, info, context);
216 container->SetAssetManager(assetManagerImpl);
217
218 auto window = std::make_shared<NG::RosenWindow>(nullptr, container->GetTaskExecutor(), instanceId);
219 RefPtr<Platform::AceViewOhos> aceView =
220 Platform::AceViewOhos::CreateView(instanceId, false, container->GetSettings().usePlatformAsUIThread);
221 double density = GetDensity();
222 float width = 0.0f;
223 float height = 0.0f;
224
225 container->AttachView(window, aceView, density, width, height, Rosen::INVALID_WINDOW_ID, nullptr);
226 return container;
227 }
228
DestroyWindowFreeContainer()229 void WindowFreeContainer::DestroyWindowFreeContainer()
230 {
231 if (!g_WindowFreeContainer) {
232 LOGW("Container without window doesn't exist.");
233 return;
234 }
235 int32_t instanceId = g_WindowFreeContainer->GetInstanceId();
236 Platform::AceContainer::DestroyContainer(instanceId, nullptr);
237 ContainerScope::RemoveAndCheck(instanceId);
238 g_WindowFreeContainer.Reset();
239 }
240 } // namespace OHOS::Ace
241