blob: 64353deb204d299caddf0e18265dc6df84d8b3b4 [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"
18#include "Locale.h"
19#include "SdkConstants.h"
Adam Lesinski1ab598f2015-08-14 14:26:04 -070020#include "util/StringPiece.h"
21#include "util/Util.h"
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080022
23#include <androidfw/ResourceTypes.h>
24#include <string>
25#include <vector>
26
27namespace aapt {
28
29using android::ResTable_config;
30
31static const char* kWildcardName = "any";
32
33static bool parseMcc(const char* name, ResTable_config* out) {
34 if (strcmp(name, kWildcardName) == 0) {
35 if (out) out->mcc = 0;
36 return true;
37 }
38 const char* c = name;
39 if (tolower(*c) != 'm') return false;
40 c++;
41 if (tolower(*c) != 'c') return false;
42 c++;
43 if (tolower(*c) != 'c') return false;
44 c++;
45
46 const char* val = c;
47
48 while (*c >= '0' && *c <= '9') {
49 c++;
50 }
51 if (*c != 0) return false;
52 if (c-val != 3) return false;
53
54 int d = atoi(val);
55 if (d != 0) {
56 if (out) out->mcc = d;
57 return true;
58 }
59
60 return false;
61}
62
63static bool parseMnc(const char* name, ResTable_config* out) {
64 if (strcmp(name, kWildcardName) == 0) {
65 if (out) out->mcc = 0;
66 return true;
67 }
68 const char* c = name;
69 if (tolower(*c) != 'm') return false;
70 c++;
71 if (tolower(*c) != 'n') return false;
72 c++;
73 if (tolower(*c) != 'c') return false;
74 c++;
75
76 const char* val = c;
77
78 while (*c >= '0' && *c <= '9') {
79 c++;
80 }
81 if (*c != 0) return false;
82 if (c-val == 0 || c-val > 3) return false;
83
84 if (out) {
85 out->mnc = atoi(val);
86 if (out->mnc == 0) {
87 out->mnc = ACONFIGURATION_MNC_ZERO;
88 }
89 }
90
91 return true;
92}
93
94static bool parseLayoutDirection(const char* name, ResTable_config* out) {
95 if (strcmp(name, kWildcardName) == 0) {
96 if (out) out->screenLayout =
97 (out->screenLayout&~ResTable_config::MASK_LAYOUTDIR)
98 | ResTable_config::LAYOUTDIR_ANY;
99 return true;
100 } else if (strcmp(name, "ldltr") == 0) {
101 if (out) out->screenLayout =
102 (out->screenLayout&~ResTable_config::MASK_LAYOUTDIR)
103 | ResTable_config::LAYOUTDIR_LTR;
104 return true;
105 } else if (strcmp(name, "ldrtl") == 0) {
106 if (out) out->screenLayout =
107 (out->screenLayout&~ResTable_config::MASK_LAYOUTDIR)
108 | ResTable_config::LAYOUTDIR_RTL;
109 return true;
110 }
111
112 return false;
113}
114
115static bool parseScreenLayoutSize(const char* name, ResTable_config* out) {
116 if (strcmp(name, kWildcardName) == 0) {
117 if (out) out->screenLayout =
118 (out->screenLayout&~ResTable_config::MASK_SCREENSIZE)
119 | ResTable_config::SCREENSIZE_ANY;
120 return true;
121 } else if (strcmp(name, "small") == 0) {
122 if (out) out->screenLayout =
123 (out->screenLayout&~ResTable_config::MASK_SCREENSIZE)
124 | ResTable_config::SCREENSIZE_SMALL;
125 return true;
126 } else if (strcmp(name, "normal") == 0) {
127 if (out) out->screenLayout =
128 (out->screenLayout&~ResTable_config::MASK_SCREENSIZE)
129 | ResTable_config::SCREENSIZE_NORMAL;
130 return true;
131 } else if (strcmp(name, "large") == 0) {
132 if (out) out->screenLayout =
133 (out->screenLayout&~ResTable_config::MASK_SCREENSIZE)
134 | ResTable_config::SCREENSIZE_LARGE;
135 return true;
136 } else if (strcmp(name, "xlarge") == 0) {
137 if (out) out->screenLayout =
138 (out->screenLayout&~ResTable_config::MASK_SCREENSIZE)
139 | ResTable_config::SCREENSIZE_XLARGE;
140 return true;
141 }
142
143 return false;
144}
145
146static bool parseScreenLayoutLong(const char* name, ResTable_config* out) {
147 if (strcmp(name, kWildcardName) == 0) {
148 if (out) out->screenLayout =
149 (out->screenLayout&~ResTable_config::MASK_SCREENLONG)
150 | ResTable_config::SCREENLONG_ANY;
151 return true;
152 } else if (strcmp(name, "long") == 0) {
153 if (out) out->screenLayout =
154 (out->screenLayout&~ResTable_config::MASK_SCREENLONG)
155 | ResTable_config::SCREENLONG_YES;
156 return true;
157 } else if (strcmp(name, "notlong") == 0) {
158 if (out) out->screenLayout =
159 (out->screenLayout&~ResTable_config::MASK_SCREENLONG)
160 | ResTable_config::SCREENLONG_NO;
161 return true;
162 }
163
164 return false;
165}
166
Adam Lesinski64254972015-11-03 16:16:17 -0800167static bool parseScreenRound(const char* name, ResTable_config* out) {
168 if (strcmp(name, kWildcardName) == 0) {
169 if (out) out->screenLayout2 =
170 (out->screenLayout2&~ResTable_config::MASK_SCREENROUND)
171 | ResTable_config::SCREENROUND_ANY;
172 return true;
173 } else if (strcmp(name, "round") == 0) {
174 if (out) out->screenLayout2 =
175 (out->screenLayout2&~ResTable_config::MASK_SCREENROUND)
176 | ResTable_config::SCREENROUND_YES;
177 return true;
178 } else if (strcmp(name, "notround") == 0) {
179 if (out) out->screenLayout2 =
180 (out->screenLayout2&~ResTable_config::MASK_SCREENROUND)
181 | ResTable_config::SCREENROUND_NO;
182 return true;
183 }
184 return false;
185}
186
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800187static bool parseOrientation(const char* name, ResTable_config* out) {
188 if (strcmp(name, kWildcardName) == 0) {
189 if (out) out->orientation = out->ORIENTATION_ANY;
190 return true;
191 } else if (strcmp(name, "port") == 0) {
192 if (out) out->orientation = out->ORIENTATION_PORT;
193 return true;
194 } else if (strcmp(name, "land") == 0) {
195 if (out) out->orientation = out->ORIENTATION_LAND;
196 return true;
197 } else if (strcmp(name, "square") == 0) {
198 if (out) out->orientation = out->ORIENTATION_SQUARE;
199 return true;
200 }
201
202 return false;
203}
204
205static bool parseUiModeType(const char* name, ResTable_config* out) {
206 if (strcmp(name, kWildcardName) == 0) {
207 if (out) out->uiMode =
208 (out->uiMode&~ResTable_config::MASK_UI_MODE_TYPE)
209 | ResTable_config::UI_MODE_TYPE_ANY;
210 return true;
211 } else if (strcmp(name, "desk") == 0) {
212 if (out) out->uiMode =
213 (out->uiMode&~ResTable_config::MASK_UI_MODE_TYPE)
214 | ResTable_config::UI_MODE_TYPE_DESK;
215 return true;
216 } else if (strcmp(name, "car") == 0) {
217 if (out) out->uiMode =
218 (out->uiMode&~ResTable_config::MASK_UI_MODE_TYPE)
219 | ResTable_config::UI_MODE_TYPE_CAR;
220 return true;
221 } else if (strcmp(name, "television") == 0) {
222 if (out) out->uiMode =
223 (out->uiMode&~ResTable_config::MASK_UI_MODE_TYPE)
224 | ResTable_config::UI_MODE_TYPE_TELEVISION;
225 return true;
226 } else if (strcmp(name, "appliance") == 0) {
227 if (out) out->uiMode =
228 (out->uiMode&~ResTable_config::MASK_UI_MODE_TYPE)
229 | ResTable_config::UI_MODE_TYPE_APPLIANCE;
230 return true;
231 } else if (strcmp(name, "watch") == 0) {
232 if (out) out->uiMode =
233 (out->uiMode&~ResTable_config::MASK_UI_MODE_TYPE)
234 | ResTable_config::UI_MODE_TYPE_WATCH;
235 return true;
236 }
237
238 return false;
239}
240
241static bool parseUiModeNight(const char* name, ResTable_config* out) {
242 if (strcmp(name, kWildcardName) == 0) {
243 if (out) out->uiMode =
244 (out->uiMode&~ResTable_config::MASK_UI_MODE_NIGHT)
245 | ResTable_config::UI_MODE_NIGHT_ANY;
246 return true;
247 } else if (strcmp(name, "night") == 0) {
248 if (out) out->uiMode =
249 (out->uiMode&~ResTable_config::MASK_UI_MODE_NIGHT)
250 | ResTable_config::UI_MODE_NIGHT_YES;
251 return true;
252 } else if (strcmp(name, "notnight") == 0) {
253 if (out) out->uiMode =
254 (out->uiMode&~ResTable_config::MASK_UI_MODE_NIGHT)
255 | ResTable_config::UI_MODE_NIGHT_NO;
256 return true;
257 }
258
259 return false;
260}
261
262static bool parseDensity(const char* name, ResTable_config* out) {
263 if (strcmp(name, kWildcardName) == 0) {
264 if (out) out->density = ResTable_config::DENSITY_DEFAULT;
265 return true;
266 }
267
268 if (strcmp(name, "anydpi") == 0) {
269 if (out) out->density = ResTable_config::DENSITY_ANY;
270 return true;
271 }
272
273 if (strcmp(name, "nodpi") == 0) {
274 if (out) out->density = ResTable_config::DENSITY_NONE;
275 return true;
276 }
277
278 if (strcmp(name, "ldpi") == 0) {
279 if (out) out->density = ResTable_config::DENSITY_LOW;
280 return true;
281 }
282
283 if (strcmp(name, "mdpi") == 0) {
284 if (out) out->density = ResTable_config::DENSITY_MEDIUM;
285 return true;
286 }
287
288 if (strcmp(name, "tvdpi") == 0) {
289 if (out) out->density = ResTable_config::DENSITY_TV;
290 return true;
291 }
292
293 if (strcmp(name, "hdpi") == 0) {
294 if (out) out->density = ResTable_config::DENSITY_HIGH;
295 return true;
296 }
297
298 if (strcmp(name, "xhdpi") == 0) {
299 if (out) out->density = ResTable_config::DENSITY_XHIGH;
300 return true;
301 }
302
303 if (strcmp(name, "xxhdpi") == 0) {
304 if (out) out->density = ResTable_config::DENSITY_XXHIGH;
305 return true;
306 }
307
308 if (strcmp(name, "xxxhdpi") == 0) {
309 if (out) out->density = ResTable_config::DENSITY_XXXHIGH;
310 return true;
311 }
312
313 char* c = (char*)name;
314 while (*c >= '0' && *c <= '9') {
315 c++;
316 }
317
318 // check that we have 'dpi' after the last digit.
319 if (toupper(c[0]) != 'D' ||
320 toupper(c[1]) != 'P' ||
321 toupper(c[2]) != 'I' ||
322 c[3] != 0) {
323 return false;
324 }
325
326 // temporarily replace the first letter with \0 to
327 // use atoi.
328 char tmp = c[0];
329 c[0] = '\0';
330
331 int d = atoi(name);
332 c[0] = tmp;
333
334 if (d != 0) {
335 if (out) out->density = d;
336 return true;
337 }
338
339 return false;
340}
341
342static bool parseTouchscreen(const char* name, ResTable_config* out) {
343 if (strcmp(name, kWildcardName) == 0) {
344 if (out) out->touchscreen = out->TOUCHSCREEN_ANY;
345 return true;
346 } else if (strcmp(name, "notouch") == 0) {
347 if (out) out->touchscreen = out->TOUCHSCREEN_NOTOUCH;
348 return true;
349 } else if (strcmp(name, "stylus") == 0) {
350 if (out) out->touchscreen = out->TOUCHSCREEN_STYLUS;
351 return true;
352 } else if (strcmp(name, "finger") == 0) {
353 if (out) out->touchscreen = out->TOUCHSCREEN_FINGER;
354 return true;
355 }
356
357 return false;
358}
359
360static bool parseKeysHidden(const char* name, ResTable_config* out) {
361 uint8_t mask = 0;
362 uint8_t value = 0;
363 if (strcmp(name, kWildcardName) == 0) {
364 mask = ResTable_config::MASK_KEYSHIDDEN;
365 value = ResTable_config::KEYSHIDDEN_ANY;
366 } else if (strcmp(name, "keysexposed") == 0) {
367 mask = ResTable_config::MASK_KEYSHIDDEN;
368 value = ResTable_config::KEYSHIDDEN_NO;
369 } else if (strcmp(name, "keyshidden") == 0) {
370 mask = ResTable_config::MASK_KEYSHIDDEN;
371 value = ResTable_config::KEYSHIDDEN_YES;
372 } else if (strcmp(name, "keyssoft") == 0) {
373 mask = ResTable_config::MASK_KEYSHIDDEN;
374 value = ResTable_config::KEYSHIDDEN_SOFT;
375 }
376
377 if (mask != 0) {
378 if (out) out->inputFlags = (out->inputFlags&~mask) | value;
379 return true;
380 }
381
382 return false;
383}
384
385static bool parseKeyboard(const char* name, ResTable_config* out) {
386 if (strcmp(name, kWildcardName) == 0) {
387 if (out) out->keyboard = out->KEYBOARD_ANY;
388 return true;
389 } else if (strcmp(name, "nokeys") == 0) {
390 if (out) out->keyboard = out->KEYBOARD_NOKEYS;
391 return true;
392 } else if (strcmp(name, "qwerty") == 0) {
393 if (out) out->keyboard = out->KEYBOARD_QWERTY;
394 return true;
395 } else if (strcmp(name, "12key") == 0) {
396 if (out) out->keyboard = out->KEYBOARD_12KEY;
397 return true;
398 }
399
400 return false;
401}
402
403static bool parseNavHidden(const char* name, ResTable_config* out) {
404 uint8_t mask = 0;
405 uint8_t value = 0;
406 if (strcmp(name, kWildcardName) == 0) {
407 mask = ResTable_config::MASK_NAVHIDDEN;
408 value = ResTable_config::NAVHIDDEN_ANY;
409 } else if (strcmp(name, "navexposed") == 0) {
410 mask = ResTable_config::MASK_NAVHIDDEN;
411 value = ResTable_config::NAVHIDDEN_NO;
412 } else if (strcmp(name, "navhidden") == 0) {
413 mask = ResTable_config::MASK_NAVHIDDEN;
414 value = ResTable_config::NAVHIDDEN_YES;
415 }
416
417 if (mask != 0) {
418 if (out) out->inputFlags = (out->inputFlags&~mask) | value;
419 return true;
420 }
421
422 return false;
423}
424
425static bool parseNavigation(const char* name, ResTable_config* out) {
426 if (strcmp(name, kWildcardName) == 0) {
427 if (out) out->navigation = out->NAVIGATION_ANY;
428 return true;
429 } else if (strcmp(name, "nonav") == 0) {
430 if (out) out->navigation = out->NAVIGATION_NONAV;
431 return true;
432 } else if (strcmp(name, "dpad") == 0) {
433 if (out) out->navigation = out->NAVIGATION_DPAD;
434 return true;
435 } else if (strcmp(name, "trackball") == 0) {
436 if (out) out->navigation = out->NAVIGATION_TRACKBALL;
437 return true;
438 } else if (strcmp(name, "wheel") == 0) {
439 if (out) out->navigation = out->NAVIGATION_WHEEL;
440 return true;
441 }
442
443 return false;
444}
445
446static bool parseScreenSize(const char* name, ResTable_config* out) {
447 if (strcmp(name, kWildcardName) == 0) {
448 if (out) {
449 out->screenWidth = out->SCREENWIDTH_ANY;
450 out->screenHeight = out->SCREENHEIGHT_ANY;
451 }
452 return true;
453 }
454
455 const char* x = name;
456 while (*x >= '0' && *x <= '9') x++;
457 if (x == name || *x != 'x') return false;
458 std::string xName(name, x-name);
459 x++;
460
461 const char* y = x;
462 while (*y >= '0' && *y <= '9') y++;
463 if (y == name || *y != 0) return false;
464 std::string yName(x, y-x);
465
466 uint16_t w = (uint16_t)atoi(xName.c_str());
467 uint16_t h = (uint16_t)atoi(yName.c_str());
468 if (w < h) {
469 return false;
470 }
471
472 if (out) {
473 out->screenWidth = w;
474 out->screenHeight = h;
475 }
476
477 return true;
478}
479
480static bool parseSmallestScreenWidthDp(const char* name, ResTable_config* out) {
481 if (strcmp(name, kWildcardName) == 0) {
482 if (out) {
483 out->smallestScreenWidthDp = out->SCREENWIDTH_ANY;
484 }
485 return true;
486 }
487
488 if (*name != 's') return false;
489 name++;
490 if (*name != 'w') return false;
491 name++;
492 const char* x = name;
493 while (*x >= '0' && *x <= '9') x++;
494 if (x == name || x[0] != 'd' || x[1] != 'p' || x[2] != 0) return false;
495 std::string xName(name, x-name);
496
497 if (out) {
498 out->smallestScreenWidthDp = (uint16_t)atoi(xName.c_str());
499 }
500
501 return true;
502}
503
504static bool parseScreenWidthDp(const char* name, ResTable_config* out) {
505 if (strcmp(name, kWildcardName) == 0) {
506 if (out) {
507 out->screenWidthDp = out->SCREENWIDTH_ANY;
508 }
509 return true;
510 }
511
512 if (*name != 'w') return false;
513 name++;
514 const char* x = name;
515 while (*x >= '0' && *x <= '9') x++;
516 if (x == name || x[0] != 'd' || x[1] != 'p' || x[2] != 0) return false;
517 std::string xName(name, x-name);
518
519 if (out) {
520 out->screenWidthDp = (uint16_t)atoi(xName.c_str());
521 }
522
523 return true;
524}
525
526static bool parseScreenHeightDp(const char* name, ResTable_config* out) {
527 if (strcmp(name, kWildcardName) == 0) {
528 if (out) {
529 out->screenHeightDp = out->SCREENWIDTH_ANY;
530 }
531 return true;
532 }
533
534 if (*name != 'h') return false;
535 name++;
536 const char* x = name;
537 while (*x >= '0' && *x <= '9') x++;
538 if (x == name || x[0] != 'd' || x[1] != 'p' || x[2] != 0) return false;
539 std::string xName(name, x-name);
540
541 if (out) {
542 out->screenHeightDp = (uint16_t)atoi(xName.c_str());
543 }
544
545 return true;
546}
547
548static bool parseVersion(const char* name, ResTable_config* out) {
549 if (strcmp(name, kWildcardName) == 0) {
550 if (out) {
551 out->sdkVersion = out->SDKVERSION_ANY;
552 out->minorVersion = out->MINORVERSION_ANY;
553 }
554 return true;
555 }
556
557 if (*name != 'v') {
558 return false;
559 }
560
561 name++;
562 const char* s = name;
563 while (*s >= '0' && *s <= '9') s++;
564 if (s == name || *s != 0) return false;
565 std::string sdkName(name, s-name);
566
567 if (out) {
568 out->sdkVersion = (uint16_t)atoi(sdkName.c_str());
569 out->minorVersion = 0;
570 }
571
572 return true;
573}
574
575bool ConfigDescription::parse(const StringPiece& str, ConfigDescription* out) {
576 std::vector<std::string> parts = util::splitAndLowercase(str, '-');
577
578 ConfigDescription config;
579 ssize_t partsConsumed = 0;
580 LocaleValue locale;
581
582 const auto partsEnd = parts.end();
583 auto partIter = parts.begin();
584
585 if (str.size() == 0) {
586 goto success;
587 }
588
589 if (parseMcc(partIter->c_str(), &config)) {
590 ++partIter;
591 if (partIter == partsEnd) {
592 goto success;
593 }
594 }
595
596 if (parseMnc(partIter->c_str(), &config)) {
597 ++partIter;
598 if (partIter == partsEnd) {
599 goto success;
600 }
601 }
602
603 // Locale spans a few '-' separators, so we let it
604 // control the index.
605 partsConsumed = locale.initFromParts(partIter, partsEnd);
606 if (partsConsumed < 0) {
607 return false;
608 } else {
609 locale.writeTo(&config);
610 partIter += partsConsumed;
611 if (partIter == partsEnd) {
612 goto success;
613 }
614 }
615
616 if (parseLayoutDirection(partIter->c_str(), &config)) {
617 ++partIter;
618 if (partIter == partsEnd) {
619 goto success;
620 }
621 }
622
623 if (parseSmallestScreenWidthDp(partIter->c_str(), &config)) {
624 ++partIter;
625 if (partIter == partsEnd) {
626 goto success;
627 }
628 }
629
630 if (parseScreenWidthDp(partIter->c_str(), &config)) {
631 ++partIter;
632 if (partIter == partsEnd) {
633 goto success;
634 }
635 }
636
637 if (parseScreenHeightDp(partIter->c_str(), &config)) {
638 ++partIter;
639 if (partIter == partsEnd) {
640 goto success;
641 }
642 }
643
644 if (parseScreenLayoutSize(partIter->c_str(), &config)) {
645 ++partIter;
646 if (partIter == partsEnd) {
647 goto success;
648 }
649 }
650
651 if (parseScreenLayoutLong(partIter->c_str(), &config)) {
652 ++partIter;
653 if (partIter == partsEnd) {
654 goto success;
655 }
656 }
657
Adam Lesinski64254972015-11-03 16:16:17 -0800658 if (parseScreenRound(partIter->c_str(), &config)) {
659 ++partIter;
660 if (partIter == partsEnd) {
661 goto success;
662 }
663 }
664
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800665 if (parseOrientation(partIter->c_str(), &config)) {
666 ++partIter;
667 if (partIter == partsEnd) {
668 goto success;
669 }
670 }
671
672 if (parseUiModeType(partIter->c_str(), &config)) {
673 ++partIter;
674 if (partIter == partsEnd) {
675 goto success;
676 }
677 }
678
679 if (parseUiModeNight(partIter->c_str(), &config)) {
680 ++partIter;
681 if (partIter == partsEnd) {
682 goto success;
683 }
684 }
685
686 if (parseDensity(partIter->c_str(), &config)) {
687 ++partIter;
688 if (partIter == partsEnd) {
689 goto success;
690 }
691 }
692
693 if (parseTouchscreen(partIter->c_str(), &config)) {
694 ++partIter;
695 if (partIter == partsEnd) {
696 goto success;
697 }
698 }
699
700 if (parseKeysHidden(partIter->c_str(), &config)) {
701 ++partIter;
702 if (partIter == partsEnd) {
703 goto success;
704 }
705 }
706
707 if (parseKeyboard(partIter->c_str(), &config)) {
708 ++partIter;
709 if (partIter == partsEnd) {
710 goto success;
711 }
712 }
713
714 if (parseNavHidden(partIter->c_str(), &config)) {
715 ++partIter;
716 if (partIter == partsEnd) {
717 goto success;
718 }
719 }
720
721 if (parseNavigation(partIter->c_str(), &config)) {
722 ++partIter;
723 if (partIter == partsEnd) {
724 goto success;
725 }
726 }
727
728 if (parseScreenSize(partIter->c_str(), &config)) {
729 ++partIter;
730 if (partIter == partsEnd) {
731 goto success;
732 }
733 }
734
735 if (parseVersion(partIter->c_str(), &config)) {
736 ++partIter;
737 if (partIter == partsEnd) {
738 goto success;
739 }
740 }
741
742 // Unrecognized.
743 return false;
744
745success:
746 if (out != NULL) {
747 applyVersionForCompatibility(&config);
748 *out = config;
749 }
750 return true;
751}
752
753void ConfigDescription::applyVersionForCompatibility(ConfigDescription* config) {
754 uint16_t minSdk = 0;
Adam Lesinski64254972015-11-03 16:16:17 -0800755 if (config->screenLayout2 & ResTable_config::MASK_SCREENROUND) {
756 minSdk = SDK_MARSHMALLOW;
757 } else if (config->density == ResTable_config::DENSITY_ANY) {
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800758 minSdk = SDK_LOLLIPOP;
759 } else if (config->smallestScreenWidthDp != ResTable_config::SCREENWIDTH_ANY
760 || config->screenWidthDp != ResTable_config::SCREENWIDTH_ANY
761 || config->screenHeightDp != ResTable_config::SCREENHEIGHT_ANY) {
762 minSdk = SDK_HONEYCOMB_MR2;
763 } else if ((config->uiMode & ResTable_config::MASK_UI_MODE_TYPE)
764 != ResTable_config::UI_MODE_TYPE_ANY
765 || (config->uiMode & ResTable_config::MASK_UI_MODE_NIGHT)
766 != ResTable_config::UI_MODE_NIGHT_ANY) {
767 minSdk = SDK_FROYO;
768 } else if ((config->screenLayout & ResTable_config::MASK_SCREENSIZE)
769 != ResTable_config::SCREENSIZE_ANY
770 || (config->screenLayout & ResTable_config::MASK_SCREENLONG)
771 != ResTable_config::SCREENLONG_ANY
772 || config->density != ResTable_config::DENSITY_DEFAULT) {
773 minSdk = SDK_DONUT;
774 }
775
776 if (minSdk > config->sdkVersion) {
777 config->sdkVersion = minSdk;
778 }
779}
780
781} // namespace aapt