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