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