• 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 "base/resource/ace_res_config.h"
16 
17 #include <algorithm>
18 #include <cstddef>
19 #include <cstring>
20 #include <memory>
21 #include <unordered_map>
22 #include <utility>
23 
24 #include "base/i18n/localization.h"
25 #include "base/log/ace_trace.h"
26 #include "base/log/log.h"
27 #include "base/resource/ace_res_data_struct.h"
28 #include "base/resource/ace_res_key_parser.h"
29 #include "base/utils/linear_map.h"
30 #include "base/utils/utils.h"
31 
32 namespace OHOS::Ace {
33 namespace {
34 
35 const std::unordered_map<std::string, std::string> LOCALE_PARENTS {
36     { "ar-DZ", "ar-015" },
37     { "ar-EH", "ar-015" },
38     { "ar-LY", "ar-015" },
39     { "ar-MA", "ar-015" },
40     { "ar-TN", "ar-015" },
41     { "zh-MO", "zh-HK" },
42     { "en-150", "en-001" },
43     { "en-AG", "en-001" },
44     { "en-AI", "en-001" },
45     { "en-AU", "en-001" },
46     { "en-BB", "en-001" },
47     { "en-BE", "en-001" },
48     { "en-BM", "en-001" },
49     { "en-BS", "en-001" },
50     { "en-BZ", "en-001" },
51     { "en-CC", "en-001" },
52     { "en-CK", "en-001" },
53     { "en-CX", "en-001" },
54     { "en-DG", "en-001" },
55     { "en-ER", "en-001" },
56     { "en-FK", "en-001" },
57     { "en-FM", "en-001" },
58     { "en-GB", "en-001" },
59     { "en-GD", "en-001" },
60     { "en-GG", "en-001" },
61     { "en-GI", "en-001" },
62     { "en-GY", "en-001" },
63     { "en-HK", "en-001" },
64     { "en-IE", "en-001" },
65     { "en-IM", "en-001" },
66     { "en-IN", "en-001" },
67     { "en-IO", "en-001" },
68     { "en-JE", "en-001" },
69     { "en-KI", "en-001" },
70     { "en-KN", "en-001" },
71     { "en-KY", "en-001" },
72     { "en-LC", "en-001" },
73     { "en-LR", "en-001" },
74     { "en-LS", "en-001" },
75     { "en-MM", "en-001" },
76     { "en-MO", "en-001" },
77     { "en-MS", "en-001" },
78     { "en-MT", "en-001" },
79     { "en-MY", "en-001" },
80     { "en-NF", "en-001" },
81     { "en-NR", "en-001" },
82     { "en-NU", "en-001" },
83     { "en-NZ", "en-001" },
84     { "en-PG", "en-001" },
85     { "en-PK", "en-001" },
86     { "en-PN", "en-001" },
87     { "en-PW", "en-001" },
88     { "en-SB", "en-001" },
89     { "en-SC", "en-001" },
90     { "en-SD", "en-001" },
91     { "en-SG", "en-001" },
92     { "en-SH", "en-001" },
93     { "en-SL", "en-001" },
94     { "en-SS", "en-001" },
95     { "en-SX", "en-001" },
96     { "en-SZ", "en-001" },
97     { "en-TC", "en-001" },
98     { "en-TK", "en-001" },
99     { "en-TT", "en-001" },
100     { "en-TV", "en-001" },
101     { "en-VC", "en-001" },
102     { "en-VG", "en-001" },
103     { "en-WS", "en-001" },
104     { "en-ZG", "en-001" },
105     { "es-AR", "es-419" },
106     { "es-BO", "es-419" },
107     { "es-BR", "es-419" },
108     { "es-BZ", "es-419" },
109     { "es-CL", "es-419" },
110     { "es-CO", "es-419" },
111     { "es-CR", "es-419" },
112     { "es-CU", "es-419" },
113     { "es-DO", "es-419" },
114     { "es-EC", "es-419" },
115     { "es-GT", "es-419" },
116     { "es-HN", "es-419" },
117     { "es-MX", "es-419" },
118     { "es-NI", "es-419" },
119     { "es-PA", "es-419" },
120     { "es-PE", "es-419" },
121     { "es-PR", "es-419" },
122     { "es-PY", "es-419" },
123     { "es-SV", "es-419" },
124     { "es-US", "es-419" },
125     { "es-UY", "es-419" },
126     { "es-VE", "es-419" },
127     { "pt-AO", "pt-PT" },
128     { "pt-CH", "pt-PT" },
129     { "pt-CV", "pt-PT" },
130     { "pt-GQ", "pt-PT" },
131     { "pt-GW", "pt-PT" },
132     { "pt-LU", "pt-PT" },
133     { "pt-MO", "pt-PT" },
134     { "pt-MZ", "pt-PT" },
135     { "pt-ST", "pt-PT" },
136     { "pt-TL", "pt-PT" },
137 };
138 
139 const std::unordered_map<std::string, std::string> DEFAULT_LANG {
140     { "es-419", "es-US" },
141     { "en-Qaag", "en-GB" },
142     { "en-001", "en-GB" },
143 };
144 
145 const std::unordered_map<std::string, std::string> LANGUAGE_CODE_MAP {
146     { "iw", "he" },
147     { "tl", "fil" },
148     { "in", "id" },
149 };
150 
ComputeScript(const AceResConfig & resConfig)151 std::string ComputeScript(const AceResConfig& resConfig)
152 {
153     return Localization::ComputeScript(resConfig.language_, resConfig.region_);
154 }
155 
ConvertLocaleTagToConfig(const std::string & localeTag)156 AceResConfig ConvertLocaleTagToConfig(const std::string& localeTag)
157 {
158     std::string language, script, region;
159     Localization::ParseLocaleTag(localeTag, language, script, region, false);
160     return AceResConfig(language, script, region);
161 }
162 
ConvertLocaleConfigToTag(const AceResConfig & localeConfig)163 std::string ConvertLocaleConfigToTag(const AceResConfig& localeConfig)
164 {
165     std::string localeTag = localeConfig.language_;
166     if (!localeConfig.script_.empty()) {
167         localeTag += ('-' + localeConfig.script_);
168     }
169     if (!localeConfig.region_.empty()) {
170         localeTag += ('-' + localeConfig.region_);
171     }
172     return localeTag;
173 }
174 
IsPseudoLocale(const AceResConfig & resConfig)175 bool IsPseudoLocale(const AceResConfig& resConfig)
176 {
177     return (resConfig.language_ == "en" && resConfig.region_ == "XA") ||
178            (resConfig.language_ == "ar" && resConfig.region_ == "XB");
179 }
180 
MatchLocaleConfig(const std::vector<AceResConfig> & candidatesLocaleConfig,const AceResConfig & deviceLocaleConfig,std::vector<AceResConfig> & matchedLocaleConfigs,bool isDeclarative=false)181 void MatchLocaleConfig(const std::vector<AceResConfig>& candidatesLocaleConfig, const AceResConfig& deviceLocaleConfig,
182     std::vector<AceResConfig>& matchedLocaleConfigs, bool isDeclarative = false)
183 {
184     std::string deviceLanguage = deviceLocaleConfig.language_;
185     std::string deviceScript = deviceLocaleConfig.script_;
186     auto iter = LANGUAGE_CODE_MAP.find(deviceLanguage);
187     if (iter != LANGUAGE_CODE_MAP.end()) {
188         deviceLanguage = iter->second;
189     }
190     for (auto& candidate : candidatesLocaleConfig) {
191         if (isDeclarative && candidate.language_ == "" && candidate.script_ == "") {
192             matchedLocaleConfigs.emplace_back(candidate);
193             continue;
194         }
195         std::string candidateLanguage = candidate.language_;
196         // Languages codes need to be specially handled.
197         auto candidateIter = LANGUAGE_CODE_MAP.find(candidateLanguage);
198         if (candidateIter != LANGUAGE_CODE_MAP.end()) {
199             candidateLanguage = candidateIter->second;
200         }
201         if (candidateLanguage != deviceLanguage) {
202             continue;
203         }
204         if (IsPseudoLocale(candidate)) {
205             if (IsPseudoLocale(deviceLocaleConfig)) {
206                 matchedLocaleConfigs.emplace_back(candidate);
207             }
208             continue;
209         }
210         if (deviceLanguage == "en" && deviceScript == "Qaag") {
211             deviceScript = "Latn";
212         }
213         // Compute Script when it is not provided.
214         std::string candidateScript = candidate.script_.empty() ? ComputeScript(candidate) : candidate.script_;
215         if (deviceScript != candidateScript) {
216             continue;
217         }
218         matchedLocaleConfigs.emplace_back(candidate);
219     }
220 }
221 
FindBacktrackPath(const AceResConfig & localeConfig,std::vector<std::string> & backtrackPath,const std::string & localeTag)222 void FindBacktrackPath(
223     const AceResConfig& localeConfig, std::vector<std::string>& backtrackPath, const std::string& localeTag)
224 {
225     if (LOCALE_PARENTS.find(localeTag) != LOCALE_PARENTS.end()) {
226         std::string curTag = LOCALE_PARENTS.find(localeTag)->second;
227         backtrackPath.emplace_back(curTag);
228         FindBacktrackPath(localeConfig, backtrackPath, curTag);
229     } else {
230         backtrackPath.emplace_back(localeConfig.language_);
231     }
232 }
233 
IsOnBacktrackingPath(const std::string & bestConfigTag,const std::string & candidateConfigTag,const AceResConfig & bestLocaleConfig,const AceResConfig & candidateLocaleConfig,std::vector<std::string> backtrackPath)234 bool IsOnBacktrackingPath(const std::string& bestConfigTag, const std::string& candidateConfigTag,
235     const AceResConfig& bestLocaleConfig, const AceResConfig& candidateLocaleConfig,
236     std::vector<std::string> backtrackPath)
237 {
238     std::vector<std::string> bestConfigBacktrackPaths;
239     FindBacktrackPath(bestLocaleConfig, bestConfigBacktrackPaths, bestConfigTag);
240     std::vector<std::string> candidateConfigBacktrackPaths;
241     FindBacktrackPath(candidateLocaleConfig, candidateConfigBacktrackPaths, candidateConfigTag);
242     int32_t bestConfigIndex = -1;
243     int32_t candidateConfigIndex = -1;
244     for (std::size_t i = 0; i < backtrackPath.size(); i++) {
245         for (const auto& bestConfigPath : bestConfigBacktrackPaths) {
246             if (bestConfigPath == backtrackPath[i] && bestConfigIndex == -1) {
247                 bestConfigIndex = static_cast<int32_t>(i);
248             }
249         }
250         for (const auto& candidateConfigPath : candidateConfigBacktrackPaths) {
251             if (candidateConfigPath == backtrackPath[i] && candidateConfigIndex == -1) {
252                 candidateConfigIndex = static_cast<int32_t>(i);
253             }
254         }
255     }
256     if (bestConfigIndex < candidateConfigIndex) {
257         return (bestConfigIndex == -1);
258     } else if (candidateConfigIndex < bestConfigIndex) {
259         return (candidateConfigIndex != -1);
260     }
261     // Check if candidate and best are on the default area of device's backtracking path.
262     for (auto& path : backtrackPath) {
263         if (DEFAULT_LANG.find(path) != DEFAULT_LANG.end()) {
264             std::string curTag = DEFAULT_LANG.find(path)->second;
265             if (bestConfigTag == curTag) {
266                 return false;
267             } else if (candidateConfigTag == curTag) {
268                 return true;
269             }
270         }
271     }
272 
273     // Compute the default region code through the device language code.
274     std::string language, script, region;
275     Localization::ParseLocaleTag(backtrackPath[backtrackPath.size() - 1], language, script, region, true);
276 
277     if (bestLocaleConfig.region_ == region) {
278         return false;
279     }
280     if (candidateLocaleConfig.region_ == region) {
281         return true;
282     }
283 
284     // If configs did not meet all the conditions above, sort the config region with dictionary order.
285     return strcmp(bestLocaleConfig.region_.c_str(), candidateLocaleConfig.region_.c_str()) >= 0;
286 }
287 
IsLocaleConfigMoreSpecified(const AceResConfig & bestLocaleConfig,const AceResConfig & deviceLocaleConfig,const AceResConfig & candidateLocaleConfig)288 bool IsLocaleConfigMoreSpecified(const AceResConfig& bestLocaleConfig, const AceResConfig& deviceLocaleConfig,
289     const AceResConfig& candidateLocaleConfig)
290 {
291     // Candidates' language and script are equal with the device's after being filtered MatchLocaleConfig().
292     std::string deviceRegion = deviceLocaleConfig.region_;
293     if (bestLocaleConfig.region_ == deviceRegion) {
294         return false;
295     }
296     if (candidateLocaleConfig.region_ == deviceRegion) {
297         return true;
298     }
299     std::string deviceTag = deviceLocaleConfig.language_ + '-' + deviceLocaleConfig.region_;
300     std::vector<std::string> deviceBacktrackPath;
301     FindBacktrackPath(deviceLocaleConfig, deviceBacktrackPath, deviceTag);
302     std::string bestConfigTag = bestLocaleConfig.language_;
303     if (!bestLocaleConfig.region_.empty()) {
304         bestConfigTag += '-' + bestLocaleConfig.region_;
305     }
306     std::string candidateConfigTag = candidateLocaleConfig.language_;
307     if (!candidateLocaleConfig.region_.empty()) {
308         candidateConfigTag += '-' + candidateLocaleConfig.region_;
309     }
310     int32_t bestConfigIndex = -1;
311     int32_t candidateConfigIndex = -1;
312     for (std::size_t i = 0; i < deviceBacktrackPath.size(); i++) {
313         if (deviceBacktrackPath[i] == bestConfigTag && bestConfigIndex == -1) {
314             bestConfigIndex = static_cast<int32_t>(i);
315         }
316         if (deviceBacktrackPath[i] == candidateConfigTag && candidateConfigIndex == -1) {
317             candidateConfigIndex = static_cast<int32_t>(i);
318         }
319     }
320     if (bestConfigIndex < candidateConfigIndex) {
321         return (bestConfigIndex == -1);
322     } else if (candidateConfigIndex < bestConfigIndex) {
323         return (candidateConfigIndex != -1);
324     }
325     // Neither best nor candidate on the device's backtracking path, check if they are the default locale of the device.
326     if (candidateConfigIndex == bestConfigIndex && candidateConfigIndex == -1) {
327         std::string deviceTagWithScript = deviceLocaleConfig.language_ + "-" + deviceLocaleConfig.script_;
328         if (DEFAULT_LANG.find(deviceTagWithScript) != DEFAULT_LANG.end()) {
329             std::string defaultTag = DEFAULT_LANG.find(deviceTagWithScript)->second;
330             std::string defaultRegion = defaultTag.substr(defaultTag.find('-') + 1);
331             if (candidateLocaleConfig.region_ == defaultRegion) {
332                 return true;
333             }
334             if (bestLocaleConfig.region_ == defaultRegion) {
335                 return false;
336             }
337         }
338         // If they are not on the default area, continue to check the candidates' backtacking path.
339         return IsOnBacktrackingPath(
340             bestConfigTag, candidateConfigTag, bestLocaleConfig, candidateLocaleConfig, deviceBacktrackPath);
341     }
342     // Both best and candidate on the device's backtracking path with same index.
343     return false;
344 }
345 
SortLocaleConfigs(std::vector<AceResConfig> & candidatesLocaleConfig,const AceResConfig & deviceLocaleConfig,int32_t left,int32_t right)346 void SortLocaleConfigs(std::vector<AceResConfig>& candidatesLocaleConfig, const AceResConfig& deviceLocaleConfig,
347     int32_t left, int32_t right)
348 {
349     if (left < right) {
350         AceResConfig bestLocaleConfig = candidatesLocaleConfig[left];
351         int32_t i = left;
352         int32_t j = right;
353         while (i < j) {
354             while (i < j &&
355                    !IsLocaleConfigMoreSpecified(bestLocaleConfig, deviceLocaleConfig, candidatesLocaleConfig[j])) {
356                 j--;
357             }
358             candidatesLocaleConfig[i] = candidatesLocaleConfig[j];
359             while (
360                 i < j && IsLocaleConfigMoreSpecified(bestLocaleConfig, deviceLocaleConfig, candidatesLocaleConfig[i])) {
361                 i++;
362             }
363             candidatesLocaleConfig[j] = candidatesLocaleConfig[i];
364         }
365         candidatesLocaleConfig[i] = bestLocaleConfig;
366         SortLocaleConfigs(candidatesLocaleConfig, deviceLocaleConfig, left, i - 1);
367         SortLocaleConfigs(candidatesLocaleConfig, deviceLocaleConfig, i + 1, right);
368     }
369 }
370 
IsLowerResolutionPreferred(int32_t high,int32_t low,int32_t request)371 bool IsLowerResolutionPreferred(int32_t high, int32_t low, int32_t request)
372 {
373     if (request <= low) {
374         return true;
375     }
376 
377     if (request >= high) {
378         return false;
379     }
380 
381     return ((2 * low) - request) * high > request * request; // scaling down is 2x better than up
382 }
383 
IsCandidateResolutionPreferred(const AceResConfig & deviceConfig,const AceResConfig & bestConfig,const AceResConfig & candidateConfig)384 bool IsCandidateResolutionPreferred(
385     const AceResConfig& deviceConfig, const AceResConfig& bestConfig, const AceResConfig& candidateConfig)
386 {
387     if (bestConfig.resolution_ == candidateConfig.resolution_) {
388         return false;
389     }
390 
391     const ResolutionType bestRes = bestConfig.resolution_ != ResolutionType::RESOLUTION_NONE
392                                        ? bestConfig.resolution_
393                                        : ResolutionType::RESOLUTION_MDPI;
394     const ResolutionType candidateRes = candidateConfig.resolution_ != ResolutionType::RESOLUTION_NONE
395                                             ? candidateConfig.resolution_
396                                             : ResolutionType::RESOLUTION_MDPI;
397 
398     if (bestRes == ResolutionType::RESOLUTION_ANY) {
399         return false;
400     } else if (candidateRes == ResolutionType::RESOLUTION_ANY) {
401         return true;
402     }
403 
404     ResolutionType deviceRes = deviceConfig.resolution_;
405     if (deviceConfig.resolution_ == ResolutionType::RESOLUTION_NONE ||
406         deviceConfig.resolution_ == ResolutionType::RESOLUTION_ANY) {
407         deviceRes = ResolutionType::RESOLUTION_MDPI;
408     }
409 
410     if (bestRes > candidateRes) {
411         return IsLowerResolutionPreferred(
412             static_cast<int32_t>(bestRes), static_cast<int32_t>(candidateRes), static_cast<int32_t>(deviceRes));
413     }
414 
415     if (bestRes < candidateRes) {
416         return !IsLowerResolutionPreferred(
417             static_cast<int32_t>(candidateRes), static_cast<int32_t>(bestRes), static_cast<int32_t>(deviceRes));
418     }
419 
420     return false;
421 }
422 
IsCandidateResConfigPreferred(const AceResConfig & deviceConfig,const AceResConfig & bestConfig,const AceResConfig & candidateConfig)423 bool IsCandidateResConfigPreferred(
424     const AceResConfig& deviceConfig, const AceResConfig& bestConfig, const AceResConfig& candidateConfig)
425 {
426     if ((candidateConfig.mcc_ != bestConfig.mcc_) && deviceConfig.mcc_) {
427         return candidateConfig.mcc_;
428     }
429     if ((candidateConfig.mnc_ != bestConfig.mnc_) && deviceConfig.mnc_) {
430         return candidateConfig.mnc_;
431     }
432 
433     if (bestConfig.orientation_ != candidateConfig.orientation_ &&
434         deviceConfig.orientation_ != DeviceOrientation::ORIENTATION_UNDEFINED) {
435         return candidateConfig.orientation_ != DeviceOrientation::ORIENTATION_UNDEFINED;
436     }
437 
438     if (bestConfig.colorMode_ != candidateConfig.colorMode_) {
439         return candidateConfig.colorMode_ == deviceConfig.colorMode_;
440     }
441 
442     if (bestConfig.deviceType_ != DeviceType::UNKNOWN || candidateConfig.deviceType_ != DeviceType::UNKNOWN) {
443         if (bestConfig.deviceType_ != candidateConfig.deviceType_) {
444             return candidateConfig.deviceType_ != DeviceType::UNKNOWN;
445         }
446     }
447 
448     return IsCandidateResolutionPreferred(deviceConfig, bestConfig, candidateConfig);
449 }
450 
IsCandidateDeclarativeResConfigPreferred(const AceResConfig & deviceConfig,const AceResConfig & bestConfig,const AceResConfig & candidateConfig)451 bool IsCandidateDeclarativeResConfigPreferred(
452     const AceResConfig& deviceConfig, const AceResConfig& bestConfig, const AceResConfig& candidateConfig)
453 {
454     if (bestConfig.screenLong_ != candidateConfig.screenLong_ &&
455         deviceConfig.screenLong_ != LongScreenType::LONG_SCREEN_UNDEFINED) {
456         if ((bestConfig.screenLong_ == deviceConfig.screenLong_) ||
457             (candidateConfig.screenLong_ == deviceConfig.screenLong_)) {
458             return candidateConfig.screenLong_ == deviceConfig.screenLong_;
459         }
460         return candidateConfig.screenLong_ == LongScreenType::LONG_SCREEN_UNDEFINED;
461     }
462 
463     if (bestConfig.screenShape_ != candidateConfig.screenShape_ &&
464         deviceConfig.screenShape_ != ScreenShape::SCREEN_SHAPE_UNDEFINED) {
465         if ((bestConfig.screenShape_ == deviceConfig.screenShape_) ||
466             (candidateConfig.screenShape_ == deviceConfig.screenShape_)) {
467             return candidateConfig.screenShape_ == deviceConfig.screenShape_;
468         }
469         return candidateConfig.screenShape_ == ScreenShape::SCREEN_SHAPE_UNDEFINED;
470     }
471 
472     if (bestConfig.orientation_ != candidateConfig.orientation_ &&
473         deviceConfig.orientation_ != DeviceOrientation::ORIENTATION_UNDEFINED) {
474         return candidateConfig.orientation_ != DeviceOrientation::ORIENTATION_UNDEFINED;
475     }
476 
477     if (bestConfig.colorMode_ != candidateConfig.colorMode_ &&
478         deviceConfig.colorMode_ != ColorMode::COLOR_MODE_UNDEFINED) {
479         if ((bestConfig.colorMode_ == deviceConfig.colorMode_) ||
480             (candidateConfig.colorMode_ == deviceConfig.colorMode_)) {
481             return candidateConfig.colorMode_ == deviceConfig.colorMode_;
482         }
483         return candidateConfig.colorMode_ == ColorMode::COLOR_MODE_UNDEFINED;
484     }
485 
486     if (bestConfig.deviceType_ != DeviceType::UNKNOWN || candidateConfig.deviceType_ != DeviceType::UNKNOWN) {
487         if (bestConfig.deviceType_ != candidateConfig.deviceType_) {
488             return candidateConfig.deviceType_ != DeviceType::UNKNOWN;
489         }
490     }
491 
492     return IsCandidateResolutionPreferred(deviceConfig, bestConfig, candidateConfig);
493 }
494 
IsDialectsOfEnUs(const AceResConfig & config)495 bool IsDialectsOfEnUs(const AceResConfig& config)
496 {
497     int tracebackPathLength = 0;
498     if (config.language_ == "en") {
499         std::string configTag = config.language_ + "-" + config.region_;
500         std::vector<std::string> backtrackPath;
501         backtrackPath.push_back(configTag);
502         FindBacktrackPath(config, backtrackPath, configTag);
503         tracebackPathLength = static_cast<int>(backtrackPath.size());
504     }
505     // backtracking size 2, means that the locale is an American English dialect.
506     return tracebackPathLength == 2;
507 }
508 
IsBaseLanguagePreferred(const AceResConfig & deviceConfig,const AceResConfig & bestConfig,const AceResConfig & candidateConfig)509 CompareResult IsBaseLanguagePreferred(
510     const AceResConfig& deviceConfig, const AceResConfig& bestConfig, const AceResConfig& candidateConfig)
511 {
512     if (deviceConfig.language_ == "en" && deviceConfig.region_ == "US") {
513         if (candidateConfig.region_.length() == 0 && candidateConfig.language_.length() == 0) {
514             return (bestConfig.region_ != "US" && bestConfig.region_.length() != 0) ? CompareResult::PREFERRED
515                                                                                     : CompareResult::NOT_PREFERRED;
516         }
517         if (bestConfig.region_.length() == 0 && bestConfig.language_.length() == 0) {
518             return (candidateConfig.region_ == "US" || candidateConfig.region_.length() == 0)
519                        ? CompareResult::PREFERRED
520                        : CompareResult::NOT_PREFERRED;
521         }
522     }
523     if (!IsDialectsOfEnUs(deviceConfig)) {
524         if (bestConfig.language_.length() == 0 && candidateConfig.language_.length() > 0) {
525             return CompareResult::PREFERRED;
526         } else if (bestConfig.language_.length() > 0 && candidateConfig.language_.length() == 0) {
527             return CompareResult::NOT_PREFERRED;
528         }
529     }
530     return CompareResult::EQUAL_RES;
531 }
532 
IsCandidateDeclarativeConfigPreferred(const AceResConfig & bestConfig,const AceResConfig & deviceConfig,const AceResConfig & candidateConfig)533 bool IsCandidateDeclarativeConfigPreferred(
534     const AceResConfig& bestConfig, const AceResConfig& deviceConfig, const AceResConfig& candidateConfig)
535 {
536     if (bestConfig.language_ != candidateConfig.language_) {
537         auto isBasePreferred = IsBaseLanguagePreferred(deviceConfig, bestConfig, candidateConfig);
538         if (isBasePreferred == CompareResult::PREFERRED) {
539             return true;
540         }
541         if (isBasePreferred == CompareResult::NOT_PREFERRED) {
542             return false;
543         }
544     }
545 
546     if (bestConfig.region_ != candidateConfig.region_) {
547         return IsLocaleConfigMoreSpecified(bestConfig, deviceConfig, candidateConfig);
548     }
549 
550     return IsCandidateDeclarativeResConfigPreferred(deviceConfig, bestConfig, candidateConfig);
551 }
552 
SortResConfigs(const AceResConfig & desiredConfig,std::vector<AceResConfig> & candidateConfigs,int32_t left,int32_t right)553 void SortResConfigs(
554     const AceResConfig& desiredConfig, std::vector<AceResConfig>& candidateConfigs, int32_t left, int32_t right)
555 {
556     if (left < right) {
557         AceResConfig bestConfig = candidateConfigs[left];
558         int32_t i = left;
559         int32_t j = right;
560         while (i < j) {
561             while (i < j && !IsCandidateResConfigPreferred(desiredConfig, bestConfig, candidateConfigs[j])) {
562                 j--;
563             }
564             candidateConfigs[i] = candidateConfigs[j];
565             while (i < j && IsCandidateResConfigPreferred(desiredConfig, bestConfig, candidateConfigs[i])) {
566                 i++;
567             }
568             candidateConfigs[j] = candidateConfigs[i];
569         }
570         candidateConfigs[i] = bestConfig;
571         SortResConfigs(desiredConfig, candidateConfigs, left, i - 1);
572         SortResConfigs(desiredConfig, candidateConfigs, i + 1, right);
573     }
574 }
575 
SortDeclarativeResConfigs(const AceResConfig & desiredConfig,std::vector<AceResConfig> & candidateConfigs,int32_t left,int32_t right)576 void SortDeclarativeResConfigs(
577     const AceResConfig& desiredConfig, std::vector<AceResConfig>& candidateConfigs, int32_t left, int32_t right)
578 {
579     if (left < right) {
580         AceResConfig bestConfig = candidateConfigs[left];
581         int32_t i = left;
582         int32_t j = right;
583         while (i < j) {
584             while (i < j && !IsCandidateDeclarativeConfigPreferred(bestConfig, desiredConfig, candidateConfigs[j])) {
585                 j--;
586             }
587             candidateConfigs[i] = candidateConfigs[j];
588             while (i < j && IsCandidateDeclarativeConfigPreferred(bestConfig, desiredConfig, candidateConfigs[i])) {
589                 i++;
590             }
591             candidateConfigs[j] = candidateConfigs[i];
592         }
593         candidateConfigs[i] = bestConfig;
594         SortDeclarativeResConfigs(desiredConfig, candidateConfigs, left, i - 1);
595         SortDeclarativeResConfigs(desiredConfig, candidateConfigs, i + 1, right);
596     }
597 }
598 
IsOrientationMatch(const AceResConfig & desired,const AceResConfig & supported)599 bool IsOrientationMatch(const AceResConfig& desired, const AceResConfig& supported)
600 {
601     return supported.orientation_ == DeviceOrientation::ORIENTATION_UNDEFINED ||
602            supported.orientation_ == desired.orientation_;
603 }
604 
IsDeviceTypeMatch(const AceResConfig & desired,const AceResConfig & supported)605 bool IsDeviceTypeMatch(const AceResConfig& desired, const AceResConfig& supported)
606 {
607     return supported.deviceType_ == DeviceType::UNKNOWN || supported.deviceType_ == desired.deviceType_;
608 }
609 
IsColorModeMatch(const AceResConfig & desired,const AceResConfig & supported)610 bool IsColorModeMatch(const AceResConfig& desired, const AceResConfig& supported)
611 {
612     return supported.colorMode_ == ColorMode::COLOR_MODE_UNDEFINED || supported.colorMode_ == desired.colorMode_;
613 }
614 
IsMccMncMatch(const AceResConfig & desired,const AceResConfig & supported)615 bool IsMccMncMatch(const AceResConfig& desired, const AceResConfig& supported)
616 {
617     if (supported.mcc_ != 0 && supported.mcc_ != desired.mcc_) {
618         return false;
619     }
620     return !(supported.mnc_ != 0 && supported.mnc_ != desired.mnc_);
621 }
622 
IsResolutionMatch(const AceResConfig & desired,const AceResConfig & supported)623 bool IsResolutionMatch(const AceResConfig& desired, const AceResConfig& supported)
624 {
625     return supported.resolution_ == ResolutionType::RESOLUTION_NONE || supported.resolution_ == desired.resolution_;
626 }
627 
MatchResConfig(const AceResConfig & desired,const AceResConfig & supported)628 bool MatchResConfig(const AceResConfig& desired, const AceResConfig& supported)
629 {
630     return !(!IsOrientationMatch(desired, supported) || !IsDeviceTypeMatch(desired, supported) ||
631              !IsColorModeMatch(desired, supported) || !IsMccMncMatch(desired, supported) ||
632              !IsResolutionMatch(desired, supported));
633 }
634 
DeclarativeMatchResConfig(const AceResConfig & desired,const AceResConfig & supported)635 bool DeclarativeMatchResConfig(const AceResConfig& desired, const AceResConfig& supported)
636 {
637     return !(!IsOrientationMatch(desired, supported) || !IsDeviceTypeMatch(desired, supported));
638 }
639 
GetConfigString(KeyType type,int32_t value,std::string & buf)640 void GetConfigString(KeyType type, int32_t value, std::string& buf)
641 {
642     std::string appending;
643     if (!buf.empty()) {
644         appending = "-";
645     }
646 
647     switch (type) {
648         case KeyType::ORIENTATION:
649             appending.append(
650                 AceResKeyParser::GetInstance().GetOrientationByType(static_cast<DeviceOrientation>(value)));
651             break;
652         case KeyType::DEVICETYPE:
653             appending.append(AceResKeyParser::GetInstance().GetDeviceByType(static_cast<DeviceType>(value)));
654             break;
655         case KeyType::RESOLUTION:
656             appending.append(AceResKeyParser::GetInstance().GetResolutionByType(static_cast<ResolutionType>(value)));
657             break;
658         case KeyType::COLOR_MODE:
659             appending.append(AceResKeyParser::GetInstance().GetColorModeByType(static_cast<ColorMode>(value)));
660             break;
661         case KeyType::DECLARATIVE_COLOR_MODE:
662             appending.append(
663                 AceResKeyParser::GetInstance().GetDeclarativeColorModeByType(static_cast<ColorMode>(value)));
664             break;
665         case KeyType::MCC:
666             appending.append(AceResKeyParser::GetInstance().GetMccByValue(value));
667             break;
668         case KeyType::MNC_SHORT_LEN:
669             appending.append(AceResKeyParser::GetInstance().GetMncShortLenByValue(value));
670             break;
671         case KeyType::MNC:
672             appending.append(AceResKeyParser::GetInstance().GetMncByValue(value));
673             break;
674         case KeyType::SCREENSHAPE:
675             appending.append(AceResKeyParser::GetInstance().GetScreenShapeByType(static_cast<ScreenShape>(value)));
676             break;
677         case KeyType::LONGSCREEN:
678             appending.append(AceResKeyParser::GetInstance().GetScreenLongByType(static_cast<LongScreenType>(value)));
679             break;
680         default:
681             break;
682     }
683 
684     if (appending != "" && appending != "-") {
685         buf.append(appending);
686     }
687 }
688 
689 } // namespace
690 
operator ==(const AceResConfig & other) const691 bool AceResConfig::operator==(const AceResConfig& other) const
692 {
693     return language_ == other.language_ && script_ == other.script_ && region_ == other.region_ && mcc_ == other.mcc_ &&
694            mnc_ == other.mnc_ && screenLong_ == other.screenLong_ && screenShape_ == other.screenShape_ &&
695            orientation_ == other.orientation_ && colorMode_ == other.colorMode_ && deviceType_ == other.deviceType_ &&
696            resolution_ == other.resolution_;
697 }
698 
GetLocaleFallback(const std::string & localeTag,const std::vector<std::string> & localeList)699 std::vector<std::string> AceResConfig::GetLocaleFallback(
700     const std::string& localeTag, const std::vector<std::string>& localeList)
701 {
702     ACE_SCOPED_TRACE("GetLocaleFallback");
703     std::vector<std::string> fileList;
704     AceResConfig::MatchAndSortI18nConfigs(localeList, localeTag, fileList);
705     return fileList;
706 }
707 
GetResourceFallback(const std::vector<std::string> & resourceList)708 std::vector<std::string> AceResConfig::GetResourceFallback(const std::vector<std::string>& resourceList)
709 {
710     ACE_SCOPED_TRACE("GetResourceFallback");
711     std::string deviceConfigTag = GetCurrentDeviceResTag();
712     std::vector<std::string> fileList;
713     AceResConfig::MatchAndSortResConfigs(resourceList, deviceConfigTag, fileList);
714     return fileList;
715 }
716 
GetStyleResourceFallback(const std::vector<std::string> & resourceList)717 std::vector<std::string> AceResConfig::GetStyleResourceFallback(const std::vector<std::string>& resourceList)
718 {
719     std::vector<std::string> fileList;
720     std::string deviceConfigTag = GetCurrentDeviceResTag();
721     AceResConfig::MatchAndSortStyleResConfigs(resourceList, deviceConfigTag, fileList);
722     return fileList;
723 }
724 
GetDeclarativeResourceFallback(const std::set<std::string> & resourceFolderList)725 std::vector<std::string> AceResConfig::GetDeclarativeResourceFallback(const std::set<std::string>& resourceFolderList)
726 {
727     std::string deviceConfigTag = GetCurrentDeviceDeclarativeResTag();
728     std::vector<std::string> folderList;
729     AceResConfig::MatchAndSortDeclarativeResConfigs(resourceFolderList, deviceConfigTag, folderList);
730     return folderList;
731 }
732 
GetCurrentDeviceResTag()733 std::string AceResConfig::GetCurrentDeviceResTag()
734 {
735     ResolutionType resolutionType = AceResConfig::GetResolutionType(SystemProperties::GetResolution());
736     AceResConfig deviceResConfig = AceResConfig(SystemProperties::GetMcc(), SystemProperties::GetMnc(),
737         SystemProperties::GetDeviceOrientation(), SystemProperties::GetColorMode(),
738         SystemProperties::GetParamDeviceType() == "tablet" ? DeviceType::TABLET : SystemProperties::GetDeviceType(),
739         resolutionType);
740     return AceResConfig::ConvertResConfigToTag(deviceResConfig, false);
741 }
742 
GetCurrentDeviceDeclarativeResTag()743 std::string AceResConfig::GetCurrentDeviceDeclarativeResTag()
744 {
745     auto localeTag = Localization::GetInstance()->GetLanguageTag();
746     std::string language, script, region;
747     Localization::ParseLocaleTag(localeTag, language, script, region, false);
748 
749     ResolutionType resolutionType = AceResConfig::GetResolutionType(SystemProperties::GetResolution());
750     LongScreenType longScreenType = AceResConfig::GetLongScreenType(SystemProperties::GetResolution());
751     AceResConfig deviceResConfig;
752 
753     deviceResConfig = AceResConfig(language, script, region, longScreenType, SystemProperties::GetScreenShape(),
754         SystemProperties::GetDeviceOrientation(), SystemProperties::GetColorMode(),
755         SystemProperties::GetParamDeviceType() == "tablet" ? DeviceType::TABLET : SystemProperties::GetDeviceType(),
756         resolutionType);
757 
758     return AceResConfig::ConvertDeclarativeResConfigToTag(deviceResConfig);
759 }
760 
GetTargetMediaScaleRatio(const std::string & targetResTag)761 double AceResConfig::GetTargetMediaScaleRatio(const std::string& targetResTag)
762 {
763     std::string deviceConfigTag = GetCurrentDeviceDeclarativeResTag();
764     auto deviceConfig = AceResConfig::ConvertDeclarativeResTagToConfig(deviceConfigTag);
765     ResolutionType deviceResolution = (deviceConfig.resolution_ != ResolutionType::RESOLUTION_NONE)
766                                           ? deviceConfig.resolution_
767                                           : ResolutionType::RESOLUTION_MDPI;
768 
769     ResolutionType targetResolution;
770     if (targetResTag == "default") {
771         targetResolution = ResolutionType::RESOLUTION_MDPI;
772     } else {
773         AceResConfig targetConfig = AceResConfig::ConvertDeclarativeResTagToConfig(targetResTag);
774         targetResolution = (targetConfig.resolution_ != ResolutionType::RESOLUTION_NONE)
775                                ? targetConfig.resolution_
776                                : ResolutionType::RESOLUTION_MDPI;
777     }
778 
779     return static_cast<double>(deviceResolution) / static_cast<double>(targetResolution);
780 }
781 
MatchAndSortI18nConfigs(const std::vector<std::string> & candidatesFiles,const std::string & devicesLocaleTag,std::vector<std::string> & fileList)782 void AceResConfig::MatchAndSortI18nConfigs(const std::vector<std::string>& candidatesFiles,
783     const std::string& devicesLocaleTag, std::vector<std::string>& fileList)
784 {
785     std::vector<AceResConfig> candidateLocaleConfigs;
786     for (auto& file : candidatesFiles) {
787         AceResConfig LocaleConfig = ConvertLocaleTagToConfig(file);
788         if (file == ConvertLocaleConfigToTag(LocaleConfig)) {
789             candidateLocaleConfigs.emplace_back(LocaleConfig);
790         }
791     }
792     AceResConfig deviceLocaleConfig = ConvertLocaleTagToConfig(devicesLocaleTag);
793     // Compute Script when it is not provided.
794     if (deviceLocaleConfig.script_.empty()) {
795         deviceLocaleConfig.script_ = ComputeScript(deviceLocaleConfig);
796     }
797     std::vector<AceResConfig> matchedLocaleConfigs;
798     MatchLocaleConfig(candidateLocaleConfigs, deviceLocaleConfig, matchedLocaleConfigs);
799     int32_t left = 0;
800     int32_t right = static_cast<int32_t>(matchedLocaleConfigs.size()) - 1;
801     SortLocaleConfigs(matchedLocaleConfigs, deviceLocaleConfig, left, right);
802     bool existDefault = false;
803     for (const auto& matchedLocaleConfig : matchedLocaleConfigs) {
804         std::string localeConfigTag = ConvertLocaleConfigToTag(matchedLocaleConfig);
805         if (localeConfigTag == "en-US") {
806             existDefault = true;
807         }
808         fileList.emplace_back(localeConfigTag);
809     }
810 
811     if (!existDefault) {
812         fileList.emplace_back("en-US");
813     }
814 }
815 
MatchAndSortResConfigs(const std::vector<std::string> & candidateFiles,const std::string & deviceResTag,std::vector<std::string> & matchedFileList,bool styleRes)816 void AceResConfig::MatchAndSortResConfigs(const std::vector<std::string>& candidateFiles,
817     const std::string& deviceResTag, std::vector<std::string>& matchedFileList, bool styleRes)
818 {
819     std::vector<AceResConfig> candidateResConfigs;
820     for (auto& file : candidateFiles) {
821         AceResConfig ResConfig = ConvertResTagToConfig(file, styleRes);
822         if (file == ConvertResConfigToTag(ResConfig, styleRes)) {
823             candidateResConfigs.emplace_back(ResConfig);
824         }
825     }
826 
827     AceResConfig deviceResConfig = ConvertResTagToConfig(deviceResTag, false);
828     int32_t candidateConfigSize = static_cast<int32_t>(candidateResConfigs.size());
829     std::vector<AceResConfig> matchedResConfigs;
830     for (auto i = 0; i < candidateConfigSize; i++) {
831         if (!MatchResConfig(deviceResConfig, candidateResConfigs[i])) {
832             continue;
833         } else {
834             matchedResConfigs.emplace_back(candidateResConfigs[i]);
835         }
836     }
837     int32_t left = 0;
838     int32_t right = static_cast<int32_t>(matchedResConfigs.size()) - 1;
839     SortResConfigs(deviceResConfig, matchedResConfigs, left, right);
840     for (const auto& matchedConfig : matchedResConfigs) {
841         matchedFileList.emplace_back(ConvertResConfigToTag(matchedConfig, styleRes));
842     }
843 
844     if (styleRes) {
845         matchedFileList.emplace_back("default");
846     } else {
847         matchedFileList.emplace_back("res-defaults");
848     }
849 }
850 
MatchAndSortStyleResConfigs(const std::vector<std::string> & candidateFiles,const std::string & deviceResTag,std::vector<std::string> & matchedFileList)851 void AceResConfig::MatchAndSortStyleResConfigs(const std::vector<std::string>& candidateFiles,
852     const std::string& deviceResTag, std::vector<std::string>& matchedFileList)
853 {
854     MatchAndSortResConfigs(candidateFiles, deviceResTag, matchedFileList, true);
855 }
856 
MatchAndSortDeclarativeResConfigs(const std::set<std::string> & candidateFolders,const std::string & deviceConfigTag,std::vector<std::string> & matchedFoldersList)857 void AceResConfig::MatchAndSortDeclarativeResConfigs(const std::set<std::string>& candidateFolders,
858     const std::string& deviceConfigTag, std::vector<std::string>& matchedFoldersList)
859 {
860     std::vector<AceResConfig> candidateResConfigs;
861     for (auto& folder : candidateFolders) {
862         if (folder == "default") {
863             continue;
864         }
865         AceResConfig resConfig = ConvertDeclarativeResTagToConfig(folder);
866         if (folder == ConvertDeclarativeResConfigToTag(resConfig)) {
867             candidateResConfigs.emplace_back(resConfig);
868         }
869     }
870 
871     AceResConfig deviceResConfig = ConvertDeclarativeResTagToConfig(deviceConfigTag);
872     // Compute Script when it is not provided.
873     if (deviceResConfig.script_.empty()) {
874         deviceResConfig.script_ = ComputeScript(deviceResConfig);
875     }
876 
877     std::vector<AceResConfig> matchedLocaleConfigs;
878     MatchLocaleConfig(candidateResConfigs, deviceResConfig, matchedLocaleConfigs, true);
879     int32_t candidateConfigSize = static_cast<int32_t>(matchedLocaleConfigs.size());
880     std::vector<AceResConfig> matchedResConfigs;
881     for (auto i = 0; i < candidateConfigSize; i++) {
882         if (!DeclarativeMatchResConfig(deviceResConfig, matchedLocaleConfigs[i])) {
883             continue;
884         } else {
885             matchedResConfigs.emplace_back(matchedLocaleConfigs[i]);
886         }
887     }
888 
889     int32_t left = 0;
890     int32_t right = static_cast<int32_t>(matchedResConfigs.size()) - 1;
891     SortDeclarativeResConfigs(deviceResConfig, matchedResConfigs, left, right);
892     for (const auto& matchedConfig : matchedResConfigs) {
893         matchedFoldersList.emplace_back(ConvertDeclarativeResConfigToTag(matchedConfig));
894     }
895 
896     matchedFoldersList.emplace_back("default");
897 }
898 
ParseConfig(const std::vector<KeyParam> & keyParams)899 bool AceResConfig::ParseConfig(const std::vector<KeyParam>& keyParams)
900 {
901     for (auto keyParam : keyParams) {
902         switch (keyParam.keyType) {
903             case KeyType::RESOLUTION:
904                 resolution_ = static_cast<ResolutionType>(keyParam.value);
905                 break;
906             case KeyType::ORIENTATION:
907                 orientation_ = static_cast<DeviceOrientation>(keyParam.value);
908                 break;
909             case KeyType::DEVICETYPE:
910                 deviceType_ = static_cast<DeviceType>(keyParam.value);
911                 break;
912             case KeyType::DECLARATIVE_COLOR_MODE:
913             case KeyType::COLOR_MODE:
914                 colorMode_ = static_cast<ColorMode>(keyParam.value);
915                 break;
916             case KeyType::MCC:
917                 mcc_ = keyParam.value;
918                 break;
919             case KeyType::MNC:
920                 mnc_ = keyParam.value;
921                 break;
922             case KeyType::MNC_SHORT_LEN:
923                 mnc_ = keyParam.value;
924                 mncShortLen_ = true;
925                 break;
926             case KeyType::SCREENSHAPE:
927                 screenShape_ = static_cast<ScreenShape>(keyParam.value);
928                 break;
929             case KeyType::LONGSCREEN:
930                 screenLong_ = static_cast<LongScreenType>(keyParam.value);
931                 break;
932             default:
933                 LOGE("unknown KeyType:%{public}d", keyParam.keyType);
934                 break;
935         }
936     }
937     return true;
938 }
939 
GetResolutionType(double resolution)940 ResolutionType AceResConfig::GetResolutionType(double resolution)
941 {
942     static const LinearEnumMapNode<ResolutionType, bool (*)(double)> resolutionMap[] = {
943         { ResolutionType::RESOLUTION_LDPI,
944             [](double resolution) { return GreatNotEqual(resolution, 0.0) && LessNotEqual(resolution, 0.875); } },
945         { ResolutionType::RESOLUTION_MDPI,
946             [](double resolution) { return GreatOrEqual(resolution, 0.875) && LessNotEqual(resolution, 1.25); } },
947         { ResolutionType::RESOLUTION_HDPI,
948             [](double resolution) { return GreatOrEqual(resolution, 1.25) && LessNotEqual(resolution, 1.75); } },
949         { ResolutionType::RESOLUTION_XHDPI,
950             [](double resolution) { return GreatOrEqual(resolution, 1.75) && LessNotEqual(resolution, 2.5); } },
951         { ResolutionType::RESOLUTION_XXHDPI,
952             [](double resolution) { return GreatOrEqual(resolution, 2.5) && LessNotEqual(resolution, 3.5); } },
953         { ResolutionType::RESOLUTION_XXXHDPI, [](double resolution) { return GreatOrEqual(resolution, 3.5); } },
954     };
955 
956     for (const auto& idx : resolutionMap) {
957         if (idx.value(resolution)) {
958             return idx.key;
959         }
960     }
961     return ResolutionType::RESOLUTION_MDPI;
962 }
963 
GetLongScreenType(double resolution)964 LongScreenType AceResConfig::GetLongScreenType(double resolution)
965 {
966     if (GreatNotEqual(resolution, 1.5)) {
967         return LongScreenType::LONG;
968     } else if (GreatNotEqual(resolution, 0.0) && LessOrEqual(resolution, 1.5)) {
969         return LongScreenType::NOT_LONG;
970     }
971 
972     return LongScreenType::NOT_LONG;
973 }
974 
ConvertResTagToConfig(const std::string & deviceResConfigTag,bool styleRes)975 AceResConfig AceResConfig::ConvertResTagToConfig(const std::string& deviceResConfigTag, bool styleRes)
976 {
977     AceResConfig resConfig;
978     std::vector<KeyParam> keyParams;
979     bool parseSucceed = AceResKeyParser::GetInstance().Parse(deviceResConfigTag, keyParams, styleRes);
980     if (parseSucceed) {
981         resConfig.ParseConfig(keyParams);
982     }
983     return resConfig;
984 }
985 
ConvertDeclarativeResTagToConfig(const std::string & deviceResConfigTag)986 AceResConfig AceResConfig::ConvertDeclarativeResTagToConfig(const std::string& deviceResConfigTag)
987 {
988     AceResConfig resConfig;
989     std::vector<KeyParam> keyParams;
990     if (deviceResConfigTag.find_first_of("-") == std::string::npos) {
991         if (deviceResConfigTag.find_first_of("_") == std::string::npos) {
992             bool parseSucceed = AceResKeyParser::GetInstance().DeclarativeParse(deviceResConfigTag, keyParams);
993             if (parseSucceed) {
994                 resConfig = AceResConfig("", "", "");
995                 resConfig.ParseConfig(keyParams);
996                 return resConfig;
997             }
998         }
999 
1000         std::string tempResTag(deviceResConfigTag);
1001         std::replace(tempResTag.begin(), tempResTag.end(), '_', '-');
1002         std::string language, script, region;
1003         Localization::ParseLocaleTag(tempResTag, language, script, region, false);
1004         resConfig = AceResConfig(language, script, region);
1005 
1006         return resConfig;
1007     }
1008 
1009     resConfig = AceResConfig("", "", "");
1010     bool parseSucceed = AceResKeyParser::GetInstance().DeclarativeParse(deviceResConfigTag, keyParams);
1011     if (parseSucceed) {
1012         resConfig.ParseConfig(keyParams);
1013         return resConfig;
1014     }
1015 
1016     std::string localeTag = deviceResConfigTag.substr(0, deviceResConfigTag.find_first_of("-"));
1017     std::string resConfigTag = deviceResConfigTag.substr(deviceResConfigTag.find_first_of("-"));
1018     std::replace(localeTag.begin(), localeTag.end(), '_', '-');
1019 
1020     std::string language, script, region;
1021     Localization::ParseLocaleTag(localeTag, language, script, region, false);
1022     resConfig = AceResConfig(language, script, region);
1023 
1024     parseSucceed = AceResKeyParser::GetInstance().DeclarativeParse(resConfigTag, keyParams);
1025     if (parseSucceed) {
1026         resConfig.ParseConfig(keyParams);
1027     }
1028 
1029     return resConfig;
1030 }
1031 
ConvertResConfigToTag(const AceResConfig & resConfig,bool styleRes)1032 std::string AceResConfig::ConvertResConfigToTag(const AceResConfig& resConfig, bool styleRes)
1033 {
1034     std::string resTag;
1035     if (!styleRes) {
1036         resTag = "res";
1037     }
1038     if (resConfig.mcc_ != MCC_UNDEFINED && resConfig.mnc_ != MNC_UNDEFINED) {
1039         GetConfigString(KeyType::MCC, resConfig.mcc_, resTag);
1040         if (resConfig.mncShortLen_) {
1041             GetConfigString(KeyType::MNC_SHORT_LEN, resConfig.mnc_, resTag);
1042         } else {
1043             GetConfigString(KeyType::MNC, resConfig.mnc_, resTag);
1044         }
1045     }
1046 
1047     if (resConfig.orientation_ != DeviceOrientation::ORIENTATION_UNDEFINED) {
1048         GetConfigString(KeyType::ORIENTATION, static_cast<int32_t>(resConfig.orientation_), resTag);
1049     }
1050 
1051     if (resConfig.colorMode_ != ColorMode::COLOR_MODE_UNDEFINED) {
1052         GetConfigString(KeyType::COLOR_MODE, static_cast<int32_t>(resConfig.colorMode_), resTag);
1053     }
1054 
1055     if (resConfig.deviceType_ != DeviceType::UNKNOWN) {
1056         GetConfigString(KeyType::DEVICETYPE, static_cast<int32_t>(resConfig.deviceType_), resTag);
1057     }
1058 
1059     if (resConfig.resolution_ != ResolutionType::RESOLUTION_NONE) {
1060         GetConfigString(KeyType::RESOLUTION, static_cast<int32_t>(resConfig.resolution_), resTag);
1061     }
1062     return resTag;
1063 }
1064 
ConvertDeclarativeResConfigToTag(const AceResConfig & resConfig)1065 std::string AceResConfig::ConvertDeclarativeResConfigToTag(const AceResConfig& resConfig)
1066 {
1067     std::string resTag = resConfig.language_;
1068     if (!resConfig.script_.empty()) {
1069         resTag += ('_' + resConfig.script_);
1070     }
1071     if (!resConfig.region_.empty()) {
1072         resTag += ('_' + resConfig.region_);
1073     }
1074 
1075     if (resConfig.screenLong_ != LongScreenType::LONG_SCREEN_UNDEFINED) {
1076         GetConfigString(KeyType::LONGSCREEN, static_cast<int32_t>(resConfig.screenLong_), resTag);
1077     }
1078 
1079     if (resConfig.screenShape_ != ScreenShape::SCREEN_SHAPE_UNDEFINED) {
1080         GetConfigString(KeyType::SCREENSHAPE, static_cast<int32_t>(resConfig.screenShape_), resTag);
1081     }
1082 
1083     if (resConfig.orientation_ != DeviceOrientation::ORIENTATION_UNDEFINED) {
1084         GetConfigString(KeyType::ORIENTATION, static_cast<int32_t>(resConfig.orientation_), resTag);
1085     }
1086 
1087     if (resConfig.colorMode_ != ColorMode::COLOR_MODE_UNDEFINED) {
1088         GetConfigString(KeyType::DECLARATIVE_COLOR_MODE, static_cast<int32_t>(resConfig.colorMode_), resTag);
1089     }
1090 
1091     if (resConfig.deviceType_ != DeviceType::UNKNOWN) {
1092         GetConfigString(KeyType::DEVICETYPE, static_cast<int32_t>(resConfig.deviceType_), resTag);
1093     }
1094 
1095     if (resConfig.resolution_ != ResolutionType::RESOLUTION_NONE) {
1096         GetConfigString(KeyType::RESOLUTION, static_cast<int32_t>(resConfig.resolution_), resTag);
1097     }
1098     return resTag;
1099 }
1100 
1101 } // namespace OHOS::Ace