add overlay

Signed-off-by: wplan1 <wangpeng163@huawei.com>
This commit is contained in:
wplan1 2022-02-14 16:02:27 +08:00
parent 9a3cec5e4f
commit 60ff402776
9 changed files with 240 additions and 90 deletions

View File

@ -21,6 +21,7 @@
#include "lock.h"
#include <unicode/plurrule.h>
#include <unordered_map>
#include <vector>
namespace OHOS {
@ -38,6 +39,8 @@ public:
bool AddResource(const char *path);
bool AddResource(const std::string &path, const std::vector<std::string> &overlayPaths);
const IdItem *FindResourceById(uint32_t id);
const IdItem *FindResourceByName(const char *name, const ResType resType);
@ -57,9 +60,9 @@ private:
void GetResConfigImpl(ResConfigImpl &resConfig);
const HapResource::IdValues *GetResourceList(uint32_t ident) const;
std::vector<const HapResource::IdValues *> GetResourceList(uint32_t ident) const;
const HapResource::IdValues *GetResourceListByName(const char *name, const ResType resType) const;
std::vector<const HapResource::IdValues *> GetResourceListByName(const char *name, const ResType resType) const;
bool AddResourcePath(const char *path);
@ -77,7 +80,7 @@ private:
std::vector<HapResource *> hapResources_;
// set of loaded hap path
std::vector<std::string> loadedHapPaths_;
std::unordered_map<std::string, std::vector<std::string>> loadedHapPaths_;
// key is language
std::vector<std::pair<std::string, icu::PluralRules *>> plurRulesCache_;

View File

@ -15,12 +15,13 @@
#ifndef RESOURCE_MANAGER_HAPRESOURCE_H
#define RESOURCE_MANAGER_HAPRESOURCE_H
#include "res_desc.h"
#include "res_config_impl.h"
#include <map>
#include <string>
#include <time.h>
#include <unordered_map>
#include <vector>
#include "res_desc.h"
#include "res_config_impl.h"
namespace OHOS {
namespace Global {
@ -43,6 +44,9 @@ public:
*/
static const HapResource *LoadFromIndex(const char *path, const ResConfigImpl *defaultConfig, bool system = false);
static const std::unordered_map<std::string, HapResource *> LoadOverlays(const std::string &path,
const std::vector<std::string> &overlayPath, const ResConfigImpl *defaultConfig);
~HapResource();
inline const std::string GetIndexPath() const
@ -87,8 +91,13 @@ public:
return hapResource_;
}
inline bool IsOverlay() const
{
return isOverlay_;
}
ValueUnderQualifierDir(const std::vector<KeyParam *> &keyParams, IdItem *idItem,
HapResource *hapResource);
HapResource *hapResource, bool isOverlay = false);
~ValueUnderQualifierDir();
@ -111,6 +120,10 @@ public:
// indicate belong to which hapresource
const HapResource *hapResource_;
friend class HapResource;
bool isOverlay_;
};
/**
@ -149,6 +162,10 @@ public:
private:
HapResource(const std::string path, time_t lastModTime, const ResConfig *defaultConfig, ResDesc *resDes);
std::unordered_map<std::string, std::unordered_map<ResType, uint32_t>> BuildNameTypeIdMapping() const;
void UpdateOverlayInfo(std::unordered_map<std::string, std::unordered_map<ResType, uint32_t>> &nameTypeId);
// must call Init() after constructor
bool Init();

View File

@ -34,6 +34,8 @@ public:
virtual bool AddResource(const char *path);
virtual bool AddResource(const std::string &path, const std::vector<std::string> &overlayPaths);
virtual RState UpdateResConfig(ResConfig &resConfig);
virtual void GetResConfig(ResConfig &resConfig);

View File

@ -142,66 +142,78 @@ const IdItem *HapManager::FindResourceByName(const char *name, const ResType res
const HapResource::ValueUnderQualifierDir *HapManager::FindQualifierValueByName(
const char *name, const ResType resType)
{
const HapResource::IdValues *idValues = this->GetResourceListByName(name, resType);
if (idValues == nullptr) {
std::vector<const HapResource::IdValues *> candidates = this->GetResourceListByName(name, resType);
if (candidates.size() == 0) {
return nullptr;
}
const std::vector<HapResource::ValueUnderQualifierDir *> paths = idValues->GetLimitPathsConst();
size_t len = paths.size();
size_t i = 0;
size_t bestIndex = -1;
const ResConfigImpl *bestResConfig = nullptr;
const ResConfigImpl *currentResConfig = this->resConfig_;
for (i = 0; i < len; i++) {
HapResource::ValueUnderQualifierDir *path = paths[i];
const ResConfigImpl *resConfig = path->GetResConfig();
if (this->resConfig_->Match(resConfig)) {
if (bestResConfig == nullptr) {
bestIndex = i;
bestResConfig = resConfig;
} else if (bestResConfig->IsMoreSuitable(resConfig, currentResConfig)) {
const HapResource::ValueUnderQualifierDir *result = nullptr;
for (auto iter = candidates.begin(); iter != candidates.end(); iter++) {
const std::vector<HapResource::ValueUnderQualifierDir *> paths = (*iter)->GetLimitPathsConst();
size_t len = paths.size();
size_t i = 0;
const ResConfigImpl *currentResConfig = this->resConfig_;
for (i = 0; i < len; i++) {
HapResource::ValueUnderQualifierDir *path = paths[i];
const ResConfigImpl *resConfig = path->GetResConfig();
if (!this->resConfig_->Match(resConfig)) {
continue;
} else {
}
if (bestResConfig == nullptr) {
bestResConfig = resConfig;
bestIndex = i;
result = paths[i];
continue;
}
if (!bestResConfig->IsMoreSuitable(resConfig, currentResConfig)) {
bestResConfig = resConfig;
result = paths[i];
}
}
}
return paths[bestIndex];
return result;
}
const HapResource::ValueUnderQualifierDir *HapManager::FindQualifierValueById(uint32_t id)
{
const HapResource::IdValues *idValues = this->GetResourceList(id);
if (idValues == nullptr) {
std::vector<const HapResource::IdValues *> candidates = this->GetResourceList(id);
if (candidates.size() == 0) {
return nullptr;
}
const std::vector<HapResource::ValueUnderQualifierDir *> paths = idValues->GetLimitPathsConst();
size_t len = paths.size();
size_t i = 0;
size_t bestIndex = -1;
const ResConfigImpl *bestResConfig = nullptr;
const ResConfigImpl *currentResConfig = this->resConfig_;
for (i = 0; i < len; i++) {
HapResource::ValueUnderQualifierDir *path = paths[i];
const ResConfigImpl *resConfig = path->GetResConfig();
if (this->resConfig_->Match(resConfig)) {
const HapResource::ValueUnderQualifierDir *result = nullptr;
bool isOverlayChange = false;
for (auto iter = candidates.begin(); iter != candidates.end(); iter++) {
const std::vector<HapResource::ValueUnderQualifierDir *> paths = (*iter)->GetLimitPathsConst();
size_t len = paths.size();
size_t i = 0;
const ResConfigImpl *currentResConfig = this->resConfig_;
if (isOverlayChange) {
break;
}
for (i = 0; i < len; i++) {
HapResource::ValueUnderQualifierDir *path = paths[i];
const ResConfigImpl *resConfig = path->GetResConfig();
if (!this->resConfig_->Match(resConfig)) {
continue;
}
if (bestResConfig == nullptr) {
bestIndex = i;
bestResConfig = resConfig;
} else {
if (bestResConfig->IsMoreSuitable(resConfig, currentResConfig)) {
continue;
} else {
bestResConfig = resConfig;
bestIndex = i;
}
result = paths[i];
continue;
}
if (!bestResConfig->IsMoreSuitable(resConfig, currentResConfig)) {
bestResConfig = resConfig;
result = paths[i];
}
if (path->IsOverlay()) {
bestResConfig = resConfig;
result = paths[i];
isOverlayChange = true;
break;
}
}
}
return paths[bestIndex];
return result;
}
RState HapManager::FindRawFile(const std::string &name, std::string &outValue)
@ -274,6 +286,26 @@ bool HapManager::AddResource(const char *path)
return this->AddResourcePath(path);
}
bool HapManager::AddResource(const std::string &path, const std::vector<std::string> &overlayPaths)
{
loadedHapPaths_[path] = overlayPaths;
std::unordered_map<std::string, HapResource *> result = HapResource::LoadOverlays(path, overlayPaths, resConfig_);
if (result.size() > 0) {
std::vector<std::string> &validOverlayPaths = loadedHapPaths_[path];
int i = 0;
for (auto iter = result.begin(); iter != result.end(); iter++) {
this->hapResources_.push_back(iter->second);
if (i > 0) {
// the first is the target, not the overlay
validOverlayPaths.push_back(iter->first);
i++;
}
}
return true;
}
return false;
}
HapManager::~HapManager()
{
for (size_t i = 0; i < hapResources_.size(); ++i) {
@ -290,37 +322,39 @@ HapManager::~HapManager()
}
}
const HapResource::IdValues *HapManager::GetResourceList(uint32_t ident) const
std::vector<const HapResource::IdValues *> HapManager::GetResourceList(uint32_t ident) const
{
std::vector<const HapResource::IdValues *> result;
// one id only exit in one hap
for (size_t i = 0; i < hapResources_.size(); ++i) {
HapResource *pResource = hapResources_[i];
const HapResource::IdValues *out = pResource->GetIdValues(ident);
if (out != nullptr) {
return out;
result.emplace_back(out);
}
}
return nullptr;
return result;
}
const HapResource::IdValues *HapManager::GetResourceListByName(const char *name, const ResType resType) const
std::vector<const HapResource::IdValues *> HapManager::GetResourceListByName(const char *name,
const ResType resType) const
{
// first match will return
std::vector<const HapResource::IdValues *> result;
// all match will return
for (size_t i = 0; i < hapResources_.size(); ++i) {
HapResource *pResource = hapResources_[i];
const HapResource::IdValues *out = pResource->GetIdValuesByName(std::string(name), resType);
if (out != nullptr) {
return out;
result.emplace_back(out);
}
}
return nullptr;
return result;
}
bool HapManager::AddResourcePath(const char *path)
{
std::string sPath(path);
std::vector<std::string>::iterator it = std::find(loadedHapPaths_.begin(),
loadedHapPaths_.end(), sPath);
auto it = loadedHapPaths_.find(sPath);
if (it != loadedHapPaths_.end()) {
HILOG_ERROR(" %s has already been loaded!", path);
return false;
@ -330,7 +364,7 @@ bool HapManager::AddResourcePath(const char *path)
return false;
}
this->hapResources_.push_back((HapResource *)pResource);
this->loadedHapPaths_.push_back(sPath);
this->loadedHapPaths_[sPath] = std::vector<std::string>();
return true;
}
@ -340,21 +374,27 @@ RState HapManager::ReloadAll()
return SUCCESS;
}
std::vector<HapResource *> newResources;
for (size_t i = 0; i < hapResources_.size(); ++i) {
const HapResource *pResource = HapResource::LoadFromIndex(hapResources_[i]->GetIndexPath().c_str(), resConfig_);
if (pResource == nullptr) {
for (size_t i = 0; i < newResources.size(); ++i) {
delete (newResources[i]);
do {
for (auto iter = loadedHapPaths_.begin(); iter != loadedHapPaths_.end(); iter++) {
std::vector<std::string> &overlayPaths = iter->second;
std::unordered_map<std::string, HapResource *> result = HapResource::LoadOverlays(iter->first.c_str(),
overlayPaths, resConfig_);
if (result.size() == 0) {
break;
}
return HAP_INIT_FAILED;
for_each(overlayPaths.begin(), overlayPaths.end(), [&](auto &path) {
if (result.find(path) != result.end()) {
newResources.push_back(result[path]);
}
});
}
newResources.push_back((HapResource *)pResource);
return SUCCESS;
} while (false);
for (size_t i = 0; i < newResources.size(); ++i) {
delete (newResources[i]);
}
for (size_t i = 0; i < hapResources_.size(); ++i) {
delete (hapResources_[i]);
}
hapResources_ = newResources;
return SUCCESS;
return HAP_INIT_FAILED;
}
std::vector<std::string> HapManager::GetResourcePaths()

View File

@ -35,11 +35,12 @@ namespace OHOS {
namespace Global {
namespace Resource {
HapResource::ValueUnderQualifierDir::ValueUnderQualifierDir(const std::vector<KeyParam *> &keyParams, IdItem *idItem,
HapResource *hapResource) : hapResource_(hapResource)
HapResource *hapResource, bool isOverlay) : hapResource_(hapResource)
{
keyParams_ = keyParams;
folder_ = HapParser::ToFolderPath(keyParams_);
idItem_ = idItem;
isOverlay_ = isOverlay;
InitResConfig();
}
@ -142,6 +143,88 @@ const HapResource *HapResource::LoadFromIndex(const char *path, const ResConfigI
return pResource;
}
const std::unordered_map<std::string, HapResource *> HapResource::LoadOverlays(const std::string &path,
const std::vector<std::string> &overlayPaths, const ResConfigImpl *defaultConfig)
{
std::unordered_map<std::string, HapResource *> result;
do {
const HapResource *targetResource = LoadFromIndex(path.c_str(), defaultConfig);
if (targetResource == nullptr) {
HILOG_ERROR("load target failed");
break;
}
result[path] = const_cast<HapResource*>(targetResource);
bool success = true;
std::unordered_map<std::string, std::unordered_map<ResType, uint32_t>> mapping =
targetResource->BuildNameTypeIdMapping();
for (auto iter = overlayPaths.begin(); iter != overlayPaths.end(); iter++) {
const HapResource *overlayResource = LoadFromIndex(iter->c_str(), defaultConfig);
if (overlayResource == nullptr) {
HILOG_ERROR("load overlay failed");
success = false;
break;
}
result[*iter] = const_cast<HapResource*>(overlayResource);
}
if (success) {
for (auto iter = result.begin(); iter != result.end(); iter++) {
auto index = iter->first.find(path);
if (index == std::string::npos) {
iter->second->UpdateOverlayInfo(mapping);
}
}
return result;
}
} while (false);
for_each (result.begin(), result.end(), [](auto &iter) {
delete iter.second;
});
return std::unordered_map<std::string, HapResource *>();
}
std::unordered_map<std::string, std::unordered_map<ResType, uint32_t>> HapResource::BuildNameTypeIdMapping() const
{
std::unordered_map<std::string, std::unordered_map<ResType, uint32_t>> result;
for (auto iter = idValuesMap_.begin(); iter != idValuesMap_.end(); iter++) {
const std::vector<ValueUnderQualifierDir *> &limitPaths = iter->second->GetLimitPathsConst();
if (limitPaths.size() > 0) {
ValueUnderQualifierDir* value = limitPaths[0];
result[value->idItem_->name_][value->idItem_->resType_] = value->idItem_->id_;
}
}
return result;
}
void HapResource::UpdateOverlayInfo(std::unordered_map<std::string, std::unordered_map<ResType, uint32_t>> &nameTypeId)
{
std::map<uint32_t, IdValues *> newIdValuesMap;
for (auto iter = idValuesMap_.begin(); iter != idValuesMap_.end(); iter++) {
const std::vector<ValueUnderQualifierDir *> &limitPaths = iter->second->GetLimitPathsConst();
uint32_t newId = 0;
if (limitPaths.size() > 0) {
ValueUnderQualifierDir *value = limitPaths[0];
std::string name = value->idItem_->name_;
ResType type = value->idItem_->resType_;
if (nameTypeId.find(name) == nameTypeId.end()) {
continue;
}
auto &typeId = nameTypeId[name];
if (typeId.find(type) == typeId.end()) {
continue;
}
newId = typeId[type];
for_each(limitPaths.begin(), limitPaths.end(), [&](auto &item) {
item->idItem_->id_ = newId;
item->isOverlay_ = true;
});
newIdValuesMap[newId] = iter->second;
}
}
idValuesMap_.swap(newIdValuesMap);
}
bool HapResource::Init()
{
#if !defined(__WINNT__) && !defined(__IDE_PREVIEW__)
@ -197,8 +280,8 @@ bool HapResource::InitIdList()
HILOG_ERROR("new IdValues failed in HapResource::InitIdList");
return false;
}
auto limitPath =
new (std::nothrow) HapResource::ValueUnderQualifierDir(resKey->keyParams_, idParam->idItem_, this);
auto limitPath = new (std::nothrow) HapResource::ValueUnderQualifierDir(resKey->keyParams_,
idParam->idItem_, this, false);
if (limitPath == nullptr) {
HILOG_ERROR("new ValueUnderQualifierDir failed in HapResource::InitIdList");
delete (idValues);
@ -210,8 +293,8 @@ bool HapResource::InitIdList()
idValuesNameMap_[idParam->idItem_->resType_]->insert(std::make_pair(name, idValues));
} else {
HapResource::IdValues *idValues = iter->second;
auto limitPath =
new (std::nothrow) HapResource::ValueUnderQualifierDir(resKey->keyParams_, idParam->idItem_, this);
auto limitPath = new (std::nothrow) HapResource::ValueUnderQualifierDir(resKey->keyParams_,
idParam->idItem_, this, false);
if (limitPath == nullptr) {
HILOG_ERROR("new ValueUnderQualifierDir failed in HapResource::InitIdList");
return false;

View File

@ -677,6 +677,11 @@ bool ResourceManagerImpl::AddResource(const char *path)
return this->hapManager_->AddResource(path);
}
bool ResourceManagerImpl::AddResource(const std::string &path, const std::vector<std::string> &overlayPaths)
{
return this->hapManager_->AddResource(path, overlayPaths);
}
RState ResourceManagerImpl::UpdateResConfig(ResConfig &resConfig)
{
#if !defined(__WINNT__) && !defined(__IDE_PREVIEW__)

View File

@ -75,14 +75,14 @@ HWTEST_F(HapManagerTest, HapManagerFuncTest001, TestSize.Level1)
EXPECT_TRUE(ret);
int id = 16777217;
const HapResource::IdValues *idValues = hapManager->GetResourceList(id);
if (idValues == nullptr) {
std::vector<const HapResource::IdValues *> idValues = hapManager->GetResourceList(id);
if (idValues.size() == 0) {
delete hapManager;
EXPECT_TRUE(false);
return;
}
PrintIdValues(idValues);
PrintIdValues(idValues[0]);
delete hapManager;
}
@ -114,16 +114,16 @@ HWTEST_F(HapManagerTest, HapManagerFuncTest002, TestSize.Level1)
EXPECT_TRUE(ret);
int id = 16777228;
const HapResource::IdValues *idValues = hapManager->GetResourceList(id);
if (idValues == nullptr) {
std::vector<const HapResource::IdValues *> idValues = hapManager->GetResourceList(id);
if (idValues.size() == 0) {
delete (hapManager);
delete (rc);
EXPECT_TRUE(false);
return;
}
EXPECT_EQ(static_cast<size_t>(1), idValues->GetLimitPathsConst().size());
PrintIdValues(idValues);
EXPECT_EQ(static_cast<size_t>(1), idValues[0]->GetLimitPathsConst().size());
PrintIdValues(idValues[0]);
// reload
@ -139,14 +139,14 @@ HWTEST_F(HapManagerTest, HapManagerFuncTest002, TestSize.Level1)
hapManager->UpdateResConfig(*rc2);
do {
idValues = hapManager->GetResourceList(id);
if (idValues == nullptr) {
if (idValues.size() == 0) {
EXPECT_TRUE(false);
break;
}
EXPECT_EQ(static_cast<size_t>(2), idValues->GetLimitPathsConst().size());
EXPECT_EQ(static_cast<size_t>(2), idValues[0]->GetLimitPathsConst().size());
PrintIdValues(idValues);
PrintIdValues(idValues[0]);
} while (false);
delete (hapManager);
delete (rc2);

View File

@ -61,12 +61,12 @@ public:
int ResourceManagerPerformanceTest::GetResId(std::string name, ResType resType) const
{
auto idv = ((ResourceManagerImpl *)rm)->hapManager_->GetResourceListByName(name.c_str(), resType);
if (idv == nullptr) {
if (idv.size() == 0) {
return -1;
}
if (idv->GetLimitPathsConst().size() > 0) {
return idv->GetLimitPathsConst()[0]->GetIdItem()->id_;
if (idv[0]->GetLimitPathsConst().size() > 0) {
return idv[0]->GetLimitPathsConst()[0]->GetIdItem()->id_;
}
return OBJ_NOT_FOUND;
}

View File

@ -75,13 +75,13 @@ public:
int ResourceManagerTest::GetResId(std::string name, ResType resType) const
{
auto idv = ((ResourceManagerImpl *)rm)->hapManager_->GetResourceListByName(name.c_str(), resType);
if (idv == nullptr) {
if (idv.size() == 0) {
return -1;
}
PrintIdValues(idv);
if (idv->GetLimitPathsConst().size() > 0) {
return idv->GetLimitPathsConst()[0]->GetIdItem()->id_;
PrintIdValues(idv[0]);
if (idv[0]->GetLimitPathsConst().size() > 0) {
return idv[0]->GetLimitPathsConst()[0]->GetIdItem()->id_;
}
return OBJ_NOT_FOUND;
}