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