blob: 6a099651f2ce57d939e49573ea568465ce4e8f4a [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
17#include "ConfigDescription.h"
Adam Lesinskice5e56e2016-10-21 17:56:45 -070018
19#include <string>
20#include <vector>
21
22#include "androidfw/ResourceTypes.h"
Adam Lesinskid5083f62017-01-16 15:07:21 -080023#include "androidfw/StringPiece.h"
Adam Lesinskice5e56e2016-10-21 17:56:45 -070024
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080025#include "Locale.h"
26#include "SdkConstants.h"
Adam Lesinski1ab598f2015-08-14 14:26:04 -070027#include "util/Util.h"
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080028
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080029using android::ResTable_config;
Adam Lesinskid5083f62017-01-16 15:07:21 -080030using android::StringPiece;
31
32namespace aapt {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080033
34static const char* kWildcardName = "any";
35
Adam Lesinskice5e56e2016-10-21 17:56:45 -070036const ConfigDescription& ConfigDescription::DefaultConfig() {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070037 static ConfigDescription config = {};
38 return config;
Adam Lesinski52364f72016-01-11 13:10:24 -080039}
40
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080041static bool parseMcc(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070042 if (strcmp(name, kWildcardName) == 0) {
43 if (out) out->mcc = 0;
44 return true;
45 }
46 const char* c = name;
47 if (tolower(*c) != 'm') return false;
48 c++;
49 if (tolower(*c) != 'c') return false;
50 c++;
51 if (tolower(*c) != 'c') return false;
52 c++;
53
54 const char* val = c;
55
56 while (*c >= '0' && *c <= '9') {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080057 c++;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070058 }
59 if (*c != 0) return false;
60 if (c - val != 3) return false;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080061
Adam Lesinskicacb28f2016-10-19 12:18:14 -070062 int d = atoi(val);
63 if (d != 0) {
64 if (out) out->mcc = d;
65 return true;
66 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080067
Adam Lesinskicacb28f2016-10-19 12:18:14 -070068 return false;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080069}
70
71static bool parseMnc(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070072 if (strcmp(name, kWildcardName) == 0) {
Adam Lesinski13c0c742017-08-07 10:32:18 -070073 if (out) out->mnc = 0;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080074 return true;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070075 }
76 const char* c = name;
77 if (tolower(*c) != 'm') return false;
78 c++;
79 if (tolower(*c) != 'n') return false;
80 c++;
81 if (tolower(*c) != 'c') return false;
82 c++;
83
84 const char* val = c;
85
86 while (*c >= '0' && *c <= '9') {
87 c++;
88 }
89 if (*c != 0) return false;
90 if (c - val == 0 || c - val > 3) return false;
91
92 if (out) {
93 out->mnc = atoi(val);
94 if (out->mnc == 0) {
95 out->mnc = ACONFIGURATION_MNC_ZERO;
96 }
97 }
98
99 return true;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800100}
101
102static bool parseLayoutDirection(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700103 if (strcmp(name, kWildcardName) == 0) {
104 if (out)
105 out->screenLayout =
106 (out->screenLayout & ~ResTable_config::MASK_LAYOUTDIR) |
107 ResTable_config::LAYOUTDIR_ANY;
108 return true;
109 } else if (strcmp(name, "ldltr") == 0) {
110 if (out)
111 out->screenLayout =
112 (out->screenLayout & ~ResTable_config::MASK_LAYOUTDIR) |
113 ResTable_config::LAYOUTDIR_LTR;
114 return true;
115 } else if (strcmp(name, "ldrtl") == 0) {
116 if (out)
117 out->screenLayout =
118 (out->screenLayout & ~ResTable_config::MASK_LAYOUTDIR) |
119 ResTable_config::LAYOUTDIR_RTL;
120 return true;
121 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800122
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700123 return false;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800124}
125
126static bool parseScreenLayoutSize(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700127 if (strcmp(name, kWildcardName) == 0) {
128 if (out)
129 out->screenLayout =
130 (out->screenLayout & ~ResTable_config::MASK_SCREENSIZE) |
131 ResTable_config::SCREENSIZE_ANY;
132 return true;
133 } else if (strcmp(name, "small") == 0) {
134 if (out)
135 out->screenLayout =
136 (out->screenLayout & ~ResTable_config::MASK_SCREENSIZE) |
137 ResTable_config::SCREENSIZE_SMALL;
138 return true;
139 } else if (strcmp(name, "normal") == 0) {
140 if (out)
141 out->screenLayout =
142 (out->screenLayout & ~ResTable_config::MASK_SCREENSIZE) |
143 ResTable_config::SCREENSIZE_NORMAL;
144 return true;
145 } else if (strcmp(name, "large") == 0) {
146 if (out)
147 out->screenLayout =
148 (out->screenLayout & ~ResTable_config::MASK_SCREENSIZE) |
149 ResTable_config::SCREENSIZE_LARGE;
150 return true;
151 } else if (strcmp(name, "xlarge") == 0) {
152 if (out)
153 out->screenLayout =
154 (out->screenLayout & ~ResTable_config::MASK_SCREENSIZE) |
155 ResTable_config::SCREENSIZE_XLARGE;
156 return true;
157 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800158
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700159 return false;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800160}
161
162static bool parseScreenLayoutLong(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700163 if (strcmp(name, kWildcardName) == 0) {
164 if (out)
165 out->screenLayout =
166 (out->screenLayout & ~ResTable_config::MASK_SCREENLONG) |
167 ResTable_config::SCREENLONG_ANY;
168 return true;
169 } else if (strcmp(name, "long") == 0) {
170 if (out)
171 out->screenLayout =
172 (out->screenLayout & ~ResTable_config::MASK_SCREENLONG) |
173 ResTable_config::SCREENLONG_YES;
174 return true;
175 } else if (strcmp(name, "notlong") == 0) {
176 if (out)
177 out->screenLayout =
178 (out->screenLayout & ~ResTable_config::MASK_SCREENLONG) |
179 ResTable_config::SCREENLONG_NO;
180 return true;
181 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800182
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700183 return false;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800184}
185
Adam Lesinski64254972015-11-03 16:16:17 -0800186static bool parseScreenRound(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700187 if (strcmp(name, kWildcardName) == 0) {
188 if (out)
189 out->screenLayout2 =
190 (out->screenLayout2 & ~ResTable_config::MASK_SCREENROUND) |
191 ResTable_config::SCREENROUND_ANY;
192 return true;
193 } else if (strcmp(name, "round") == 0) {
194 if (out)
195 out->screenLayout2 =
196 (out->screenLayout2 & ~ResTable_config::MASK_SCREENROUND) |
197 ResTable_config::SCREENROUND_YES;
198 return true;
199 } else if (strcmp(name, "notround") == 0) {
200 if (out)
201 out->screenLayout2 =
202 (out->screenLayout2 & ~ResTable_config::MASK_SCREENROUND) |
203 ResTable_config::SCREENROUND_NO;
204 return true;
205 }
206 return false;
Adam Lesinski64254972015-11-03 16:16:17 -0800207}
208
Romain Guyc9ba5592017-01-18 16:34:42 -0800209static bool parseWideColorGamut(const char* name, ResTable_config* out) {
210 if (strcmp(name, kWildcardName) == 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_ANY;
215 return true;
216 } else if (strcmp(name, "widecg") == 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_YES;
221 return true;
222 } else if (strcmp(name, "nowidecg") == 0) {
223 if (out)
Romain Guy48327452017-01-23 17:03:35 -0800224 out->colorMode =
225 (out->colorMode & ~ResTable_config::MASK_WIDE_COLOR_GAMUT) |
Romain Guyc9ba5592017-01-18 16:34:42 -0800226 ResTable_config::WIDE_COLOR_GAMUT_NO;
227 return true;
228 }
229 return false;
230}
231
232static bool parseHdr(const char* name, ResTable_config* out) {
233 if (strcmp(name, kWildcardName) == 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_ANY;
238 return true;
239 } else if (strcmp(name, "highdr") == 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_YES;
244 return true;
245 } else if (strcmp(name, "lowdr") == 0) {
246 if (out)
Romain Guy48327452017-01-23 17:03:35 -0800247 out->colorMode =
248 (out->colorMode & ~ResTable_config::MASK_HDR) |
Romain Guyc9ba5592017-01-18 16:34:42 -0800249 ResTable_config::HDR_NO;
250 return true;
251 }
252 return false;
253}
254
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800255static bool parseOrientation(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700256 if (strcmp(name, kWildcardName) == 0) {
257 if (out) out->orientation = out->ORIENTATION_ANY;
258 return true;
259 } else if (strcmp(name, "port") == 0) {
260 if (out) out->orientation = out->ORIENTATION_PORT;
261 return true;
262 } else if (strcmp(name, "land") == 0) {
263 if (out) out->orientation = out->ORIENTATION_LAND;
264 return true;
265 } else if (strcmp(name, "square") == 0) {
266 if (out) out->orientation = out->ORIENTATION_SQUARE;
267 return true;
268 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800269
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700270 return false;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800271}
272
273static bool parseUiModeType(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700274 if (strcmp(name, kWildcardName) == 0) {
275 if (out)
276 out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_TYPE) |
277 ResTable_config::UI_MODE_TYPE_ANY;
278 return true;
279 } else if (strcmp(name, "desk") == 0) {
280 if (out)
281 out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_TYPE) |
282 ResTable_config::UI_MODE_TYPE_DESK;
283 return true;
284 } else if (strcmp(name, "car") == 0) {
285 if (out)
286 out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_TYPE) |
287 ResTable_config::UI_MODE_TYPE_CAR;
288 return true;
289 } else if (strcmp(name, "television") == 0) {
290 if (out)
291 out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_TYPE) |
292 ResTable_config::UI_MODE_TYPE_TELEVISION;
293 return true;
294 } else if (strcmp(name, "appliance") == 0) {
295 if (out)
296 out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_TYPE) |
297 ResTable_config::UI_MODE_TYPE_APPLIANCE;
298 return true;
299 } else if (strcmp(name, "watch") == 0) {
300 if (out)
301 out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_TYPE) |
302 ResTable_config::UI_MODE_TYPE_WATCH;
303 return true;
Zak Cohen1a6acdb2016-12-12 15:21:21 -0800304 } else if (strcmp(name, "vrheadset") == 0) {
305 if (out)
306 out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_TYPE) |
307 ResTable_config::UI_MODE_TYPE_VR_HEADSET;
308 return true;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700309 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800310
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700311 return false;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800312}
313
314static bool parseUiModeNight(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700315 if (strcmp(name, kWildcardName) == 0) {
316 if (out)
317 out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_NIGHT) |
318 ResTable_config::UI_MODE_NIGHT_ANY;
319 return true;
320 } else if (strcmp(name, "night") == 0) {
321 if (out)
322 out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_NIGHT) |
323 ResTable_config::UI_MODE_NIGHT_YES;
324 return true;
325 } else if (strcmp(name, "notnight") == 0) {
326 if (out)
327 out->uiMode = (out->uiMode & ~ResTable_config::MASK_UI_MODE_NIGHT) |
328 ResTable_config::UI_MODE_NIGHT_NO;
329 return true;
330 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800331
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700332 return false;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800333}
334
335static bool parseDensity(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700336 if (strcmp(name, kWildcardName) == 0) {
337 if (out) out->density = ResTable_config::DENSITY_DEFAULT;
338 return true;
339 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800340
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700341 if (strcmp(name, "anydpi") == 0) {
342 if (out) out->density = ResTable_config::DENSITY_ANY;
343 return true;
344 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800345
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700346 if (strcmp(name, "nodpi") == 0) {
347 if (out) out->density = ResTable_config::DENSITY_NONE;
348 return true;
349 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800350
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700351 if (strcmp(name, "ldpi") == 0) {
352 if (out) out->density = ResTable_config::DENSITY_LOW;
353 return true;
354 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800355
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700356 if (strcmp(name, "mdpi") == 0) {
357 if (out) out->density = ResTable_config::DENSITY_MEDIUM;
358 return true;
359 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800360
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700361 if (strcmp(name, "tvdpi") == 0) {
362 if (out) out->density = ResTable_config::DENSITY_TV;
363 return true;
364 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800365
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700366 if (strcmp(name, "hdpi") == 0) {
367 if (out) out->density = ResTable_config::DENSITY_HIGH;
368 return true;
369 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800370
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700371 if (strcmp(name, "xhdpi") == 0) {
372 if (out) out->density = ResTable_config::DENSITY_XHIGH;
373 return true;
374 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800375
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700376 if (strcmp(name, "xxhdpi") == 0) {
377 if (out) out->density = ResTable_config::DENSITY_XXHIGH;
378 return true;
379 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800380
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700381 if (strcmp(name, "xxxhdpi") == 0) {
382 if (out) out->density = ResTable_config::DENSITY_XXXHIGH;
383 return true;
384 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800385
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700386 char* c = (char*)name;
387 while (*c >= '0' && *c <= '9') {
388 c++;
389 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800390
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700391 // check that we have 'dpi' after the last digit.
392 if (toupper(c[0]) != 'D' || toupper(c[1]) != 'P' || toupper(c[2]) != 'I' ||
393 c[3] != 0) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800394 return false;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700395 }
396
397 // temporarily replace the first letter with \0 to
398 // use atoi.
399 char tmp = c[0];
400 c[0] = '\0';
401
402 int d = atoi(name);
403 c[0] = tmp;
404
405 if (d != 0) {
406 if (out) out->density = d;
407 return true;
408 }
409
410 return false;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800411}
412
413static bool parseTouchscreen(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700414 if (strcmp(name, kWildcardName) == 0) {
415 if (out) out->touchscreen = out->TOUCHSCREEN_ANY;
416 return true;
417 } else if (strcmp(name, "notouch") == 0) {
418 if (out) out->touchscreen = out->TOUCHSCREEN_NOTOUCH;
419 return true;
420 } else if (strcmp(name, "stylus") == 0) {
421 if (out) out->touchscreen = out->TOUCHSCREEN_STYLUS;
422 return true;
423 } else if (strcmp(name, "finger") == 0) {
424 if (out) out->touchscreen = out->TOUCHSCREEN_FINGER;
425 return true;
426 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800427
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700428 return false;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800429}
430
431static bool parseKeysHidden(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700432 uint8_t mask = 0;
433 uint8_t value = 0;
434 if (strcmp(name, kWildcardName) == 0) {
435 mask = ResTable_config::MASK_KEYSHIDDEN;
436 value = ResTable_config::KEYSHIDDEN_ANY;
437 } else if (strcmp(name, "keysexposed") == 0) {
438 mask = ResTable_config::MASK_KEYSHIDDEN;
439 value = ResTable_config::KEYSHIDDEN_NO;
440 } else if (strcmp(name, "keyshidden") == 0) {
441 mask = ResTable_config::MASK_KEYSHIDDEN;
442 value = ResTable_config::KEYSHIDDEN_YES;
443 } else if (strcmp(name, "keyssoft") == 0) {
444 mask = ResTable_config::MASK_KEYSHIDDEN;
445 value = ResTable_config::KEYSHIDDEN_SOFT;
446 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800447
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700448 if (mask != 0) {
449 if (out) out->inputFlags = (out->inputFlags & ~mask) | value;
450 return true;
451 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800452
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700453 return false;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800454}
455
456static bool parseKeyboard(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700457 if (strcmp(name, kWildcardName) == 0) {
458 if (out) out->keyboard = out->KEYBOARD_ANY;
459 return true;
460 } else if (strcmp(name, "nokeys") == 0) {
461 if (out) out->keyboard = out->KEYBOARD_NOKEYS;
462 return true;
463 } else if (strcmp(name, "qwerty") == 0) {
464 if (out) out->keyboard = out->KEYBOARD_QWERTY;
465 return true;
466 } else if (strcmp(name, "12key") == 0) {
467 if (out) out->keyboard = out->KEYBOARD_12KEY;
468 return true;
469 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800470
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700471 return false;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800472}
473
474static bool parseNavHidden(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700475 uint8_t mask = 0;
476 uint8_t value = 0;
477 if (strcmp(name, kWildcardName) == 0) {
478 mask = ResTable_config::MASK_NAVHIDDEN;
479 value = ResTable_config::NAVHIDDEN_ANY;
480 } else if (strcmp(name, "navexposed") == 0) {
481 mask = ResTable_config::MASK_NAVHIDDEN;
482 value = ResTable_config::NAVHIDDEN_NO;
483 } else if (strcmp(name, "navhidden") == 0) {
484 mask = ResTable_config::MASK_NAVHIDDEN;
485 value = ResTable_config::NAVHIDDEN_YES;
486 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800487
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700488 if (mask != 0) {
489 if (out) out->inputFlags = (out->inputFlags & ~mask) | value;
490 return true;
491 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800492
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700493 return false;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800494}
495
496static bool parseNavigation(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700497 if (strcmp(name, kWildcardName) == 0) {
498 if (out) out->navigation = out->NAVIGATION_ANY;
499 return true;
500 } else if (strcmp(name, "nonav") == 0) {
501 if (out) out->navigation = out->NAVIGATION_NONAV;
502 return true;
503 } else if (strcmp(name, "dpad") == 0) {
504 if (out) out->navigation = out->NAVIGATION_DPAD;
505 return true;
506 } else if (strcmp(name, "trackball") == 0) {
507 if (out) out->navigation = out->NAVIGATION_TRACKBALL;
508 return true;
509 } else if (strcmp(name, "wheel") == 0) {
510 if (out) out->navigation = out->NAVIGATION_WHEEL;
511 return true;
512 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800513
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700514 return false;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800515}
516
517static bool parseScreenSize(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700518 if (strcmp(name, kWildcardName) == 0) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800519 if (out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700520 out->screenWidth = out->SCREENWIDTH_ANY;
521 out->screenHeight = out->SCREENHEIGHT_ANY;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800522 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800523 return true;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700524 }
525
526 const char* x = name;
527 while (*x >= '0' && *x <= '9') x++;
528 if (x == name || *x != 'x') return false;
529 std::string xName(name, x - name);
530 x++;
531
532 const char* y = x;
533 while (*y >= '0' && *y <= '9') y++;
534 if (y == name || *y != 0) return false;
535 std::string yName(x, y - x);
536
537 uint16_t w = (uint16_t)atoi(xName.c_str());
538 uint16_t h = (uint16_t)atoi(yName.c_str());
539 if (w < h) {
540 return false;
541 }
542
543 if (out) {
544 out->screenWidth = w;
545 out->screenHeight = h;
546 }
547
548 return true;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800549}
550
551static bool parseSmallestScreenWidthDp(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700552 if (strcmp(name, kWildcardName) == 0) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800553 if (out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700554 out->smallestScreenWidthDp = out->SCREENWIDTH_ANY;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800555 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800556 return true;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700557 }
558
559 if (*name != 's') return false;
560 name++;
561 if (*name != 'w') return false;
562 name++;
563 const char* x = name;
564 while (*x >= '0' && *x <= '9') x++;
565 if (x == name || x[0] != 'd' || x[1] != 'p' || x[2] != 0) return false;
566 std::string xName(name, x - name);
567
568 if (out) {
569 out->smallestScreenWidthDp = (uint16_t)atoi(xName.c_str());
570 }
571
572 return true;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800573}
574
575static bool parseScreenWidthDp(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700576 if (strcmp(name, kWildcardName) == 0) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800577 if (out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700578 out->screenWidthDp = out->SCREENWIDTH_ANY;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800579 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800580 return true;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700581 }
582
583 if (*name != 'w') return false;
584 name++;
585 const char* x = name;
586 while (*x >= '0' && *x <= '9') x++;
587 if (x == name || x[0] != 'd' || x[1] != 'p' || x[2] != 0) return false;
588 std::string xName(name, x - name);
589
590 if (out) {
591 out->screenWidthDp = (uint16_t)atoi(xName.c_str());
592 }
593
594 return true;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800595}
596
597static bool parseScreenHeightDp(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700598 if (strcmp(name, kWildcardName) == 0) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800599 if (out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700600 out->screenHeightDp = out->SCREENWIDTH_ANY;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800601 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800602 return true;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700603 }
604
605 if (*name != 'h') return false;
606 name++;
607 const char* x = name;
608 while (*x >= '0' && *x <= '9') x++;
609 if (x == name || x[0] != 'd' || x[1] != 'p' || x[2] != 0) return false;
610 std::string xName(name, x - name);
611
612 if (out) {
613 out->screenHeightDp = (uint16_t)atoi(xName.c_str());
614 }
615
616 return true;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800617}
618
619static bool parseVersion(const char* name, ResTable_config* out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700620 if (strcmp(name, kWildcardName) == 0) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800621 if (out) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700622 out->sdkVersion = out->SDKVERSION_ANY;
623 out->minorVersion = out->MINORVERSION_ANY;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800624 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800625 return true;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700626 }
627
628 if (*name != 'v') {
629 return false;
630 }
631
632 name++;
633 const char* s = name;
634 while (*s >= '0' && *s <= '9') s++;
635 if (s == name || *s != 0) return false;
636 std::string sdkName(name, s - name);
637
638 if (out) {
639 out->sdkVersion = (uint16_t)atoi(sdkName.c_str());
640 out->minorVersion = 0;
641 }
642
643 return true;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800644}
645
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700646bool ConfigDescription::Parse(const StringPiece& str, ConfigDescription* out) {
647 std::vector<std::string> parts = util::SplitAndLowercase(str, '-');
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800648
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700649 ConfigDescription config;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700650 ssize_t parts_consumed = 0;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700651 LocaleValue locale;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800652
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700653 const auto parts_end = parts.end();
654 auto part_iter = parts.begin();
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800655
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700656 if (str.size() == 0) {
657 goto success;
658 }
659
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700660 if (parseMcc(part_iter->c_str(), &config)) {
661 ++part_iter;
662 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700663 goto success;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800664 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700665 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800666
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700667 if (parseMnc(part_iter->c_str(), &config)) {
668 ++part_iter;
669 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700670 goto success;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800671 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700672 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800673
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700674 // Locale spans a few '-' separators, so we let it
675 // control the index.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700676 parts_consumed = locale.InitFromParts(part_iter, parts_end);
677 if (parts_consumed < 0) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800678 return false;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700679 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700680 locale.WriteTo(&config);
681 part_iter += parts_consumed;
682 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700683 goto success;
684 }
685 }
686
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700687 if (parseLayoutDirection(part_iter->c_str(), &config)) {
688 ++part_iter;
689 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700690 goto success;
691 }
692 }
693
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700694 if (parseSmallestScreenWidthDp(part_iter->c_str(), &config)) {
695 ++part_iter;
696 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700697 goto success;
698 }
699 }
700
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700701 if (parseScreenWidthDp(part_iter->c_str(), &config)) {
702 ++part_iter;
703 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700704 goto success;
705 }
706 }
707
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700708 if (parseScreenHeightDp(part_iter->c_str(), &config)) {
709 ++part_iter;
710 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700711 goto success;
712 }
713 }
714
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700715 if (parseScreenLayoutSize(part_iter->c_str(), &config)) {
716 ++part_iter;
717 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700718 goto success;
719 }
720 }
721
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700722 if (parseScreenLayoutLong(part_iter->c_str(), &config)) {
723 ++part_iter;
724 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700725 goto success;
726 }
727 }
728
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700729 if (parseScreenRound(part_iter->c_str(), &config)) {
730 ++part_iter;
731 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700732 goto success;
733 }
734 }
735
Romain Guyc9ba5592017-01-18 16:34:42 -0800736 if (parseWideColorGamut(part_iter->c_str(), &config)) {
737 ++part_iter;
738 if (part_iter == parts_end) {
739 goto success;
740 }
741 }
742
743 if (parseHdr(part_iter->c_str(), &config)) {
744 ++part_iter;
745 if (part_iter == parts_end) {
746 goto success;
747 }
748 }
749
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700750 if (parseOrientation(part_iter->c_str(), &config)) {
751 ++part_iter;
752 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700753 goto success;
754 }
755 }
756
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700757 if (parseUiModeType(part_iter->c_str(), &config)) {
758 ++part_iter;
759 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700760 goto success;
761 }
762 }
763
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700764 if (parseUiModeNight(part_iter->c_str(), &config)) {
765 ++part_iter;
766 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700767 goto success;
768 }
769 }
770
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700771 if (parseDensity(part_iter->c_str(), &config)) {
772 ++part_iter;
773 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700774 goto success;
775 }
776 }
777
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700778 if (parseTouchscreen(part_iter->c_str(), &config)) {
779 ++part_iter;
780 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700781 goto success;
782 }
783 }
784
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700785 if (parseKeysHidden(part_iter->c_str(), &config)) {
786 ++part_iter;
787 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700788 goto success;
789 }
790 }
791
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700792 if (parseKeyboard(part_iter->c_str(), &config)) {
793 ++part_iter;
794 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700795 goto success;
796 }
797 }
798
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700799 if (parseNavHidden(part_iter->c_str(), &config)) {
800 ++part_iter;
801 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700802 goto success;
803 }
804 }
805
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700806 if (parseNavigation(part_iter->c_str(), &config)) {
807 ++part_iter;
808 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700809 goto success;
810 }
811 }
812
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700813 if (parseScreenSize(part_iter->c_str(), &config)) {
814 ++part_iter;
815 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700816 goto success;
817 }
818 }
819
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700820 if (parseVersion(part_iter->c_str(), &config)) {
821 ++part_iter;
822 if (part_iter == parts_end) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700823 goto success;
824 }
825 }
826
827 // Unrecognized.
828 return false;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800829
830success:
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700831 if (out != NULL) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700832 ApplyVersionForCompatibility(&config);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700833 *out = config;
834 }
835 return true;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800836}
837
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700838void ConfigDescription::ApplyVersionForCompatibility(
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700839 ConfigDescription* config) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700840 uint16_t min_sdk = 0;
Zak Cohen1a6acdb2016-12-12 15:21:21 -0800841 if ((config->uiMode & ResTable_config::MASK_UI_MODE_TYPE)
Romain Guyc9ba5592017-01-18 16:34:42 -0800842 == ResTable_config::UI_MODE_TYPE_VR_HEADSET ||
Romain Guy48327452017-01-23 17:03:35 -0800843 config->colorMode & ResTable_config::MASK_WIDE_COLOR_GAMUT ||
844 config->colorMode & ResTable_config::MASK_HDR) {
Zak Cohen1a6acdb2016-12-12 15:21:21 -0800845 min_sdk = SDK_O;
846 } else if (config->screenLayout2 & ResTable_config::MASK_SCREENROUND) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700847 min_sdk = SDK_MARSHMALLOW;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700848 } else if (config->density == ResTable_config::DENSITY_ANY) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700849 min_sdk = SDK_LOLLIPOP;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700850 } else if (config->smallestScreenWidthDp !=
851 ResTable_config::SCREENWIDTH_ANY ||
852 config->screenWidthDp != ResTable_config::SCREENWIDTH_ANY ||
853 config->screenHeightDp != ResTable_config::SCREENHEIGHT_ANY) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700854 min_sdk = SDK_HONEYCOMB_MR2;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700855 } else if ((config->uiMode & ResTable_config::MASK_UI_MODE_TYPE) !=
856 ResTable_config::UI_MODE_TYPE_ANY ||
857 (config->uiMode & ResTable_config::MASK_UI_MODE_NIGHT) !=
858 ResTable_config::UI_MODE_NIGHT_ANY) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700859 min_sdk = SDK_FROYO;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700860 } else if ((config->screenLayout & ResTable_config::MASK_SCREENSIZE) !=
861 ResTable_config::SCREENSIZE_ANY ||
862 (config->screenLayout & ResTable_config::MASK_SCREENLONG) !=
863 ResTable_config::SCREENLONG_ANY ||
864 config->density != ResTable_config::DENSITY_DEFAULT) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700865 min_sdk = SDK_DONUT;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700866 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800867
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700868 if (min_sdk > config->sdkVersion) {
869 config->sdkVersion = min_sdk;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700870 }
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800871}
872
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700873ConfigDescription ConfigDescription::CopyWithoutSdkVersion() const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700874 ConfigDescription copy = *this;
875 copy.sdkVersion = 0;
876 return copy;
Adam Lesinski87675ad2016-07-15 17:03:03 -0700877}
878
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700879bool ConfigDescription::Dominates(const ConfigDescription& o) const {
Adam Lesinskie3856742017-06-12 14:55:58 -0700880 if (*this == o) {
881 return true;
882 }
883
884 // Locale de-duping is not-trivial, disable for now (b/62409213).
885 if (diff(o) & CONFIG_LOCALE) {
886 return false;
887 }
888
889 if (*this == DefaultConfig()) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700890 return true;
891 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700892 return MatchWithDensity(o) && !o.MatchWithDensity(*this) &&
893 !isMoreSpecificThan(o) && !o.HasHigherPrecedenceThan(*this);
Alexandria Cornwall77788eb2016-09-06 15:16:49 -0700894}
895
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700896bool ConfigDescription::HasHigherPrecedenceThan(
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700897 const ConfigDescription& o) const {
898 // The order of the following tests defines the importance of one
899 // configuration parameter over another. Those tests first are more
900 // important, trumping any values in those following them.
901 // The ordering should be the same as ResTable_config#isBetterThan.
902 if (mcc || o.mcc) return (!o.mcc);
903 if (mnc || o.mnc) return (!o.mnc);
904 if (language[0] || o.language[0]) return (!o.language[0]);
905 if (country[0] || o.country[0]) return (!o.country[0]);
906 // Script and variant require either a language or country, both of which
907 // have higher precedence.
908 if ((screenLayout | o.screenLayout) & MASK_LAYOUTDIR) {
909 return !(o.screenLayout & MASK_LAYOUTDIR);
910 }
911 if (smallestScreenWidthDp || o.smallestScreenWidthDp)
912 return (!o.smallestScreenWidthDp);
913 if (screenWidthDp || o.screenWidthDp) return (!o.screenWidthDp);
914 if (screenHeightDp || o.screenHeightDp) return (!o.screenHeightDp);
915 if ((screenLayout | o.screenLayout) & MASK_SCREENSIZE) {
916 return !(o.screenLayout & MASK_SCREENSIZE);
917 }
918 if ((screenLayout | o.screenLayout) & MASK_SCREENLONG) {
919 return !(o.screenLayout & MASK_SCREENLONG);
920 }
921 if ((screenLayout2 | o.screenLayout2) & MASK_SCREENROUND) {
922 return !(o.screenLayout2 & MASK_SCREENROUND);
923 }
Romain Guy48327452017-01-23 17:03:35 -0800924 if ((colorMode | o.colorMode) & MASK_HDR) {
925 return !(o.colorMode & MASK_HDR);
Romain Guyc9ba5592017-01-18 16:34:42 -0800926 }
Romain Guy48327452017-01-23 17:03:35 -0800927 if ((colorMode | o.colorMode) & MASK_WIDE_COLOR_GAMUT) {
928 return !(o.colorMode & MASK_WIDE_COLOR_GAMUT);
Romain Guyc9ba5592017-01-18 16:34:42 -0800929 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700930 if (orientation || o.orientation) return (!o.orientation);
931 if ((uiMode | o.uiMode) & MASK_UI_MODE_TYPE) {
932 return !(o.uiMode & MASK_UI_MODE_TYPE);
933 }
934 if ((uiMode | o.uiMode) & MASK_UI_MODE_NIGHT) {
935 return !(o.uiMode & MASK_UI_MODE_NIGHT);
936 }
937 if (density || o.density) return (!o.density);
938 if (touchscreen || o.touchscreen) return (!o.touchscreen);
939 if ((inputFlags | o.inputFlags) & MASK_KEYSHIDDEN) {
940 return !(o.inputFlags & MASK_KEYSHIDDEN);
941 }
942 if ((inputFlags | o.inputFlags) & MASK_NAVHIDDEN) {
943 return !(o.inputFlags & MASK_NAVHIDDEN);
944 }
945 if (keyboard || o.keyboard) return (!o.keyboard);
946 if (navigation || o.navigation) return (!o.navigation);
947 if (screenWidth || o.screenWidth) return (!o.screenWidth);
948 if (screenHeight || o.screenHeight) return (!o.screenHeight);
949 if (sdkVersion || o.sdkVersion) return (!o.sdkVersion);
950 if (minorVersion || o.minorVersion) return (!o.minorVersion);
951 // Both configurations have nothing defined except some possible future
952 // value. Returning the comparison of the two configurations is a
953 // "best effort" at this point to protect against incorrect dominations.
954 return *this != o;
Alexandria Cornwall77788eb2016-09-06 15:16:49 -0700955}
956
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700957bool ConfigDescription::ConflictsWith(const ConfigDescription& o) const {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700958 // This method should be updated as new configuration parameters are
959 // introduced (e.g. screenConfig2).
960 auto pred = [](const uint32_t a, const uint32_t b) -> bool {
961 return a == 0 || b == 0 || a == b;
962 };
963 // The values here can be found in ResTable_config#match. Density and range
964 // values can't lead to conflicts, and are ignored.
965 return !pred(mcc, o.mcc) || !pred(mnc, o.mnc) || !pred(locale, o.locale) ||
966 !pred(screenLayout & MASK_LAYOUTDIR,
967 o.screenLayout & MASK_LAYOUTDIR) ||
968 !pred(screenLayout & MASK_SCREENLONG,
969 o.screenLayout & MASK_SCREENLONG) ||
970 !pred(screenLayout & MASK_UI_MODE_TYPE,
971 o.screenLayout & MASK_UI_MODE_TYPE) ||
972 !pred(uiMode & MASK_UI_MODE_TYPE, o.uiMode & MASK_UI_MODE_TYPE) ||
973 !pred(uiMode & MASK_UI_MODE_NIGHT, o.uiMode & MASK_UI_MODE_NIGHT) ||
974 !pred(screenLayout2 & MASK_SCREENROUND,
975 o.screenLayout2 & MASK_SCREENROUND) ||
Romain Guy48327452017-01-23 17:03:35 -0800976 !pred(colorMode & MASK_HDR, o.colorMode & MASK_HDR) ||
977 !pred(colorMode & MASK_WIDE_COLOR_GAMUT,
978 o.colorMode & MASK_WIDE_COLOR_GAMUT) ||
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700979 !pred(orientation, o.orientation) ||
980 !pred(touchscreen, o.touchscreen) ||
981 !pred(inputFlags & MASK_KEYSHIDDEN, o.inputFlags & MASK_KEYSHIDDEN) ||
982 !pred(inputFlags & MASK_NAVHIDDEN, o.inputFlags & MASK_NAVHIDDEN) ||
983 !pred(keyboard, o.keyboard) || !pred(navigation, o.navigation);
Alexandria Cornwall77788eb2016-09-06 15:16:49 -0700984}
985
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700986bool ConfigDescription::IsCompatibleWith(const ConfigDescription& o) const {
987 return !ConflictsWith(o) && !Dominates(o) && !o.Dominates(*this);
Alexandria Cornwall77788eb2016-09-06 15:16:49 -0700988}
989
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700990} // namespace aapt