ConfigDescription.cpp revision 6425497f4129a40e75569328525c0dcbaa6e3f22
1/* 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" 20#include "util/StringPiece.h" 21#include "util/Util.h" 22 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 167static 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 187static 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 658 if (parseScreenRound(partIter->c_str(), &config)) { 659 ++partIter; 660 if (partIter == partsEnd) { 661 goto success; 662 } 663 } 664 665 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; 755 if (config->screenLayout2 & ResTable_config::MASK_SCREENROUND) { 756 minSdk = SDK_MARSHMALLOW; 757 } else if (config->density == ResTable_config::DENSITY_ANY) { 758 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 782