blob: 1f3a89edb8afab02d582e704ca38b796efde83ca [file] [log] [blame]
Adam Lesinski6f6ceb72014-11-14 14:48:12 -08001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Mårten Kongstad24c9aa62018-06-20 08:46:41 +020017#include "androidfw/ConfigDescription.h"
18#include "androidfw/Locale.h"
19#include "androidfw/ResourceTypes.h"
20#include "androidfw/StringPiece.h"
21#include "androidfw/Util.h"
Adam Lesinskice5e56e2016-10-21 17:56:45 -070022
23#include <string>
24#include <vector>
25
Mårten Kongstad24c9aa62018-06-20 08:46:41 +020026namespace android {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080027
28static const char* kWildcardName = "any";
29
Adam Lesinskice5e56e2016-10-21 17:56:45 -070030const ConfigDescription& ConfigDescription::DefaultConfig() {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070031 static ConfigDescription config = {};
32 return config;
Adam Lesinski52364f72016-01-11 13:10:24 -080033}
34
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080035static bool parseMcc(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070036 if (strcmp(name, kWildcardName) == 0) {
37 if (out) out->mcc = 0;
38 return true;
39 }
40 const char* c = name;
41 if (tolower(*c) != 'm') return false;
42 c++;
43 if (tolower(*c) != 'c') return false;
44 c++;
45 if (tolower(*c) != 'c') return false;
46 c++;
47
48 const char* val = c;
49
50 while (*c >= '0' && *c <= '9') {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080051 c++;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070052 }
53 if (*c != 0) return false;
54 if (c - val != 3) return false;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080055
Adam Lesinskicacb28f2016-10-19 12:18:14 -070056 int d = atoi(val);
57 if (d != 0) {
58 if (out) out->mcc = d;
59 return true;
60 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080061
Adam Lesinskicacb28f2016-10-19 12:18:14 -070062 return false;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080063}
64
65static bool parseMnc(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070066 if (strcmp(name, kWildcardName) == 0) {
Adam Lesinski13c0c742017-08-07 10:32:18 -070067 if (out) out->mnc = 0;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080068 return true;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070069 }
70 const char* c = name;
71 if (tolower(*c) != 'm') return false;
72 c++;
73 if (tolower(*c) != 'n') return false;
74 c++;
75 if (tolower(*c) != 'c') return false;
76 c++;
77
78 const char* val = c;
79
80 while (*c >= '0' && *c <= '9') {
81 c++;
82 }
83 if (*c != 0) return false;
84 if (c - val == 0 || c - val > 3) return false;
85
86 if (out) {
87 out->mnc = atoi(val);
88 if (out->mnc == 0) {
89 out->mnc = ACONFIGURATION_MNC_ZERO;
90 }
91 }
92
93 return true;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080094}
95
96static bool parseLayoutDirection(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070097 if (strcmp(name, kWildcardName) == 0) {
98 if (out)
99 out->screenLayout =
100 (out->screenLayout & ~ResTable_config::MASK_LAYOUTDIR) |
101 ResTable_config::LAYOUTDIR_ANY;
102 return true;
103 } else if (strcmp(name, "ldltr") == 0) {
104 if (out)
105 out->screenLayout =
106 (out->screenLayout & ~ResTable_config::MASK_LAYOUTDIR) |
107 ResTable_config::LAYOUTDIR_LTR;
108 return true;
109 } else if (strcmp(name, "ldrtl") == 0) {
110 if (out)
111 out->screenLayout =
112 (out->screenLayout & ~ResTable_config::MASK_LAYOUTDIR) |
113 ResTable_config::LAYOUTDIR_RTL;
114 return true;
115 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800116
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700117 return false;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800118}
119
120static bool parseScreenLayoutSize(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700121 if (strcmp(name, kWildcardName) == 0) {
122 if (out)
123 out->screenLayout =
124 (out->screenLayout & ~ResTable_config::MASK_SCREENSIZE) |
125 ResTable_config::SCREENSIZE_ANY;
126 return true;
127 } else if (strcmp(name, "small") == 0) {
128 if (out)
129 out->screenLayout =
130 (out->screenLayout & ~ResTable_config::MASK_SCREENSIZE) |
131 ResTable_config::SCREENSIZE_SMALL;
132 return true;
133 } else if (strcmp(name, "normal") == 0) {
134 if (out)
135 out->screenLayout =
136 (out->screenLayout & ~ResTable_config::MASK_SCREENSIZE) |
137 ResTable_config::SCREENSIZE_NORMAL;
138 return true;
139 } else if (strcmp(name, "large") == 0) {
140 if (out)
141 out->screenLayout =
142 (out->screenLayout & ~ResTable_config::MASK_SCREENSIZE) |
143 ResTable_config::SCREENSIZE_LARGE;
144 return true;
145 } else if (strcmp(name, "xlarge") == 0) {
146 if (out)
147 out->screenLayout =
148 (out->screenLayout & ~ResTable_config::MASK_SCREENSIZE) |
149 ResTable_config::SCREENSIZE_XLARGE;
150 return true;
151 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800152
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700153 return false;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800154}
155
156static bool parseScreenLayoutLong(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700157 if (strcmp(name, kWildcardName) == 0) {
158 if (out)
159 out->screenLayout =
160 (out->screenLayout & ~ResTable_config::MASK_SCREENLONG) |
161 ResTable_config::SCREENLONG_ANY;
162 return true;
163 } else if (strcmp(name, "long") == 0) {
164 if (out)
165 out->screenLayout =
166 (out->screenLayout & ~ResTable_config::MASK_SCREENLONG) |
167 ResTable_config::SCREENLONG_YES;
168 return true;
169 } else if (strcmp(name, "notlong") == 0) {
170 if (out)
171 out->screenLayout =
172 (out->screenLayout & ~ResTable_config::MASK_SCREENLONG) |
173 ResTable_config::SCREENLONG_NO;
174 return true;
175 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800176
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700177 return false;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800178}
179
Adam Lesinski64254972015-11-03 16:16:17 -0800180static bool parseScreenRound(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700181 if (strcmp(name, kWildcardName) == 0) {
182 if (out)
183 out->screenLayout2 =
184 (out->screenLayout2 & ~ResTable_config::MASK_SCREENROUND) |
185 ResTable_config::SCREENROUND_ANY;
186 return true;
187 } else if (strcmp(name, "round") == 0) {
188 if (out)
189 out->screenLayout2 =
190 (out->screenLayout2 & ~ResTable_config::MASK_SCREENROUND) |
191 ResTable_config::SCREENROUND_YES;
192 return true;
193 } else if (strcmp(name, "notround") == 0) {
194 if (out)
195 out->screenLayout2 =
196 (out->screenLayout2 & ~ResTable_config::MASK_SCREENROUND) |
197 ResTable_config::SCREENROUND_NO;
198 return true;
199 }
200 return false;
Adam Lesinski64254972015-11-03 16:16:17 -0800201}
202
Romain Guyc9ba5592017-01-18 16:34:42 -0800203static bool parseWideColorGamut(const char* name, ResTable_config* out) {
204 if (strcmp(name, kWildcardName) == 0) {
205 if (out)
Romain Guy48327452017-01-23 17:03:35 -0800206 out->colorMode =
207 (out->colorMode & ~ResTable_config::MASK_WIDE_COLOR_GAMUT) |
Romain Guyc9ba5592017-01-18 16:34:42 -0800208 ResTable_config::WIDE_COLOR_GAMUT_ANY;
209 return true;
210 } else if (strcmp(name, "widecg") == 0) {
211 if (out)
Romain Guy48327452017-01-23 17:03:35 -0800212 out->colorMode =
213 (out->colorMode & ~ResTable_config::MASK_WIDE_COLOR_GAMUT) |
Romain Guyc9ba5592017-01-18 16:34:42 -0800214 ResTable_config::WIDE_COLOR_GAMUT_YES;
215 return true;
216 } else if (strcmp(name, "nowidecg") == 0) {
217 if (out)
Romain Guy48327452017-01-23 17:03:35 -0800218 out->colorMode =
219 (out->colorMode & ~ResTable_config::MASK_WIDE_COLOR_GAMUT) |
Romain Guyc9ba5592017-01-18 16:34:42 -0800220 ResTable_config::WIDE_COLOR_GAMUT_NO;
221 return true;
222 }
223 return false;
224}
225
226static bool parseHdr(const char* name, ResTable_config* out) {
227 if (strcmp(name, kWildcardName) == 0) {
228 if (out)
Romain Guy48327452017-01-23 17:03:35 -0800229 out->colorMode =
230 (out->colorMode & ~ResTable_config::MASK_HDR) |
Romain Guyc9ba5592017-01-18 16:34:42 -0800231 ResTable_config::HDR_ANY;
232 return true;
233 } else if (strcmp(name, "highdr") == 0) {
234 if (out)
Romain Guy48327452017-01-23 17:03:35 -0800235 out->colorMode =
236 (out->colorMode & ~ResTable_config::MASK_HDR) |
Romain Guyc9ba5592017-01-18 16:34:42 -0800237 ResTable_config::HDR_YES;
238 return true;
239 } else if (strcmp(name, "lowdr") == 0) {
240 if (out)
Romain Guy48327452017-01-23 17:03:35 -0800241 out->colorMode =
242 (out->colorMode & ~ResTable_config::MASK_HDR) |
Romain Guyc9ba5592017-01-18 16:34:42 -0800243 ResTable_config::HDR_NO;
244 return true;
245 }
246 return false;
247}
248
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800249static bool parseOrientation(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700250 if (strcmp(name, kWildcardName) == 0) {
251 if (out) out->orientation = out->ORIENTATION_ANY;
252 return true;
253 } else if (strcmp(name, "port") == 0) {
254 if (out) out->orientation = out->ORIENTATION_PORT;
255 return true;
256 } else if (strcmp(name, "land") == 0) {
257 if (out) out->orientation = out->ORIENTATION_LAND;
258 return true;
259 } else if (strcmp(name, "square") == 0) {
260 if (out) out->orientation = out->ORIENTATION_SQUARE;
261 return true;
262 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800263
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700264 return false;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800265}
266
267static bool parseUiModeType(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700268 if (strcmp(name, kWildcardName) == 0) {
269 if (out)
270 out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_TYPE) |
271 ResTable_config::UI_MODE_TYPE_ANY;
272 return true;
273 } else if (strcmp(name, "desk") == 0) {
274 if (out)
275 out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_TYPE) |
276 ResTable_config::UI_MODE_TYPE_DESK;
277 return true;
278 } else if (strcmp(name, "car") == 0) {
279 if (out)
280 out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_TYPE) |
281 ResTable_config::UI_MODE_TYPE_CAR;
282 return true;
283 } else if (strcmp(name, "television") == 0) {
284 if (out)
285 out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_TYPE) |
286 ResTable_config::UI_MODE_TYPE_TELEVISION;
287 return true;
288 } else if (strcmp(name, "appliance") == 0) {
289 if (out)
290 out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_TYPE) |
291 ResTable_config::UI_MODE_TYPE_APPLIANCE;
292 return true;
293 } else if (strcmp(name, "watch") == 0) {
294 if (out)
295 out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_TYPE) |
296 ResTable_config::UI_MODE_TYPE_WATCH;
297 return true;
Zak Cohen1a6acdb2016-12-12 15:21:21 -0800298 } else if (strcmp(name, "vrheadset") == 0) {
299 if (out)
300 out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_TYPE) |
301 ResTable_config::UI_MODE_TYPE_VR_HEADSET;
302 return true;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700303 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800304
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700305 return false;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800306}
307
308static bool parseUiModeNight(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700309 if (strcmp(name, kWildcardName) == 0) {
310 if (out)
311 out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_NIGHT) |
312 ResTable_config::UI_MODE_NIGHT_ANY;
313 return true;
314 } else if (strcmp(name, "night") == 0) {
315 if (out)
316 out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_NIGHT) |
317 ResTable_config::UI_MODE_NIGHT_YES;
318 return true;
319 } else if (strcmp(name, "notnight") == 0) {
320 if (out)
321 out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_NIGHT) |
322 ResTable_config::UI_MODE_NIGHT_NO;
323 return true;
324 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800325
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700326 return false;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800327}
328
329static bool parseDensity(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700330 if (strcmp(name, kWildcardName) == 0) {
331 if (out) out->density = ResTable_config::DENSITY_DEFAULT;
332 return true;
333 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800334
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700335 if (strcmp(name, "anydpi") == 0) {
336 if (out) out->density = ResTable_config::DENSITY_ANY;
337 return true;
338 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800339
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700340 if (strcmp(name, "nodpi") == 0) {
341 if (out) out->density = ResTable_config::DENSITY_NONE;
342 return true;
343 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800344
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700345 if (strcmp(name, "ldpi") == 0) {
346 if (out) out->density = ResTable_config::DENSITY_LOW;
347 return true;
348 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800349
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700350 if (strcmp(name, "mdpi") == 0) {
351 if (out) out->density = ResTable_config::DENSITY_MEDIUM;
352 return true;
353 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800354
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700355 if (strcmp(name, "tvdpi") == 0) {
356 if (out) out->density = ResTable_config::DENSITY_TV;
357 return true;
358 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800359
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700360 if (strcmp(name, "hdpi") == 0) {
361 if (out) out->density = ResTable_config::DENSITY_HIGH;
362 return true;
363 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800364
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700365 if (strcmp(name, "xhdpi") == 0) {
366 if (out) out->density = ResTable_config::DENSITY_XHIGH;
367 return true;
368 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800369
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700370 if (strcmp(name, "xxhdpi") == 0) {
371 if (out) out->density = ResTable_config::DENSITY_XXHIGH;
372 return true;
373 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800374
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700375 if (strcmp(name, "xxxhdpi") == 0) {
376 if (out) out->density = ResTable_config::DENSITY_XXXHIGH;
377 return true;
378 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800379
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700380 char* c = (char*)name;
381 while (*c >= '0' && *c <= '9') {
382 c++;
383 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800384
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700385 // check that we have 'dpi' after the last digit.
386 if (toupper(c[0]) != 'D' || toupper(c[1]) != 'P' || toupper(c[2]) != 'I' ||
387 c[3] != 0) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800388 return false;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700389 }
390
391 // temporarily replace the first letter with \0 to
392 // use atoi.
393 char tmp = c[0];
394 c[0] = '\0';
395
396 int d = atoi(name);
397 c[0] = tmp;
398
399 if (d != 0) {
400 if (out) out->density = d;
401 return true;
402 }
403
404 return false;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800405}
406
407static bool parseTouchscreen(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700408 if (strcmp(name, kWildcardName) == 0) {
409 if (out) out->touchscreen = out->TOUCHSCREEN_ANY;
410 return true;
411 } else if (strcmp(name, "notouch") == 0) {
412 if (out) out->touchscreen = out->TOUCHSCREEN_NOTOUCH;
413 return true;
414 } else if (strcmp(name, "stylus") == 0) {
415 if (out) out->touchscreen = out->TOUCHSCREEN_STYLUS;
416 return true;
417 } else if (strcmp(name, "finger") == 0) {
418 if (out) out->touchscreen = out->TOUCHSCREEN_FINGER;
419 return true;
420 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800421
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700422 return false;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800423}
424
425static bool parseKeysHidden(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700426 uint8_t mask = 0;
427 uint8_t value = 0;
428 if (strcmp(name, kWildcardName) == 0) {
429 mask = ResTable_config::MASK_KEYSHIDDEN;
430 value = ResTable_config::KEYSHIDDEN_ANY;
431 } else if (strcmp(name, "keysexposed") == 0) {
432 mask = ResTable_config::MASK_KEYSHIDDEN;
433 value = ResTable_config::KEYSHIDDEN_NO;
434 } else if (strcmp(name, "keyshidden") == 0) {
435 mask = ResTable_config::MASK_KEYSHIDDEN;
436 value = ResTable_config::KEYSHIDDEN_YES;
437 } else if (strcmp(name, "keyssoft") == 0) {
438 mask = ResTable_config::MASK_KEYSHIDDEN;
439 value = ResTable_config::KEYSHIDDEN_SOFT;
440 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800441
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700442 if (mask != 0) {
443 if (out) out->inputFlags = (out->inputFlags & ~mask) | value;
444 return true;
445 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800446
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700447 return false;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800448}
449
450static bool parseKeyboard(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700451 if (strcmp(name, kWildcardName) == 0) {
452 if (out) out->keyboard = out->KEYBOARD_ANY;
453 return true;
454 } else if (strcmp(name, "nokeys") == 0) {
455 if (out) out->keyboard = out->KEYBOARD_NOKEYS;
456 return true;
457 } else if (strcmp(name, "qwerty") == 0) {
458 if (out) out->keyboard = out->KEYBOARD_QWERTY;
459 return true;
460 } else if (strcmp(name, "12key") == 0) {
461 if (out) out->keyboard = out->KEYBOARD_12KEY;
462 return true;
463 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800464
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700465 return false;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800466}
467
468static bool parseNavHidden(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700469 uint8_t mask = 0;
470 uint8_t value = 0;
471 if (strcmp(name, kWildcardName) == 0) {
472 mask = ResTable_config::MASK_NAVHIDDEN;
473 value = ResTable_config::NAVHIDDEN_ANY;
474 } else if (strcmp(name, "navexposed") == 0) {
475 mask = ResTable_config::MASK_NAVHIDDEN;
476 value = ResTable_config::NAVHIDDEN_NO;
477 } else if (strcmp(name, "navhidden") == 0) {
478 mask = ResTable_config::MASK_NAVHIDDEN;
479 value = ResTable_config::NAVHIDDEN_YES;
480 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800481
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700482 if (mask != 0) {
483 if (out) out->inputFlags = (out->inputFlags & ~mask) | value;
484 return true;
485 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800486
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700487 return false;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800488}
489
490static bool parseNavigation(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700491 if (strcmp(name, kWildcardName) == 0) {
492 if (out) out->navigation = out->NAVIGATION_ANY;
493 return true;
494 } else if (strcmp(name, "nonav") == 0) {
495 if (out) out->navigation = out->NAVIGATION_NONAV;
496 return true;
497 } else if (strcmp(name, "dpad") == 0) {
498 if (out) out->navigation = out->NAVIGATION_DPAD;
499 return true;
500 } else if (strcmp(name, "trackball") == 0) {
501 if (out) out->navigation = out->NAVIGATION_TRACKBALL;
502 return true;
503 } else if (strcmp(name, "wheel") == 0) {
504 if (out) out->navigation = out->NAVIGATION_WHEEL;
505 return true;
506 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800507
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700508 return false;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800509}
510
511static bool parseScreenSize(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700512 if (strcmp(name, kWildcardName) == 0) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800513 if (out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700514 out->screenWidth = out->SCREENWIDTH_ANY;
515 out->screenHeight = out->SCREENHEIGHT_ANY;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800516 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800517 return true;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700518 }
519
520 const char* x = name;
521 while (*x >= '0' && *x <= '9') x++;
522 if (x == name || *x != 'x') return false;
523 std::string xName(name, x - name);
524 x++;
525
526 const char* y = x;
527 while (*y >= '0' && *y <= '9') y++;
528 if (y == name || *y != 0) return false;
529 std::string yName(x, y - x);
530
531 uint16_t w = (uint16_t)atoi(xName.c_str());
532 uint16_t h = (uint16_t)atoi(yName.c_str());
533 if (w < h) {
534 return false;
535 }
536
537 if (out) {
538 out->screenWidth = w;
539 out->screenHeight = h;
540 }
541
542 return true;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800543}
544
545static bool parseSmallestScreenWidthDp(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700546 if (strcmp(name, kWildcardName) == 0) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800547 if (out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700548 out->smallestScreenWidthDp = out->SCREENWIDTH_ANY;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800549 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800550 return true;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700551 }
552
553 if (*name != 's') return false;
554 name++;
555 if (*name != 'w') return false;
556 name++;
557 const char* x = name;
558 while (*x >= '0' && *x <= '9') x++;
559 if (x == name || x[0] != 'd' || x[1] != 'p' || x[2] != 0) return false;
560 std::string xName(name, x - name);
561
562 if (out) {
563 out->smallestScreenWidthDp = (uint16_t)atoi(xName.c_str());
564 }
565
566 return true;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800567}
568
569static bool parseScreenWidthDp(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700570 if (strcmp(name, kWildcardName) == 0) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800571 if (out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700572 out->screenWidthDp = out->SCREENWIDTH_ANY;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800573 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800574 return true;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700575 }
576
577 if (*name != 'w') return false;
578 name++;
579 const char* x = name;
580 while (*x >= '0' && *x <= '9') x++;
581 if (x == name || x[0] != 'd' || x[1] != 'p' || x[2] != 0) return false;
582 std::string xName(name, x - name);
583
584 if (out) {
585 out->screenWidthDp = (uint16_t)atoi(xName.c_str());
586 }
587
588 return true;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800589}
590
591static bool parseScreenHeightDp(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700592 if (strcmp(name, kWildcardName) == 0) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800593 if (out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700594 out->screenHeightDp = out->SCREENWIDTH_ANY;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800595 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800596 return true;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700597 }
598
599 if (*name != 'h') return false;
600 name++;
601 const char* x = name;
602 while (*x >= '0' && *x <= '9') x++;
603 if (x == name || x[0] != 'd' || x[1] != 'p' || x[2] != 0) return false;
604 std::string xName(name, x - name);
605
606 if (out) {
607 out->screenHeightDp = (uint16_t)atoi(xName.c_str());
608 }
609
610 return true;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800611}
612
613static bool parseVersion(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700614 if (strcmp(name, kWildcardName) == 0) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800615 if (out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700616 out->sdkVersion = out->SDKVERSION_ANY;
617 out->minorVersion = out->MINORVERSION_ANY;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800618 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800619 return true;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700620 }
621
622 if (*name != 'v') {
623 return false;
624 }
625
626 name++;
627 const char* s = name;
628 while (*s >= '0' && *s <= '9') s++;
629 if (s == name || *s != 0) return false;
630 std::string sdkName(name, s - name);
631
632 if (out) {
633 out->sdkVersion = (uint16_t)atoi(sdkName.c_str());
634 out->minorVersion = 0;
635 }
636
637 return true;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800638}
639
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700640bool ConfigDescription::Parse(const StringPiece& str, ConfigDescription* out) {
641 std::vector<std::string> parts = util::SplitAndLowercase(str, '-');
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800642
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700643 ConfigDescription config;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700644 ssize_t parts_consumed = 0;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700645 LocaleValue locale;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800646
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700647 const auto parts_end = parts.end();
648 auto part_iter = parts.begin();
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800649
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700650 if (str.size() == 0) {
651 goto success;
652 }
653
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700654 if (parseMcc(part_iter->c_str(), &config)) {
655 ++part_iter;
656 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700657 goto success;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800658 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700659 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800660
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700661 if (parseMnc(part_iter->c_str(), &config)) {
662 ++part_iter;
663 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700664 goto success;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800665 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700666 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800667
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700668 // Locale spans a few '-' separators, so we let it
669 // control the index.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700670 parts_consumed = locale.InitFromParts(part_iter, parts_end);
671 if (parts_consumed < 0) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800672 return false;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700673 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700674 locale.WriteTo(&config);
675 part_iter += parts_consumed;
676 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700677 goto success;
678 }
679 }
680
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700681 if (parseLayoutDirection(part_iter->c_str(), &config)) {
682 ++part_iter;
683 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700684 goto success;
685 }
686 }
687
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700688 if (parseSmallestScreenWidthDp(part_iter->c_str(), &config)) {
689 ++part_iter;
690 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700691 goto success;
692 }
693 }
694
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700695 if (parseScreenWidthDp(part_iter->c_str(), &config)) {
696 ++part_iter;
697 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700698 goto success;
699 }
700 }
701
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700702 if (parseScreenHeightDp(part_iter->c_str(), &config)) {
703 ++part_iter;
704 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700705 goto success;
706 }
707 }
708
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700709 if (parseScreenLayoutSize(part_iter->c_str(), &config)) {
710 ++part_iter;
711 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700712 goto success;
713 }
714 }
715
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700716 if (parseScreenLayoutLong(part_iter->c_str(), &config)) {
717 ++part_iter;
718 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700719 goto success;
720 }
721 }
722
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700723 if (parseScreenRound(part_iter->c_str(), &config)) {
724 ++part_iter;
725 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700726 goto success;
727 }
728 }
729
Romain Guyc9ba5592017-01-18 16:34:42 -0800730 if (parseWideColorGamut(part_iter->c_str(), &config)) {
731 ++part_iter;
732 if (part_iter == parts_end) {
733 goto success;
734 }
735 }
736
737 if (parseHdr(part_iter->c_str(), &config)) {
738 ++part_iter;
739 if (part_iter == parts_end) {
740 goto success;
741 }
742 }
743
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700744 if (parseOrientation(part_iter->c_str(), &config)) {
745 ++part_iter;
746 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700747 goto success;
748 }
749 }
750
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700751 if (parseUiModeType(part_iter->c_str(), &config)) {
752 ++part_iter;
753 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700754 goto success;
755 }
756 }
757
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700758 if (parseUiModeNight(part_iter->c_str(), &config)) {
759 ++part_iter;
760 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700761 goto success;
762 }
763 }
764
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700765 if (parseDensity(part_iter->c_str(), &config)) {
766 ++part_iter;
767 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700768 goto success;
769 }
770 }
771
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700772 if (parseTouchscreen(part_iter->c_str(), &config)) {
773 ++part_iter;
774 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700775 goto success;
776 }
777 }
778
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700779 if (parseKeysHidden(part_iter->c_str(), &config)) {
780 ++part_iter;
781 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700782 goto success;
783 }
784 }
785
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700786 if (parseKeyboard(part_iter->c_str(), &config)) {
787 ++part_iter;
788 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700789 goto success;
790 }
791 }
792
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700793 if (parseNavHidden(part_iter->c_str(), &config)) {
794 ++part_iter;
795 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700796 goto success;
797 }
798 }
799
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700800 if (parseNavigation(part_iter->c_str(), &config)) {
801 ++part_iter;
802 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700803 goto success;
804 }
805 }
806
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700807 if (parseScreenSize(part_iter->c_str(), &config)) {
808 ++part_iter;
809 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700810 goto success;
811 }
812 }
813
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700814 if (parseVersion(part_iter->c_str(), &config)) {
815 ++part_iter;
816 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700817 goto success;
818 }
819 }
820
821 // Unrecognized.
822 return false;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800823
824success:
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700825 if (out != NULL) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700826 ApplyVersionForCompatibility(&config);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700827 *out = config;
828 }
829 return true;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800830}
831
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700832void ConfigDescription::ApplyVersionForCompatibility(
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700833 ConfigDescription* config) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700834 uint16_t min_sdk = 0;
Zak Cohen1a6acdb2016-12-12 15:21:21 -0800835 if ((config->uiMode & ResTable_config::MASK_UI_MODE_TYPE)
Romain Guyc9ba5592017-01-18 16:34:42 -0800836 == ResTable_config::UI_MODE_TYPE_VR_HEADSET ||
Romain Guy48327452017-01-23 17:03:35 -0800837 config->colorMode & ResTable_config::MASK_WIDE_COLOR_GAMUT ||
838 config->colorMode & ResTable_config::MASK_HDR) {
Zak Cohen1a6acdb2016-12-12 15:21:21 -0800839 min_sdk = SDK_O;
840 } else if (config->screenLayout2 & ResTable_config::MASK_SCREENROUND) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700841 min_sdk = SDK_MARSHMALLOW;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700842 } else if (config->density == ResTable_config::DENSITY_ANY) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700843 min_sdk = SDK_LOLLIPOP;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700844 } else if (config->smallestScreenWidthDp !=
845 ResTable_config::SCREENWIDTH_ANY ||
846 config->screenWidthDp != ResTable_config::SCREENWIDTH_ANY ||
847 config->screenHeightDp != ResTable_config::SCREENHEIGHT_ANY) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700848 min_sdk = SDK_HONEYCOMB_MR2;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700849 } else if ((config->uiMode & ResTable_config::MASK_UI_MODE_TYPE) !=
850 ResTable_config::UI_MODE_TYPE_ANY ||
851 (config->uiMode & ResTable_config::MASK_UI_MODE_NIGHT) !=
852 ResTable_config::UI_MODE_NIGHT_ANY) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700853 min_sdk = SDK_FROYO;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700854 } else if ((config->screenLayout & ResTable_config::MASK_SCREENSIZE) !=
855 ResTable_config::SCREENSIZE_ANY ||
856 (config->screenLayout & ResTable_config::MASK_SCREENLONG) !=
857 ResTable_config::SCREENLONG_ANY ||
858 config->density != ResTable_config::DENSITY_DEFAULT) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700859 min_sdk = SDK_DONUT;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700860 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800861
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700862 if (min_sdk > config->sdkVersion) {
863 config->sdkVersion = min_sdk;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700864 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800865}
866
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700867ConfigDescription ConfigDescription::CopyWithoutSdkVersion() const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700868 ConfigDescription copy = *this;
869 copy.sdkVersion = 0;
870 return copy;
Adam Lesinski87675ad2016-07-15 17:03:03 -0700871}
872
Adam Lesinskib58c3ef2017-09-12 17:39:52 -0700873std::string ConfigDescription::GetBcp47LanguageTag(bool canonicalize) const {
874 char locale[RESTABLE_MAX_LOCALE_LEN];
875 getBcp47Locale(locale, canonicalize);
876 return std::string(locale);
877}
878
Adam Lesinski93190b72017-11-03 15:20:17 -0700879std::string ConfigDescription::to_string() const {
Mårten Kongstad24c9aa62018-06-20 08:46:41 +0200880 const String8 str = toString();
Adam Lesinski93190b72017-11-03 15:20:17 -0700881 return std::string(str.string(), str.size());
882}
883
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700884bool ConfigDescription::Dominates(const ConfigDescription& o) const {
Adam Lesinskie3856742017-06-12 14:55:58 -0700885 if (*this == o) {
886 return true;
887 }
888
889 // Locale de-duping is not-trivial, disable for now (b/62409213).
890 if (diff(o) & CONFIG_LOCALE) {
891 return false;
892 }
893
894 if (*this == DefaultConfig()) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700895 return true;
896 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700897 return MatchWithDensity(o) && !o.MatchWithDensity(*this) &&
898 !isMoreSpecificThan(o) && !o.HasHigherPrecedenceThan(*this);
Alexandria Cornwall77788eb2016-09-06 15:16:49 -0700899}
900
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700901bool ConfigDescription::HasHigherPrecedenceThan(
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700902 const ConfigDescription& o) const {
903 // The order of the following tests defines the importance of one
904 // configuration parameter over another. Those tests first are more
905 // important, trumping any values in those following them.
906 // The ordering should be the same as ResTable_config#isBetterThan.
907 if (mcc || o.mcc) return (!o.mcc);
908 if (mnc || o.mnc) return (!o.mnc);
909 if (language[0] || o.language[0]) return (!o.language[0]);
910 if (country[0] || o.country[0]) return (!o.country[0]);
911 // Script and variant require either a language or country, both of which
912 // have higher precedence.
913 if ((screenLayout | o.screenLayout) & MASK_LAYOUTDIR) {
914 return !(o.screenLayout & MASK_LAYOUTDIR);
915 }
916 if (smallestScreenWidthDp || o.smallestScreenWidthDp)
917 return (!o.smallestScreenWidthDp);
918 if (screenWidthDp || o.screenWidthDp) return (!o.screenWidthDp);
919 if (screenHeightDp || o.screenHeightDp) return (!o.screenHeightDp);
920 if ((screenLayout | o.screenLayout) & MASK_SCREENSIZE) {
921 return !(o.screenLayout & MASK_SCREENSIZE);
922 }
923 if ((screenLayout | o.screenLayout) & MASK_SCREENLONG) {
924 return !(o.screenLayout & MASK_SCREENLONG);
925 }
926 if ((screenLayout2 | o.screenLayout2) & MASK_SCREENROUND) {
927 return !(o.screenLayout2 & MASK_SCREENROUND);
928 }
Romain Guy48327452017-01-23 17:03:35 -0800929 if ((colorMode | o.colorMode) & MASK_HDR) {
930 return !(o.colorMode & MASK_HDR);
Romain Guyc9ba5592017-01-18 16:34:42 -0800931 }
Romain Guy48327452017-01-23 17:03:35 -0800932 if ((colorMode | o.colorMode) & MASK_WIDE_COLOR_GAMUT) {
933 return !(o.colorMode & MASK_WIDE_COLOR_GAMUT);
Romain Guyc9ba5592017-01-18 16:34:42 -0800934 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700935 if (orientation || o.orientation) return (!o.orientation);
936 if ((uiMode | o.uiMode) & MASK_UI_MODE_TYPE) {
937 return !(o.uiMode & MASK_UI_MODE_TYPE);
938 }
939 if ((uiMode | o.uiMode) & MASK_UI_MODE_NIGHT) {
940 return !(o.uiMode & MASK_UI_MODE_NIGHT);
941 }
942 if (density || o.density) return (!o.density);
943 if (touchscreen || o.touchscreen) return (!o.touchscreen);
944 if ((inputFlags | o.inputFlags) & MASK_KEYSHIDDEN) {
945 return !(o.inputFlags & MASK_KEYSHIDDEN);
946 }
947 if ((inputFlags | o.inputFlags) & MASK_NAVHIDDEN) {
948 return !(o.inputFlags & MASK_NAVHIDDEN);
949 }
950 if (keyboard || o.keyboard) return (!o.keyboard);
951 if (navigation || o.navigation) return (!o.navigation);
952 if (screenWidth || o.screenWidth) return (!o.screenWidth);
953 if (screenHeight || o.screenHeight) return (!o.screenHeight);
954 if (sdkVersion || o.sdkVersion) return (!o.sdkVersion);
955 if (minorVersion || o.minorVersion) return (!o.minorVersion);
956 // Both configurations have nothing defined except some possible future
957 // value. Returning the comparison of the two configurations is a
958 // "best effort" at this point to protect against incorrect dominations.
959 return *this != o;
Alexandria Cornwall77788eb2016-09-06 15:16:49 -0700960}
961
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700962bool ConfigDescription::ConflictsWith(const ConfigDescription& o) const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700963 // This method should be updated as new configuration parameters are
964 // introduced (e.g. screenConfig2).
965 auto pred = [](const uint32_t a, const uint32_t b) -> bool {
966 return a == 0 || b == 0 || a == b;
967 };
968 // The values here can be found in ResTable_config#match. Density and range
969 // values can't lead to conflicts, and are ignored.
970 return !pred(mcc, o.mcc) || !pred(mnc, o.mnc) || !pred(locale, o.locale) ||
971 !pred(screenLayout & MASK_LAYOUTDIR,
972 o.screenLayout & MASK_LAYOUTDIR) ||
973 !pred(screenLayout & MASK_SCREENLONG,
974 o.screenLayout & MASK_SCREENLONG) ||
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700975 !pred(uiMode & MASK_UI_MODE_TYPE, o.uiMode & MASK_UI_MODE_TYPE) ||
976 !pred(uiMode & MASK_UI_MODE_NIGHT, o.uiMode & MASK_UI_MODE_NIGHT) ||
977 !pred(screenLayout2 & MASK_SCREENROUND,
978 o.screenLayout2 & MASK_SCREENROUND) ||
Romain Guy48327452017-01-23 17:03:35 -0800979 !pred(colorMode & MASK_HDR, o.colorMode & MASK_HDR) ||
980 !pred(colorMode & MASK_WIDE_COLOR_GAMUT,
981 o.colorMode & MASK_WIDE_COLOR_GAMUT) ||
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700982 !pred(orientation, o.orientation) ||
983 !pred(touchscreen, o.touchscreen) ||
984 !pred(inputFlags & MASK_KEYSHIDDEN, o.inputFlags & MASK_KEYSHIDDEN) ||
985 !pred(inputFlags & MASK_NAVHIDDEN, o.inputFlags & MASK_NAVHIDDEN) ||
986 !pred(keyboard, o.keyboard) || !pred(navigation, o.navigation);
Alexandria Cornwall77788eb2016-09-06 15:16:49 -0700987}
988
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700989bool ConfigDescription::IsCompatibleWith(const ConfigDescription& o) const {
990 return !ConflictsWith(o) && !Dominates(o) && !o.Dominates(*this);
Alexandria Cornwall77788eb2016-09-06 15:16:49 -0700991}
992
Mårten Kongstad24c9aa62018-06-20 08:46:41 +0200993} // namespace android