• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 #include "hap_manager.h"
16 
17 #include <algorithm>
18 #include <types.h>
19 
20 #include "auto_mutex.h"
21 #include "hilog_wrapper.h"
22 #include "locale_matcher.h"
23 
24 namespace OHOS {
25 namespace Global {
26 namespace Resource {
27 constexpr uint32_t PLURAL_CACHE_MAX_COUNT = 3;
28 
HapManager(ResConfigImpl * resConfig)29 HapManager::HapManager(ResConfigImpl *resConfig)
30     : resConfig_(resConfig)
31 {
32 }
33 
ConvertToPluralStr(int idxRet)34 std::string ConvertToPluralStr(int idxRet)
35 {
36     switch (idxRet) {
37         case OHOS::I18N::PluralRuleType::ZERO:
38             return "zero";
39         case OHOS::I18N::PluralRuleType::ONE:
40             return "one";
41         case OHOS::I18N::PluralRuleType::TWO:
42             return "two";
43         case OHOS::I18N::PluralRuleType::FEW:
44             return "few";
45         case OHOS::I18N::PluralRuleType::MANY:
46             return "many";
47         case OHOS::I18N::PluralRuleType::OTHER:
48         default:
49             return "other";
50     }
51 }
52 
GetPluralRulesAndSelect(int quantity)53 std::string HapManager::GetPluralRulesAndSelect(int quantity)
54 {
55     AutoMutex mutex(this->lock_);
56     std::string defaultRet("other");
57     if (this->resConfig_ == nullptr || this->resConfig_->GetResLocale() == nullptr ||
58         this->resConfig_->GetResLocale()->GetLanguage() == nullptr) {
59         HILOG_ERROR("GetPluralRules language is null!");
60         return defaultRet;
61     }
62     std::string language = this->resConfig_->GetResLocale()->GetLanguage();
63 
64     OHOS::I18N::PluralFormat *pluralFormat = nullptr;
65     for (uint32_t i = 0; i < plurRulesCache_.size(); i++) {
66         auto pair = plurRulesCache_[i];
67         if (language == pair.first) {
68             // cache hit
69             pluralFormat = pair.second;
70             break;
71         }
72     }
73 
74     OHOS::I18N::I18nStatus status = OHOS::I18N::I18nStatus::ISUCCESS;
75     if (pluralFormat == nullptr) {
76         // no cache hit
77         OHOS::I18N::LocaleInfo locale(language.c_str(), "", "");
78         pluralFormat = new(std::nothrow) OHOS::I18N::PluralFormat(locale, status);
79         if (pluralFormat == nullptr) {
80             HILOG_ERROR("new PluralFormat failed");
81             return defaultRet;
82         }
83         if (status != OHOS::I18N::I18nStatus::ISUCCESS) {
84             HILOG_ERROR("PluralFormat init failed");
85             delete pluralFormat;
86             return defaultRet;
87         }
88         // after pluralFormat created, we add it to cache, if > 3 delete oldest one
89         if (plurRulesCache_.size() >= PLURAL_CACHE_MAX_COUNT) {
90             HILOG_DEBUG("cache rotate delete plurRulesMap_ %s", plurRulesCache_[0].first.c_str());
91             delete (plurRulesCache_[0].second);
92             plurRulesCache_.erase(plurRulesCache_.begin());
93         }
94         auto plPair = std::make_pair(language, pluralFormat);
95         plurRulesCache_.push_back(plPair);
96     }
97     int idxRet = pluralFormat->GetPluralRuleIndex(quantity, status);
98     return ConvertToPluralStr(idxRet);
99 }
100 
FindResourceById(uint32_t id)101 const IdItem *HapManager::FindResourceById(uint32_t id)
102 {
103     auto qualifierValue = FindQualifierValueById(id);
104     if (qualifierValue == nullptr) {
105         return nullptr;
106     }
107     return qualifierValue->GetIdItem();
108 }
109 
FindResourceByName(const char * name,const ResType resType)110 const IdItem *HapManager::FindResourceByName(const char *name, const ResType resType)
111 {
112     auto qualifierValue = FindQualifierValueByName(name, resType);
113     if (qualifierValue == nullptr) {
114         return nullptr;
115     }
116     return qualifierValue->GetIdItem();
117 }
118 
FindQualifierValueByName(const char * name,const ResType resType)119 const HapResource::ValueUnderQualifierDir *HapManager::FindQualifierValueByName(
120     const char *name, const ResType resType)
121 {
122     const HapResource::IdValues *idValues = this->GetResourceListByName(name, resType);
123     if (idValues == nullptr) {
124         return nullptr;
125     }
126     const std::vector<HapResource::ValueUnderQualifierDir *> paths = idValues->GetLimitPathsConst();
127 
128     size_t len = paths.size();
129     size_t i = 0;
130     size_t bestIndex = -1;
131     const ResConfigImpl *bestResConfig = nullptr;
132     const ResConfigImpl *currentResConfig = this->resConfig_;
133     for (i = 0; i < len; i++) {
134         HapResource::ValueUnderQualifierDir *path = paths[i];
135         const ResConfigImpl *resConfig = path->GetResConfig();
136         if (!this->resConfig_->Match(resConfig)) {
137             continue;
138         }
139         if (bestResConfig == nullptr) {
140             bestIndex = i;
141             bestResConfig = resConfig;
142             continue;
143         }
144         if (!bestResConfig->IsMoreSuitable(resConfig, currentResConfig)) {
145             bestResConfig = resConfig;
146             bestIndex = i;
147         }
148     }
149     return paths[bestIndex];
150 }
151 
FindQualifierValueById(uint32_t id)152 const HapResource::ValueUnderQualifierDir *HapManager::FindQualifierValueById(uint32_t id)
153 {
154     const HapResource::IdValues *idValues = this->GetResourceList(id);
155     if (idValues == nullptr) {
156         return nullptr;
157     }
158     const std::vector<HapResource::ValueUnderQualifierDir *> paths = idValues->GetLimitPathsConst();
159 
160     size_t len = paths.size();
161     size_t i = 0;
162     size_t bestIndex = -1;
163     const ResConfigImpl *bestResConfig = nullptr;
164     const ResConfigImpl *currentResConfig = this->resConfig_;
165     for (i = 0; i < len; i++) {
166         HapResource::ValueUnderQualifierDir *path = paths[i];
167         const ResConfigImpl *resConfig = path->GetResConfig();
168         if (!this->resConfig_->Match(resConfig)) {
169             continue;
170         }
171         if (bestResConfig == nullptr) {
172             bestIndex = i;
173             bestResConfig = resConfig;
174             continue;
175         }
176         if (!bestResConfig->IsMoreSuitable(resConfig, currentResConfig)) {
177             bestResConfig = resConfig;
178             bestIndex = i;
179         }
180     }
181     return paths[bestIndex];
182 }
183 
UpdateResConfig(ResConfig & resConfig)184 RState HapManager::UpdateResConfig(ResConfig &resConfig)
185 {
186     AutoMutex mutex(this->lock_);
187     this->resConfig_->Copy(resConfig);
188     RState rState = this->ReloadAll();
189     if (rState != SUCCESS) {
190         HILOG_ERROR("ReloadAll() failed when UpdateResConfig!");
191     }
192     return rState;
193 }
194 
195 
GetResConfig(ResConfig & resConfig)196 void HapManager::GetResConfig(ResConfig &resConfig)
197 {
198     AutoMutex mutex(this->lock_);
199     resConfig.Copy(*(this->resConfig_));
200 }
201 
AddResource(const char * path)202 bool HapManager::AddResource(const char *path)
203 {
204     AutoMutex mutex(this->lock_);
205     return this->AddResourcePath(path);
206 }
207 
~HapManager()208 HapManager::~HapManager()
209 {
210     for (size_t i = 0; i < hapResources_.size(); ++i) {
211         auto ptr = hapResources_[i];
212         delete (ptr);
213     }
214     delete resConfig_;
215 
216     auto iter = plurRulesCache_.begin();
217     for (; iter != plurRulesCache_.end(); iter++) {
218         HILOG_DEBUG("delete plurRulesMap_ %s", iter->first.c_str());
219         auto ptr = iter->second;
220         delete (ptr);
221     }
222 }
223 
GetResourceList(uint32_t ident) const224 const HapResource::IdValues *HapManager::GetResourceList(uint32_t ident) const
225 {
226     // one id only exit in one hap
227     for (size_t i = 0; i < hapResources_.size(); ++i) {
228         HapResource *pResource = hapResources_[i];
229         const HapResource::IdValues *out = pResource->GetIdValues(ident);
230         if (out != nullptr) {
231             return out;
232         }
233     }
234     return nullptr;
235 }
236 
GetResourceListByName(const char * name,const ResType resType) const237 const HapResource::IdValues *HapManager::GetResourceListByName(const char *name, const ResType resType) const
238 {
239     // first match will return
240     for (size_t i = 0; i < hapResources_.size(); ++i) {
241         HapResource *pResource = hapResources_[i];
242         const HapResource::IdValues *out = pResource->GetIdValuesByName(std::string(name), resType);
243         if (out != nullptr) {
244             return out;
245         }
246     }
247     return nullptr;
248 }
249 
AddResourcePath(const char * path)250 bool HapManager::AddResourcePath(const char *path)
251 {
252     std::string sPath(path);
253     std::vector<std::string>::iterator it = std::find(loadedHapPaths_.begin(),
254         loadedHapPaths_.end(), sPath);
255     if (it != loadedHapPaths_.end()) {
256         HILOG_ERROR(" %s has already been loaded!", path);
257         return false;
258     }
259     const HapResource *pResource = HapResource::LoadFromIndex(path, resConfig_);
260     if (pResource == nullptr) {
261         return false;
262     }
263     this->hapResources_.push_back(const_cast<HapResource *>(pResource));
264     this->loadedHapPaths_.push_back(sPath);
265     return true;
266 }
267 
ReloadAll()268 RState HapManager::ReloadAll()
269 {
270     if (hapResources_.size() == 0) {
271         return SUCCESS;
272     }
273     std::vector<HapResource *> newResources;
274     for (size_t i = 0; i < hapResources_.size(); ++i) {
275         const HapResource *pResource = HapResource::LoadFromIndex(hapResources_[i]->GetIndexPath().c_str(), resConfig_);
276         if (pResource == nullptr) {
277             for (size_t j = 0; j < newResources.size(); ++j) {
278                 delete (newResources[j]);
279             }
280             return HAP_INIT_FAILED;
281         }
282         newResources.push_back(const_cast<HapResource *>(pResource));
283     }
284     for (size_t i = 0; i < hapResources_.size(); ++i) {
285         delete (hapResources_[i]);
286     }
287     hapResources_ = newResources;
288     return SUCCESS;
289 }
290 } // namespace Resource
291 } // namespace Global
292 } // namespace OHOS