1 /*
2 * Copyright (c) 2024 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 "resource_manager_impl.h"
17 #include "hitrace_meter.h"
18 #include "resource_manager.h"
19 #include "resource_manager_log.h"
20 #include "securec.h"
21 #include "utils.h"
22 #include "cj_common_ffi.h"
23
24 using namespace OHOS::Global::Resource;
25 using namespace OHOS::Ace;
26 using namespace OHOS::FFI;
27
28 namespace OHOS::Resource {
29 std::map<std::string, std::shared_ptr<Global::Resource::ResourceManager>> g_resourceMgr;
30 std::mutex g_resMapLock;
31
ResourceManagerImpl(OHOS::AbilityRuntime::Context * context)32 ResourceManagerImpl::ResourceManagerImpl(OHOS::AbilityRuntime::Context* context)
33 {
34 LOGI("ResourceManagerImpl::ResourceManagerImpl start");
35 if (context == nullptr) {
36 LOGE("Failed to get native context instance");
37 return;
38 }
39 resMgr_ = context->GetResourceManager();
40 bundleName_ = context->GetBundleName();
41 context_ = std::shared_ptr<OHOS::AbilityRuntime::Context>(context);
42 isSystem_ = false;
43 LOGI("ResourceManagerImpl::ResourceManagerImpl success");
44 }
45
ResourceManagerImpl()46 ResourceManagerImpl::ResourceManagerImpl()
47 {
48 std::shared_ptr<Global::Resource::ResourceManager> resMgr(Global::Resource::GetSystemResourceManager());
49 resMgr_ = resMgr;
50 context_ = nullptr;
51 bundleName_ = "";
52 isSystem_ = true;
53 }
54
ResourceManagerImpl(std::string bundleName,std::shared_ptr<Global::Resource::ResourceManager> resMgr,std::shared_ptr<AbilityRuntime::Context> context)55 ResourceManagerImpl::ResourceManagerImpl(std::string bundleName,
56 std::shared_ptr<Global::Resource::ResourceManager> resMgr, std::shared_ptr<AbilityRuntime::Context> context)
57 : resMgr_(resMgr), bundleName_(bundleName), context_(context)
58 {
59 isOverride_ = true;
60 }
61
IsEmpty()62 bool ResourceManagerImpl::IsEmpty()
63 {
64 return resMgr_ == nullptr;
65 }
66
CloseRawFd(const std::string & name)67 int32_t ResourceManagerImpl::CloseRawFd(const std::string &name)
68 {
69 if (IsEmpty()) {
70 LOGE("Empty resource manager.");
71 return ERR_INVALID_INSTANCE_CODE;
72 }
73 return resMgr_->CloseRawFileDescriptor(name);
74 }
75
GetRawFd(const std::string & rawFileName,Global::Resource::ResourceManager::RawFileDescriptor & descriptor)76 int32_t ResourceManagerImpl::GetRawFd(
77 const std::string &rawFileName, Global::Resource::ResourceManager::RawFileDescriptor &descriptor)
78 {
79 if (IsEmpty()) {
80 LOGE("Empty resource manager.");
81 return ERR_INVALID_INSTANCE_CODE;
82 }
83 return resMgr_->GetRawFileDescriptorFromHap(rawFileName, descriptor);
84 }
85
GetRawFileContent(const std::string & name,size_t & len,std::unique_ptr<uint8_t[]> & outValue)86 int32_t ResourceManagerImpl::GetRawFileContent(
87 const std::string &name, size_t &len, std::unique_ptr<uint8_t[]> &outValue)
88 {
89 if (IsEmpty()) {
90 LOGE("Empty resource manager.");
91 return ERR_INVALID_INSTANCE_CODE;
92 }
93 return resMgr_->GetRawFileFromHap(name, len, outValue);
94 }
95
GetRawFileList(const std::string & rawDirPath,std::vector<std::string> & rawfileList)96 int32_t ResourceManagerImpl::GetRawFileList(const std::string &rawDirPath, std::vector<std::string> &rawfileList)
97 {
98 if (IsEmpty()) {
99 LOGE("Empty resource manager.");
100 return ERR_INVALID_INSTANCE_CODE;
101 }
102 return resMgr_->GetRawFileList(rawDirPath, rawfileList);
103 }
104
GetColorByName(const char * name,uint32_t & outValue)105 int32_t ResourceManagerImpl::GetColorByName(const char *name, uint32_t &outValue)
106 {
107 if (IsEmpty()) {
108 LOGE("Empty resource manager.");
109 return ERR_INVALID_INSTANCE_CODE;
110 }
111 return resMgr_->GetColorByName(name, outValue);
112 }
113
GetColorById(uint32_t id,uint32_t & outValue)114 int32_t ResourceManagerImpl::GetColorById(uint32_t id, uint32_t &outValue)
115 {
116 if (IsEmpty()) {
117 LOGE("Empty resource manager.");
118 return ERR_INVALID_INSTANCE_CODE;
119 }
120 return resMgr_->GetColorById(id, outValue);
121 }
122
GetPluralStringValue(uint32_t resId,int64_t num,std::string & outValue)123 int32_t ResourceManagerImpl::GetPluralStringValue(uint32_t resId, int64_t num, std::string &outValue)
124 {
125 if (IsEmpty()) {
126 LOGE("Empty resource manager.");
127 return ERR_INVALID_INSTANCE_CODE;
128 }
129 return resMgr_->GetPluralStringByIdFormat(outValue, resId, num, num);
130 }
131
GetStringArrayValue(uint32_t resId,std::vector<std::string> & outValue)132 int32_t ResourceManagerImpl::GetStringArrayValue(uint32_t resId, std::vector<std::string> &outValue)
133 {
134 if (IsEmpty()) {
135 LOGE("Empty resource manager.");
136 return ERR_INVALID_INSTANCE_CODE;
137 }
138 return resMgr_->GetStringArrayById(resId, outValue);
139 }
140
GetStringArrayByName(const char * name,std::vector<std::string> & outValue)141 int32_t ResourceManagerImpl::GetStringArrayByName(const char *name, std::vector<std::string> &outValue)
142 {
143 if (IsEmpty()) {
144 LOGE("Empty resource manager.");
145 return ERR_INVALID_INSTANCE_CODE;
146 }
147 return resMgr_->GetStringArrayByName(name, outValue);
148 }
149
GetString(uint32_t resId,std::string & outValue)150 int32_t ResourceManagerImpl::GetString(uint32_t resId, std::string &outValue)
151 {
152 if (IsEmpty()) {
153 LOGE("Empty resource manager.");
154 return ERR_INVALID_INSTANCE_CODE;
155 }
156 return resMgr_->GetStringById(resId, outValue);
157 }
158
GetStringByName(const char * name,std::string & outValue)159 int32_t ResourceManagerImpl::GetStringByName(const char *name, std::string &outValue)
160 {
161 if (IsEmpty()) {
162 LOGE("Empty resource manager.");
163 return ERR_INVALID_INSTANCE_CODE;
164 }
165 return resMgr_->GetStringByName(name, outValue);
166 }
167
GetPluralStringValue(const char * name,int64_t num,std::string & outValue)168 int32_t ResourceManagerImpl::GetPluralStringValue(const char *name, int64_t num, std::string &outValue)
169 {
170 if (IsEmpty()) {
171 LOGE("Empty resource manager.");
172 return ERR_INVALID_INSTANCE_CODE;
173 }
174 return resMgr_->GetPluralStringByNameFormat(outValue, name, num, num);
175 }
176
AddResource(const char * path)177 int32_t ResourceManagerImpl::AddResource(const char *path)
178 {
179 bool state = resMgr_->AddAppOverlay(path);
180 if (!state) {
181 return RState::ERROR_CODE_OVERLAY_RES_PATH_INVALID;
182 }
183 return RState::SUCCESS;
184 }
185
RemoveResource(const char * path)186 int32_t ResourceManagerImpl::RemoveResource(const char *path)
187 {
188 bool state = resMgr_->RemoveAppOverlay(path);
189 if (!state) {
190 return RState::ERROR_CODE_OVERLAY_RES_PATH_INVALID;
191 }
192 return RState::SUCCESS;
193 }
194
GetBooleanById(uint32_t id,bool & outValue)195 int32_t ResourceManagerImpl::GetBooleanById(uint32_t id, bool &outValue)
196 {
197 if (IsEmpty()) {
198 LOGE("Empty resource manager.");
199 return ERR_INVALID_INSTANCE_CODE;
200 }
201 return resMgr_->GetBooleanById(id, outValue);
202 }
203
GetBooleanByName(const char * name,bool & outValue)204 int32_t ResourceManagerImpl::GetBooleanByName(const char *name, bool &outValue)
205 {
206 if (IsEmpty()) {
207 LOGE("Empty resource manager.");
208 return ERR_INVALID_INSTANCE_CODE;
209 }
210 return resMgr_->GetBooleanByName(name, outValue);
211 }
212
GetIntegerById(uint32_t id,int & outValue)213 int32_t ResourceManagerImpl::GetIntegerById(uint32_t id, int &outValue)
214 {
215 if (IsEmpty()) {
216 LOGE("Empty resource manager.");
217 return ERR_INVALID_INSTANCE_CODE;
218 }
219 return resMgr_->GetIntegerById(id, outValue);
220 }
221
GetIntegerByName(const char * name,int & outValue)222 int32_t ResourceManagerImpl::GetIntegerByName(const char *name, int &outValue)
223 {
224 if (IsEmpty()) {
225 LOGE("Empty resource manager.");
226 return ERR_INVALID_INSTANCE_CODE;
227 }
228 return resMgr_->GetIntegerByName(name, outValue);
229 }
230
GetFloatById(uint32_t id,float & outValue)231 int32_t ResourceManagerImpl::GetFloatById(uint32_t id, float &outValue)
232 {
233 if (IsEmpty()) {
234 LOGE("Empty resource manager.");
235 return ERR_INVALID_INSTANCE_CODE;
236 }
237 return resMgr_->GetFloatById(id, outValue);
238 }
239
GetFloatByName(const char * name,float & outValue)240 int32_t ResourceManagerImpl::GetFloatByName(const char *name, float &outValue)
241 {
242 if (IsEmpty()) {
243 LOGE("Empty resource manager.");
244 return ERR_INVALID_INSTANCE_CODE;
245 }
246 return resMgr_->GetFloatByName(name, outValue);
247 }
248
GetLocale(std::unique_ptr<Global::Resource::ResConfig> & cfg)249 std::string GetLocale(std::unique_ptr<Global::Resource::ResConfig> &cfg)
250 {
251 std::string result;
252 #ifdef SUPPORT_GRAPHICS
253 const icu::Locale *localeInfo = cfg->GetLocaleInfo();
254 if (localeInfo == nullptr) {
255 return result;
256 }
257 const char *lang = localeInfo->getLanguage();
258 if (lang == nullptr) {
259 return result;
260 }
261 result = lang;
262
263 const char *script = localeInfo->getScript();
264 if (script != nullptr) {
265 result += std::string("_") + script;
266 }
267
268 const char *region = localeInfo->getCountry();
269 if (region != nullptr) {
270 result += std::string("_") + region;
271 }
272 #endif
273 return result;
274 }
275
GetConfiguration(Configuration & configuration)276 void ResourceManagerImpl::GetConfiguration(Configuration &configuration)
277 {
278 LOGI("ResourceManagerImpl::GetConfiguration start");
279 std::unique_ptr<ResConfig> cfg(CreateResConfig());
280 if (!cfg) {
281 LOGE("Failed to create ResConfig object.");
282 return;
283 }
284 resMgr_->GetResConfig(*cfg);
285 configuration.direction = static_cast<int32_t>(cfg->GetDirection());
286 LOGI("ResourceManagerImpl::GetConfiguration ok %{public}" PRId32, configuration.direction);
287 std::string locale = GetLocale(cfg);
288
289 auto temp = ::Utils::MallocCString(locale);
290 if (temp == nullptr) {
291 return;
292 }
293 configuration.locale = temp;
294 }
295
ResConfigToConfigurationEx(std::unique_ptr<ResConfig> & config,ConfigurationEx * configuration)296 void ResConfigToConfigurationEx(std::unique_ptr<ResConfig> &config, ConfigurationEx *configuration)
297 {
298 configuration->direction = static_cast<int32_t>(config->GetDirection());
299 configuration->deviceType = static_cast<int32_t>(config->GetDeviceType());
300 configuration->screenDensity = static_cast<int32_t>(config->GetScreenDensityDpi());
301 configuration->colorMode = static_cast<int32_t>(config->GetColorMode());
302 configuration->mcc = config->GetMcc();
303 configuration->mnc = config->GetMnc();
304
305 std::string locale = GetLocale(config);
306 auto temp = ::Utils::MallocCString(locale);
307 if (temp == nullptr) {
308 return;
309 }
310 configuration->locale = temp;
311 return;
312 }
313
GetConfiguration(ConfigurationEx * configuration)314 void ResourceManagerImpl::GetConfiguration(ConfigurationEx *configuration)
315 {
316 std::unique_ptr<ResConfig> cfg(CreateResConfig());
317 if (!cfg) {
318 LOGE("Failed to create ResConfig object.");
319 return;
320 }
321 resMgr_->GetResConfig(*cfg);
322 return ResConfigToConfigurationEx(cfg, configuration);
323 }
324
GetOverrideConfiguration(ConfigurationEx * configuration)325 void ResourceManagerImpl::GetOverrideConfiguration(ConfigurationEx *configuration)
326 {
327 std::unique_ptr<ResConfig> cfg(CreateResConfig());
328 if (!cfg) {
329 LOGE("Failed to create ResConfig object.");
330 return;
331 }
332 resMgr_->GetOverrideResConfig(*cfg);
333 return ResConfigToConfigurationEx(cfg, configuration);
334 }
335
GetDeviceCapability(DeviceCapability & deviceCapability)336 void ResourceManagerImpl::GetDeviceCapability(DeviceCapability &deviceCapability)
337 {
338 std::unique_ptr<ResConfig> cfg(CreateResConfig());
339 if (!cfg) {
340 LOGE("Failed to create ResConfig object.");
341 return;
342 }
343 resMgr_->GetResConfig(*cfg);
344 deviceCapability.screenDensity = static_cast<int32_t>(cfg->ConvertDensity(cfg->GetScreenDensity()));
345 deviceCapability.deviceType = static_cast<int32_t>(cfg->GetDeviceType());
346 LOGI("ResourceManagerImpl::GetDeviceCapability ok screenDensity %{public}" PRId32, deviceCapability.screenDensity);
347 }
348
GetMediaDataByName(const char * name,size_t & len,std::unique_ptr<uint8_t[]> & outValue,uint32_t density)349 int32_t ResourceManagerImpl::GetMediaDataByName(
350 const char *name, size_t &len, std::unique_ptr<uint8_t[]> &outValue, uint32_t density)
351 {
352 if (IsEmpty()) {
353 LOGE("Empty resource manager.");
354 return ERR_INVALID_INSTANCE_CODE;
355 }
356 return resMgr_->GetMediaDataByName(name, len, outValue, density);
357 }
358
GetMediaDataById(uint32_t id,size_t & len,std::unique_ptr<uint8_t[]> & outValue,uint32_t density)359 int32_t ResourceManagerImpl::GetMediaDataById(
360 uint32_t id, size_t &len, std::unique_ptr<uint8_t[]> &outValue, uint32_t density)
361 {
362 if (IsEmpty()) {
363 LOGE("Empty resource manager.");
364 return ERR_INVALID_INSTANCE_CODE;
365 }
366 return resMgr_->GetMediaDataById(id, len, outValue, density);
367 }
368
GetMediaContentBase64ById(uint32_t id,std::string & outValue,uint32_t density)369 int32_t ResourceManagerImpl::GetMediaContentBase64ById(uint32_t id, std::string &outValue, uint32_t density)
370 {
371 if (IsEmpty()) {
372 LOGE("Empty resource manager.");
373 return ERR_INVALID_INSTANCE_CODE;
374 }
375 return resMgr_->GetMediaBase64DataById(id, outValue, density);
376 }
377
GetMediaContentBase64ByName(const char * name,std::string & outValue,uint32_t density)378 int32_t ResourceManagerImpl::GetMediaContentBase64ByName(const char *name, std::string &outValue, uint32_t density)
379 {
380 if (IsEmpty()) {
381 LOGE("Empty resource manager.");
382 return ERR_INVALID_INSTANCE_CODE;
383 }
384 return resMgr_->GetMediaBase64DataByName(name, outValue, density);
385 }
386
GetDrawableDescriptor(uint32_t id,int64_t & outValue,uint32_t density)387 int32_t ResourceManagerImpl::GetDrawableDescriptor(uint32_t id, int64_t &outValue, uint32_t density)
388 {
389 RState state = SUCCESS;
390 OHOS::Ace::Napi::DrawableDescriptor::DrawableType drawableType;
391 auto drawableDescriptor =
392 OHOS::Ace::Napi::DrawableDescriptorFactory::Create(id, resMgr_, state, drawableType, density);
393 if (state != SUCCESS) {
394 LOGE("Failed to Create drawableDescriptor by %{public}" PRIu32, id);
395 return state;
396 }
397 auto ptr = FFIData::Create<DrawableDescriptorImpl>(drawableDescriptor.release());
398 if (!ptr) {
399 return ERR_INVALID_INSTANCE_CODE;
400 }
401 outValue = ptr->GetID();
402 return state;
403 }
404
GetDrawableDescriptorByName(const char * name,int64_t & outValue,uint32_t density)405 int32_t ResourceManagerImpl::GetDrawableDescriptorByName(const char *name, int64_t &outValue, uint32_t density)
406 {
407 RState state = SUCCESS;
408 OHOS::Ace::Napi::DrawableDescriptor::DrawableType drawableType;
409 auto drawableDescriptor =
410 OHOS::Ace::Napi::DrawableDescriptorFactory::Create(name, resMgr_, state, drawableType, density);
411 if (state != SUCCESS) {
412 return state;
413 }
414 auto ptr = FFIData::Create<DrawableDescriptorImpl>(drawableDescriptor.release());
415 if (!ptr) {
416 return ERR_INVALID_INSTANCE_CODE;
417 }
418 outValue = ptr->GetID();
419 return state;
420 }
421
GetHapResourceManager(Global::Resource::ResourceManager::Resource resource,std::shared_ptr<Global::Resource::ResourceManager> & resMgr,uint32_t & resId)422 bool ResourceManagerImpl::GetHapResourceManager(Global::Resource::ResourceManager::Resource resource,
423 std::shared_ptr<Global::Resource::ResourceManager> &resMgr, uint32_t &resId)
424 {
425 resId = resource.id;
426 if (isSystem_) {
427 resMgr = resMgr_;
428 return true;
429 }
430
431 std::string key(resource.bundleName + "/" + resource.moduleName);
432 std::lock_guard<std::mutex> lock(g_resMapLock);
433 auto iter = g_resourceMgr.find(key);
434 if (iter != g_resourceMgr.end()) {
435 resMgr = g_resourceMgr[key];
436 return true;
437 }
438
439 auto moduleContext = context_->CreateModuleContext(resource.bundleName, resource.moduleName);
440 if (moduleContext == nullptr) {
441 return false;
442 }
443 resMgr = moduleContext->GetResourceManager();
444 g_resourceMgr[key] = resMgr;
445 return true;
446 }
447
GetDrawableDescriptorPtr(uint32_t id,std::shared_ptr<Global::Resource::ResourceManager> resMgr,uint32_t density,RState & state)448 OHOS::Ace::Napi::DrawableDescriptor* GetDrawableDescriptorPtr(
449 uint32_t id, std::shared_ptr<Global::Resource::ResourceManager> resMgr, uint32_t density, RState &state)
450 {
451 OHOS::Ace::Napi::DrawableDescriptor::DrawableType drawableType;
452 auto drawableDescriptor =
453 OHOS::Ace::Napi::DrawableDescriptorFactory::Create(id, resMgr, state, drawableType, density);
454 if (state != SUCCESS) {
455 LOGE("Failed to Create drawableDescriptor by %{public}" PRIu32, id);
456 return nullptr;
457 }
458
459 return drawableDescriptor.release();
460 }
461
GetLocales(bool includeSystem,std::vector<std::string> & outValue)462 void ResourceManagerImpl::GetLocales(bool includeSystem, std::vector<std::string> &outValue)
463 {
464 if (IsEmpty()) {
465 LOGE("Empty resource manager.");
466 return;
467 }
468 return resMgr_->GetLocales(outValue, includeSystem);
469 }
470
GetSymbolById(uint32_t id,uint32_t & outValue)471 int32_t ResourceManagerImpl::GetSymbolById(uint32_t id, uint32_t &outValue)
472 {
473 if (IsEmpty()) {
474 LOGE("Empty resource manager.");
475 return ERR_INVALID_INSTANCE_CODE;
476 }
477 return resMgr_->GetSymbolById(id, outValue);
478 }
479
GetSymbolByName(const char * name,uint32_t & outValue)480 int32_t ResourceManagerImpl::GetSymbolByName(const char *name, uint32_t &outValue)
481 {
482 if (IsEmpty()) {
483 LOGE("Empty resource manager.");
484 return ERR_INVALID_INSTANCE_CODE;
485 }
486 return resMgr_->GetSymbolByName(name, outValue);
487 }
488
GetOverrideResMgr(ConfigurationEx & cfg,int32_t & errCode)489 std::shared_ptr<ResourceManager> ResourceManagerImpl::GetOverrideResMgr(ConfigurationEx &cfg, int32_t &errCode)
490 {
491 std::shared_ptr<ResConfig> config(CreateDefaultResConfig());
492 if (config == nullptr) {
493 LOGE("GetOverrideResMgr, new config failed");
494 errCode = ERROR_CODE_INVALID_INPUT_PARAMETER;
495 return nullptr;
496 }
497 config->SetDirection(static_cast<Direction>(cfg.direction));
498 config->SetDeviceType(static_cast<DeviceType>(cfg.deviceType));
499 config->SetScreenDensityDpi(static_cast<ScreenDensity>(cfg.screenDensity));
500 config->SetColorMode(static_cast<ColorMode>(cfg.colorMode));
501 config->SetMcc(cfg.mcc);
502 config->SetMnc(cfg.mnc);
503 #ifdef SUPPORT_GRAPHICS
504 config->SetLocaleInfo(cfg.locale);
505 #endif
506 std::shared_ptr<ResourceManager> overrideResMgr = resMgr_->GetOverrideResourceManager(config);
507 if (overrideResMgr == nullptr) {
508 errCode = ERROR_CODE_INVALID_INPUT_PARAMETER;
509 return nullptr;
510 }
511 return overrideResMgr;
512 }
513
GetBundleName()514 std::string ResourceManagerImpl::GetBundleName()
515 {
516 return bundleName_;
517 }
518
GetContext()519 std::shared_ptr<AbilityRuntime::Context> ResourceManagerImpl::GetContext()
520 {
521 return context_;
522 }
523 }
524