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