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