1 /* 2 * Copyright (C) 2016 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 "format/proto/ProtoDeserialize.h" 18 19 #include "android-base/logging.h" 20 #include "android-base/macros.h" 21 #include "androidfw/ResourceTypes.h" 22 #include "androidfw/Locale.h" 23 24 #include "ResourceTable.h" 25 #include "ResourceUtils.h" 26 #include "ResourceValues.h" 27 #include "ValueVisitor.h" 28 29 using ::android::ConfigDescription; 30 using ::android::LocaleValue; 31 using ::android::ResStringPool; 32 33 namespace aapt { 34 35 namespace { 36 37 class ReferenceIdToNameVisitor : public DescendingValueVisitor { 38 public: 39 using DescendingValueVisitor::Visit; 40 41 explicit ReferenceIdToNameVisitor(const std::map<ResourceId, ResourceNameRef>* mapping) 42 : mapping_(mapping) { 43 CHECK(mapping_ != nullptr); 44 } 45 46 void Visit(Reference* reference) override { 47 if (!reference->id || !reference->id.value().is_valid()) { 48 return; 49 } 50 51 ResourceId id = reference->id.value(); 52 auto cache_iter = mapping_->find(id); 53 if (cache_iter != mapping_->end()) { 54 reference->name = cache_iter->second.ToResourceName(); 55 } 56 } 57 58 private: 59 DISALLOW_COPY_AND_ASSIGN(ReferenceIdToNameVisitor); 60 61 const std::map<ResourceId, ResourceNameRef>* mapping_; 62 }; 63 64 } // namespace 65 66 bool DeserializeConfigFromPb(const pb::Configuration& pb_config, ConfigDescription* out_config, 67 std::string* out_error) { 68 out_config->mcc = static_cast<uint16_t>(pb_config.mcc()); 69 out_config->mnc = static_cast<uint16_t>(pb_config.mnc()); 70 71 if (!pb_config.locale().empty()) { 72 LocaleValue lv; 73 if (!lv.InitFromBcp47Tag(pb_config.locale())) { 74 std::ostringstream error; 75 error << "configuration has invalid locale '" << pb_config.locale() << "'"; 76 *out_error = error.str(); 77 return false; 78 } 79 lv.WriteTo(out_config); 80 } 81 82 switch (pb_config.layout_direction()) { 83 case pb::Configuration_LayoutDirection_LAYOUT_DIRECTION_LTR: 84 out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_LAYOUTDIR) | 85 ConfigDescription::LAYOUTDIR_LTR; 86 break; 87 88 case pb::Configuration_LayoutDirection_LAYOUT_DIRECTION_RTL: 89 out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_LAYOUTDIR) | 90 ConfigDescription::LAYOUTDIR_RTL; 91 break; 92 93 default: 94 break; 95 } 96 97 out_config->smallestScreenWidthDp = static_cast<uint16_t>(pb_config.smallest_screen_width_dp()); 98 out_config->screenWidthDp = static_cast<uint16_t>(pb_config.screen_width_dp()); 99 out_config->screenHeightDp = static_cast<uint16_t>(pb_config.screen_height_dp()); 100 101 switch (pb_config.screen_layout_size()) { 102 case pb::Configuration_ScreenLayoutSize_SCREEN_LAYOUT_SIZE_SMALL: 103 out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_SCREENSIZE) | 104 ConfigDescription::SCREENSIZE_SMALL; 105 break; 106 107 case pb::Configuration_ScreenLayoutSize_SCREEN_LAYOUT_SIZE_NORMAL: 108 out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_SCREENSIZE) | 109 ConfigDescription::SCREENSIZE_NORMAL; 110 break; 111 112 case pb::Configuration_ScreenLayoutSize_SCREEN_LAYOUT_SIZE_LARGE: 113 out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_SCREENSIZE) | 114 ConfigDescription::SCREENSIZE_LARGE; 115 break; 116 117 case pb::Configuration_ScreenLayoutSize_SCREEN_LAYOUT_SIZE_XLARGE: 118 out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_SCREENSIZE) | 119 ConfigDescription::SCREENSIZE_XLARGE; 120 break; 121 122 default: 123 break; 124 } 125 126 switch (pb_config.screen_layout_long()) { 127 case pb::Configuration_ScreenLayoutLong_SCREEN_LAYOUT_LONG_LONG: 128 out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_SCREENLONG) | 129 ConfigDescription::SCREENLONG_YES; 130 break; 131 132 case pb::Configuration_ScreenLayoutLong_SCREEN_LAYOUT_LONG_NOTLONG: 133 out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_SCREENLONG) | 134 ConfigDescription::SCREENLONG_NO; 135 break; 136 137 default: 138 break; 139 } 140 141 switch (pb_config.screen_round()) { 142 case pb::Configuration_ScreenRound_SCREEN_ROUND_ROUND: 143 out_config->screenLayout2 = 144 (out_config->screenLayout2 & ~ConfigDescription::MASK_SCREENROUND) | 145 ConfigDescription::SCREENROUND_YES; 146 break; 147 148 case pb::Configuration_ScreenRound_SCREEN_ROUND_NOTROUND: 149 out_config->screenLayout2 = 150 (out_config->screenLayout2 & ~ConfigDescription::MASK_SCREENROUND) | 151 ConfigDescription::SCREENROUND_NO; 152 break; 153 154 default: 155 break; 156 } 157 158 switch (pb_config.wide_color_gamut()) { 159 case pb::Configuration_WideColorGamut_WIDE_COLOR_GAMUT_WIDECG: 160 out_config->colorMode = (out_config->colorMode & ~ConfigDescription::MASK_WIDE_COLOR_GAMUT) | 161 ConfigDescription::WIDE_COLOR_GAMUT_YES; 162 break; 163 164 case pb::Configuration_WideColorGamut_WIDE_COLOR_GAMUT_NOWIDECG: 165 out_config->colorMode = (out_config->colorMode & ~ConfigDescription::MASK_WIDE_COLOR_GAMUT) | 166 ConfigDescription::WIDE_COLOR_GAMUT_NO; 167 break; 168 169 default: 170 break; 171 } 172 173 switch (pb_config.hdr()) { 174 case pb::Configuration_Hdr_HDR_HIGHDR: 175 out_config->colorMode = 176 (out_config->colorMode & ~ConfigDescription::MASK_HDR) | ConfigDescription::HDR_YES; 177 break; 178 179 case pb::Configuration_Hdr_HDR_LOWDR: 180 out_config->colorMode = 181 (out_config->colorMode & ~ConfigDescription::MASK_HDR) | ConfigDescription::HDR_NO; 182 break; 183 184 default: 185 break; 186 } 187 188 switch (pb_config.orientation()) { 189 case pb::Configuration_Orientation_ORIENTATION_PORT: 190 out_config->orientation = ConfigDescription::ORIENTATION_PORT; 191 break; 192 193 case pb::Configuration_Orientation_ORIENTATION_LAND: 194 out_config->orientation = ConfigDescription::ORIENTATION_LAND; 195 break; 196 197 case pb::Configuration_Orientation_ORIENTATION_SQUARE: 198 out_config->orientation = ConfigDescription::ORIENTATION_SQUARE; 199 break; 200 201 default: 202 break; 203 } 204 205 switch (pb_config.ui_mode_type()) { 206 case pb::Configuration_UiModeType_UI_MODE_TYPE_NORMAL: 207 out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) | 208 ConfigDescription::UI_MODE_TYPE_NORMAL; 209 break; 210 211 case pb::Configuration_UiModeType_UI_MODE_TYPE_DESK: 212 out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) | 213 ConfigDescription::UI_MODE_TYPE_DESK; 214 break; 215 216 case pb::Configuration_UiModeType_UI_MODE_TYPE_CAR: 217 out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) | 218 ConfigDescription::UI_MODE_TYPE_CAR; 219 break; 220 221 case pb::Configuration_UiModeType_UI_MODE_TYPE_TELEVISION: 222 out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) | 223 ConfigDescription::UI_MODE_TYPE_TELEVISION; 224 break; 225 226 case pb::Configuration_UiModeType_UI_MODE_TYPE_APPLIANCE: 227 out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) | 228 ConfigDescription::UI_MODE_TYPE_APPLIANCE; 229 break; 230 231 case pb::Configuration_UiModeType_UI_MODE_TYPE_WATCH: 232 out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) | 233 ConfigDescription::UI_MODE_TYPE_WATCH; 234 break; 235 236 case pb::Configuration_UiModeType_UI_MODE_TYPE_VRHEADSET: 237 out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) | 238 ConfigDescription::UI_MODE_TYPE_VR_HEADSET; 239 break; 240 241 default: 242 break; 243 } 244 245 switch (pb_config.ui_mode_night()) { 246 case pb::Configuration_UiModeNight_UI_MODE_NIGHT_NIGHT: 247 out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_NIGHT) | 248 ConfigDescription::UI_MODE_NIGHT_YES; 249 break; 250 251 case pb::Configuration_UiModeNight_UI_MODE_NIGHT_NOTNIGHT: 252 out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_NIGHT) | 253 ConfigDescription::UI_MODE_NIGHT_NO; 254 break; 255 256 default: 257 break; 258 } 259 260 out_config->density = static_cast<uint16_t>(pb_config.density()); 261 262 switch (pb_config.touchscreen()) { 263 case pb::Configuration_Touchscreen_TOUCHSCREEN_NOTOUCH: 264 out_config->touchscreen = ConfigDescription::TOUCHSCREEN_NOTOUCH; 265 break; 266 267 case pb::Configuration_Touchscreen_TOUCHSCREEN_STYLUS: 268 out_config->touchscreen = ConfigDescription::TOUCHSCREEN_STYLUS; 269 break; 270 271 case pb::Configuration_Touchscreen_TOUCHSCREEN_FINGER: 272 out_config->touchscreen = ConfigDescription::TOUCHSCREEN_FINGER; 273 break; 274 275 default: 276 break; 277 } 278 279 switch (pb_config.keys_hidden()) { 280 case pb::Configuration_KeysHidden_KEYS_HIDDEN_KEYSEXPOSED: 281 out_config->inputFlags = (out_config->inputFlags & ~ConfigDescription::MASK_KEYSHIDDEN) | 282 ConfigDescription::KEYSHIDDEN_NO; 283 break; 284 285 case pb::Configuration_KeysHidden_KEYS_HIDDEN_KEYSHIDDEN: 286 out_config->inputFlags = (out_config->inputFlags & ~ConfigDescription::MASK_KEYSHIDDEN) | 287 ConfigDescription::KEYSHIDDEN_YES; 288 break; 289 290 case pb::Configuration_KeysHidden_KEYS_HIDDEN_KEYSSOFT: 291 out_config->inputFlags = (out_config->inputFlags & ~ConfigDescription::MASK_KEYSHIDDEN) | 292 ConfigDescription::KEYSHIDDEN_SOFT; 293 break; 294 295 default: 296 break; 297 } 298 299 switch (pb_config.keyboard()) { 300 case pb::Configuration_Keyboard_KEYBOARD_NOKEYS: 301 out_config->keyboard = ConfigDescription::KEYBOARD_NOKEYS; 302 break; 303 304 case pb::Configuration_Keyboard_KEYBOARD_QWERTY: 305 out_config->keyboard = ConfigDescription::KEYBOARD_QWERTY; 306 break; 307 308 case pb::Configuration_Keyboard_KEYBOARD_TWELVEKEY: 309 out_config->keyboard = ConfigDescription::KEYBOARD_12KEY; 310 break; 311 312 default: 313 break; 314 } 315 316 switch (pb_config.nav_hidden()) { 317 case pb::Configuration_NavHidden_NAV_HIDDEN_NAVEXPOSED: 318 out_config->inputFlags = (out_config->inputFlags & ~ConfigDescription::MASK_NAVHIDDEN) | 319 ConfigDescription::NAVHIDDEN_NO; 320 break; 321 322 case pb::Configuration_NavHidden_NAV_HIDDEN_NAVHIDDEN: 323 out_config->inputFlags = (out_config->inputFlags & ~ConfigDescription::MASK_NAVHIDDEN) | 324 ConfigDescription::NAVHIDDEN_YES; 325 break; 326 327 default: 328 break; 329 } 330 331 switch (pb_config.navigation()) { 332 case pb::Configuration_Navigation_NAVIGATION_NONAV: 333 out_config->navigation = ConfigDescription::NAVIGATION_NONAV; 334 break; 335 336 case pb::Configuration_Navigation_NAVIGATION_DPAD: 337 out_config->navigation = ConfigDescription::NAVIGATION_DPAD; 338 break; 339 340 case pb::Configuration_Navigation_NAVIGATION_TRACKBALL: 341 out_config->navigation = ConfigDescription::NAVIGATION_TRACKBALL; 342 break; 343 344 case pb::Configuration_Navigation_NAVIGATION_WHEEL: 345 out_config->navigation = ConfigDescription::NAVIGATION_WHEEL; 346 break; 347 348 default: 349 break; 350 } 351 352 out_config->screenWidth = static_cast<uint16_t>(pb_config.screen_width()); 353 out_config->screenHeight = static_cast<uint16_t>(pb_config.screen_height()); 354 out_config->sdkVersion = static_cast<uint16_t>(pb_config.sdk_version()); 355 return true; 356 } 357 358 static void DeserializeSourceFromPb(const pb::Source& pb_source, const ResStringPool& src_pool, 359 Source* out_source) { 360 out_source->path = util::GetString(src_pool, pb_source.path_idx()); 361 out_source->line = static_cast<size_t>(pb_source.position().line_number()); 362 } 363 364 static Visibility::Level DeserializeVisibilityFromPb(const pb::Visibility::Level& pb_level) { 365 switch (pb_level) { 366 case pb::Visibility::PRIVATE: 367 return Visibility::Level::kPrivate; 368 case pb::Visibility::PUBLIC: 369 return Visibility::Level::kPublic; 370 default: 371 break; 372 } 373 return Visibility::Level::kUndefined; 374 } 375 376 bool DeserializeOverlayableItemFromPb(const pb::OverlayableItem& pb_overlayable, 377 const android::ResStringPool& src_pool, 378 OverlayableItem* out_overlayable, std::string* out_error) { 379 for (const int policy : pb_overlayable.policy()) { 380 switch (policy) { 381 case pb::OverlayableItem::PUBLIC: 382 out_overlayable->policies |= OverlayableItem::Policy::kPublic; 383 break; 384 case pb::OverlayableItem::SYSTEM: 385 out_overlayable->policies |= OverlayableItem::Policy::kSystem; 386 break; 387 case pb::OverlayableItem::VENDOR: 388 out_overlayable->policies |= OverlayableItem::Policy::kVendor; 389 break; 390 case pb::OverlayableItem::PRODUCT: 391 out_overlayable->policies |= OverlayableItem::Policy::kProduct; 392 break; 393 case pb::OverlayableItem::SIGNATURE: 394 out_overlayable->policies |= OverlayableItem::Policy::kSignature; 395 break; 396 case pb::OverlayableItem::ODM: 397 out_overlayable->policies |= OverlayableItem::Policy::kOdm; 398 break; 399 case pb::OverlayableItem::OEM: 400 out_overlayable->policies |= OverlayableItem::Policy::kOem; 401 break; 402 default: 403 *out_error = "unknown overlayable policy"; 404 return false; 405 } 406 } 407 408 if (pb_overlayable.has_source()) { 409 DeserializeSourceFromPb(pb_overlayable.source(), src_pool, &out_overlayable->source); 410 } 411 412 out_overlayable->comment = pb_overlayable.comment(); 413 return true; 414 } 415 416 static bool DeserializePackageFromPb(const pb::Package& pb_package, const ResStringPool& src_pool, 417 io::IFileCollection* files, 418 const std::vector<std::shared_ptr<Overlayable>>& overlayables, 419 ResourceTable* out_table, std::string* out_error) { 420 Maybe<uint8_t> id; 421 if (pb_package.has_package_id()) { 422 id = static_cast<uint8_t>(pb_package.package_id().id()); 423 } 424 425 std::map<ResourceId, ResourceNameRef> id_index; 426 427 ResourceTablePackage* pkg = 428 out_table->CreatePackageAllowingDuplicateNames(pb_package.package_name(), id); 429 for (const pb::Type& pb_type : pb_package.type()) { 430 const ResourceType* res_type = ParseResourceType(pb_type.name()); 431 if (res_type == nullptr) { 432 std::ostringstream error; 433 error << "unknown type '" << pb_type.name() << "'"; 434 *out_error = error.str(); 435 return false; 436 } 437 438 ResourceTableType* type = pkg->FindOrCreateType(*res_type); 439 if (pb_type.has_type_id()) { 440 type->id = static_cast<uint8_t>(pb_type.type_id().id()); 441 } 442 443 for (const pb::Entry& pb_entry : pb_type.entry()) { 444 ResourceEntry* entry = type->FindOrCreateEntry(pb_entry.name()); 445 if (pb_entry.has_entry_id()) { 446 entry->id = static_cast<uint16_t>(pb_entry.entry_id().id()); 447 } 448 449 // Deserialize the symbol status (public/private with source and comments). 450 if (pb_entry.has_visibility()) { 451 const pb::Visibility& pb_visibility = pb_entry.visibility(); 452 if (pb_visibility.has_source()) { 453 DeserializeSourceFromPb(pb_visibility.source(), src_pool, &entry->visibility.source); 454 } 455 entry->visibility.comment = pb_visibility.comment(); 456 457 const Visibility::Level level = DeserializeVisibilityFromPb(pb_visibility.level()); 458 entry->visibility.level = level; 459 if (level == Visibility::Level::kPublic) { 460 // Propagate the public visibility up to the Type. 461 type->visibility_level = Visibility::Level::kPublic; 462 } else if (level == Visibility::Level::kPrivate) { 463 // Only propagate if no previous state was assigned. 464 if (type->visibility_level == Visibility::Level::kUndefined) { 465 type->visibility_level = Visibility::Level::kPrivate; 466 } 467 } 468 } 469 470 if (pb_entry.has_allow_new()) { 471 const pb::AllowNew& pb_allow_new = pb_entry.allow_new(); 472 473 AllowNew allow_new; 474 if (pb_allow_new.has_source()) { 475 DeserializeSourceFromPb(pb_allow_new.source(), src_pool, &allow_new.source); 476 } 477 allow_new.comment = pb_allow_new.comment(); 478 entry->allow_new = std::move(allow_new); 479 } 480 481 if (pb_entry.has_overlayable_item()) { 482 // Find the overlayable to which this item belongs 483 pb::OverlayableItem pb_overlayable_item = pb_entry.overlayable_item(); 484 if (pb_overlayable_item.overlayable_idx() >= overlayables.size()) { 485 *out_error = android::base::StringPrintf("invalid overlayable_idx value %d", 486 pb_overlayable_item.overlayable_idx()); 487 return false; 488 } 489 490 OverlayableItem overlayable_item(overlayables[pb_overlayable_item.overlayable_idx()]); 491 if (!DeserializeOverlayableItemFromPb(pb_overlayable_item, src_pool, &overlayable_item, 492 out_error)) { 493 return false; 494 } 495 496 entry->overlayable_item = std::move(overlayable_item); 497 } 498 499 ResourceId resid(pb_package.package_id().id(), pb_type.type_id().id(), 500 pb_entry.entry_id().id()); 501 if (resid.is_valid()) { 502 id_index[resid] = ResourceNameRef(pkg->name, type->type, entry->name); 503 } 504 505 for (const pb::ConfigValue& pb_config_value : pb_entry.config_value()) { 506 const pb::Configuration& pb_config = pb_config_value.config(); 507 508 ConfigDescription config; 509 if (!DeserializeConfigFromPb(pb_config, &config, out_error)) { 510 return false; 511 } 512 513 ResourceConfigValue* config_value = entry->FindOrCreateValue(config, pb_config.product()); 514 if (config_value->value != nullptr) { 515 *out_error = "duplicate configuration in resource table"; 516 return false; 517 } 518 519 config_value->value = DeserializeValueFromPb(pb_config_value.value(), src_pool, config, 520 &out_table->string_pool, files, out_error); 521 if (config_value->value == nullptr) { 522 return false; 523 } 524 } 525 } 526 } 527 528 ReferenceIdToNameVisitor visitor(&id_index); 529 VisitAllValuesInPackage(pkg, &visitor); 530 return true; 531 } 532 533 bool DeserializeTableFromPb(const pb::ResourceTable& pb_table, io::IFileCollection* files, 534 ResourceTable* out_table, std::string* out_error) { 535 // We import the android namespace because on Windows NO_ERROR is a macro, not an enum, which 536 // causes errors when qualifying it with android:: 537 using namespace android; 538 539 ResStringPool source_pool; 540 if (pb_table.has_source_pool()) { 541 status_t result = source_pool.setTo(pb_table.source_pool().data().data(), 542 pb_table.source_pool().data().size()); 543 if (result != NO_ERROR) { 544 *out_error = "invalid source pool"; 545 return false; 546 } 547 } 548 549 // Deserialize the overlayable groups of the table 550 std::vector<std::shared_ptr<Overlayable>> overlayables; 551 for (const pb::Overlayable& pb_overlayable : pb_table.overlayable()) { 552 auto group = std::make_shared<Overlayable>(pb_overlayable.name(), pb_overlayable.actor()); 553 if (pb_overlayable.has_source()) { 554 DeserializeSourceFromPb(pb_overlayable.source(), source_pool, &group->source); 555 } 556 overlayables.push_back(group); 557 } 558 559 for (const pb::Package& pb_package : pb_table.package()) { 560 if (!DeserializePackageFromPb(pb_package, source_pool, files, overlayables, out_table, 561 out_error)) { 562 return false; 563 } 564 } 565 return true; 566 } 567 568 static ResourceFile::Type DeserializeFileReferenceTypeFromPb(const pb::FileReference::Type& type) { 569 switch (type) { 570 case pb::FileReference::BINARY_XML: 571 return ResourceFile::Type::kBinaryXml; 572 case pb::FileReference::PROTO_XML: 573 return ResourceFile::Type::kProtoXml; 574 case pb::FileReference::PNG: 575 return ResourceFile::Type::kPng; 576 default: 577 return ResourceFile::Type::kUnknown; 578 } 579 } 580 581 bool DeserializeCompiledFileFromPb(const pb::internal::CompiledFile& pb_file, 582 ResourceFile* out_file, std::string* out_error) { 583 ResourceNameRef name_ref; 584 if (!ResourceUtils::ParseResourceName(pb_file.resource_name(), &name_ref)) { 585 std::ostringstream error; 586 error << "invalid resource name in compiled file header: " << pb_file.resource_name(); 587 *out_error = error.str(); 588 return false; 589 } 590 591 out_file->name = name_ref.ToResourceName(); 592 out_file->source.path = pb_file.source_path(); 593 out_file->type = DeserializeFileReferenceTypeFromPb(pb_file.type()); 594 595 std::string config_error; 596 if (!DeserializeConfigFromPb(pb_file.config(), &out_file->config, &config_error)) { 597 std::ostringstream error; 598 error << "invalid resource configuration in compiled file header: " << config_error; 599 *out_error = error.str(); 600 return false; 601 } 602 603 for (const pb::internal::CompiledFile_Symbol& pb_symbol : pb_file.exported_symbol()) { 604 if (!ResourceUtils::ParseResourceName(pb_symbol.resource_name(), &name_ref)) { 605 std::ostringstream error; 606 error << "invalid resource name for exported symbol in compiled file header: " 607 << pb_file.resource_name(); 608 *out_error = error.str(); 609 return false; 610 } 611 612 size_t line = 0u; 613 if (pb_symbol.has_source()) { 614 line = pb_symbol.source().line_number(); 615 } 616 out_file->exported_symbols.push_back(SourcedResourceName{name_ref.ToResourceName(), line}); 617 } 618 return true; 619 } 620 621 static Reference::Type DeserializeReferenceTypeFromPb(const pb::Reference_Type& pb_type) { 622 switch (pb_type) { 623 case pb::Reference_Type_REFERENCE: 624 return Reference::Type::kResource; 625 case pb::Reference_Type_ATTRIBUTE: 626 return Reference::Type::kAttribute; 627 default: 628 break; 629 } 630 return Reference::Type::kResource; 631 } 632 633 static bool DeserializeReferenceFromPb(const pb::Reference& pb_ref, Reference* out_ref, 634 std::string* out_error) { 635 out_ref->reference_type = DeserializeReferenceTypeFromPb(pb_ref.type()); 636 out_ref->private_reference = pb_ref.private_(); 637 638 if (pb_ref.id() != 0) { 639 out_ref->id = ResourceId(pb_ref.id()); 640 } 641 642 if (!pb_ref.name().empty()) { 643 ResourceNameRef name_ref; 644 if (!ResourceUtils::ParseResourceName(pb_ref.name(), &name_ref, nullptr)) { 645 std::ostringstream error; 646 error << "reference has invalid resource name '" << pb_ref.name() << "'"; 647 *out_error = error.str(); 648 return false; 649 } 650 out_ref->name = name_ref.ToResourceName(); 651 } 652 return true; 653 } 654 655 template <typename T> 656 static void DeserializeItemMetaDataFromPb(const T& pb_item, const android::ResStringPool& src_pool, 657 Value* out_value) { 658 if (pb_item.has_source()) { 659 Source source; 660 DeserializeSourceFromPb(pb_item.source(), src_pool, &source); 661 out_value->SetSource(std::move(source)); 662 } 663 out_value->SetComment(pb_item.comment()); 664 } 665 666 static size_t DeserializePluralEnumFromPb(const pb::Plural_Arity& arity) { 667 switch (arity) { 668 case pb::Plural_Arity_ZERO: 669 return Plural::Zero; 670 case pb::Plural_Arity_ONE: 671 return Plural::One; 672 case pb::Plural_Arity_TWO: 673 return Plural::Two; 674 case pb::Plural_Arity_FEW: 675 return Plural::Few; 676 case pb::Plural_Arity_MANY: 677 return Plural::Many; 678 default: 679 break; 680 } 681 return Plural::Other; 682 } 683 684 std::unique_ptr<Value> DeserializeValueFromPb(const pb::Value& pb_value, 685 const android::ResStringPool& src_pool, 686 const ConfigDescription& config, 687 StringPool* value_pool, io::IFileCollection* files, 688 std::string* out_error) { 689 std::unique_ptr<Value> value; 690 if (pb_value.has_item()) { 691 value = DeserializeItemFromPb(pb_value.item(), src_pool, config, value_pool, files, out_error); 692 if (value == nullptr) { 693 return {}; 694 } 695 696 } else if (pb_value.has_compound_value()) { 697 const pb::CompoundValue& pb_compound_value = pb_value.compound_value(); 698 switch (pb_compound_value.value_case()) { 699 case pb::CompoundValue::kAttr: { 700 const pb::Attribute& pb_attr = pb_compound_value.attr(); 701 std::unique_ptr<Attribute> attr = util::make_unique<Attribute>(pb_attr.format_flags()); 702 attr->min_int = pb_attr.min_int(); 703 attr->max_int = pb_attr.max_int(); 704 for (const pb::Attribute_Symbol& pb_symbol : pb_attr.symbol()) { 705 Attribute::Symbol symbol; 706 DeserializeItemMetaDataFromPb(pb_symbol, src_pool, &symbol.symbol); 707 if (!DeserializeReferenceFromPb(pb_symbol.name(), &symbol.symbol, out_error)) { 708 return {}; 709 } 710 symbol.value = pb_symbol.value(); 711 attr->symbols.push_back(std::move(symbol)); 712 } 713 value = std::move(attr); 714 } break; 715 716 case pb::CompoundValue::kStyle: { 717 const pb::Style& pb_style = pb_compound_value.style(); 718 std::unique_ptr<Style> style = util::make_unique<Style>(); 719 if (pb_style.has_parent()) { 720 style->parent = Reference(); 721 if (!DeserializeReferenceFromPb(pb_style.parent(), &style->parent.value(), out_error)) { 722 return {}; 723 } 724 725 if (pb_style.has_parent_source()) { 726 Source parent_source; 727 DeserializeSourceFromPb(pb_style.parent_source(), src_pool, &parent_source); 728 style->parent.value().SetSource(std::move(parent_source)); 729 } 730 } 731 732 for (const pb::Style_Entry& pb_entry : pb_style.entry()) { 733 Style::Entry entry; 734 if (!DeserializeReferenceFromPb(pb_entry.key(), &entry.key, out_error)) { 735 return {}; 736 } 737 DeserializeItemMetaDataFromPb(pb_entry, src_pool, &entry.key); 738 entry.value = DeserializeItemFromPb(pb_entry.item(), src_pool, config, value_pool, files, 739 out_error); 740 if (entry.value == nullptr) { 741 return {}; 742 } 743 744 // Copy the meta-data into the value as well. 745 DeserializeItemMetaDataFromPb(pb_entry, src_pool, entry.value.get()); 746 style->entries.push_back(std::move(entry)); 747 } 748 value = std::move(style); 749 } break; 750 751 case pb::CompoundValue::kStyleable: { 752 const pb::Styleable& pb_styleable = pb_compound_value.styleable(); 753 std::unique_ptr<Styleable> styleable = util::make_unique<Styleable>(); 754 for (const pb::Styleable_Entry& pb_entry : pb_styleable.entry()) { 755 Reference attr_ref; 756 DeserializeItemMetaDataFromPb(pb_entry, src_pool, &attr_ref); 757 DeserializeReferenceFromPb(pb_entry.attr(), &attr_ref, out_error); 758 styleable->entries.push_back(std::move(attr_ref)); 759 } 760 value = std::move(styleable); 761 } break; 762 763 case pb::CompoundValue::kArray: { 764 const pb::Array& pb_array = pb_compound_value.array(); 765 std::unique_ptr<Array> array = util::make_unique<Array>(); 766 for (const pb::Array_Element& pb_entry : pb_array.element()) { 767 std::unique_ptr<Item> item = DeserializeItemFromPb(pb_entry.item(), src_pool, config, 768 value_pool, files, out_error); 769 if (item == nullptr) { 770 return {}; 771 } 772 773 DeserializeItemMetaDataFromPb(pb_entry, src_pool, item.get()); 774 array->elements.push_back(std::move(item)); 775 } 776 value = std::move(array); 777 } break; 778 779 case pb::CompoundValue::kPlural: { 780 const pb::Plural& pb_plural = pb_compound_value.plural(); 781 std::unique_ptr<Plural> plural = util::make_unique<Plural>(); 782 for (const pb::Plural_Entry& pb_entry : pb_plural.entry()) { 783 size_t plural_idx = DeserializePluralEnumFromPb(pb_entry.arity()); 784 plural->values[plural_idx] = DeserializeItemFromPb(pb_entry.item(), src_pool, config, 785 value_pool, files, out_error); 786 if (!plural->values[plural_idx]) { 787 return {}; 788 } 789 790 DeserializeItemMetaDataFromPb(pb_entry, src_pool, plural->values[plural_idx].get()); 791 } 792 value = std::move(plural); 793 } break; 794 795 default: 796 LOG(FATAL) << "unknown compound value: " << (int)pb_compound_value.value_case(); 797 break; 798 } 799 } else { 800 LOG(FATAL) << "unknown value: " << (int)pb_value.value_case(); 801 return {}; 802 } 803 804 CHECK(value) << "forgot to set value"; 805 806 value->SetWeak(pb_value.weak()); 807 DeserializeItemMetaDataFromPb(pb_value, src_pool, value.get()); 808 return value; 809 } 810 811 std::unique_ptr<Item> DeserializeItemFromPb(const pb::Item& pb_item, 812 const android::ResStringPool& src_pool, 813 const ConfigDescription& config, StringPool* value_pool, 814 io::IFileCollection* files, std::string* out_error) { 815 switch (pb_item.value_case()) { 816 case pb::Item::kRef: { 817 const pb::Reference& pb_ref = pb_item.ref(); 818 std::unique_ptr<Reference> ref = util::make_unique<Reference>(); 819 if (!DeserializeReferenceFromPb(pb_ref, ref.get(), out_error)) { 820 return {}; 821 } 822 return std::move(ref); 823 } break; 824 825 case pb::Item::kPrim: { 826 const pb::Primitive& pb_prim = pb_item.prim(); 827 android::Res_value val = {}; 828 switch (pb_prim.oneof_value_case()) { 829 case pb::Primitive::kNullValue: { 830 val.dataType = android::Res_value::TYPE_NULL; 831 val.data = android::Res_value::DATA_NULL_UNDEFINED; 832 } break; 833 case pb::Primitive::kEmptyValue: { 834 val.dataType = android::Res_value::TYPE_NULL; 835 val.data = android::Res_value::DATA_NULL_EMPTY; 836 } break; 837 case pb::Primitive::kFloatValue: { 838 val.dataType = android::Res_value::TYPE_FLOAT; 839 float float_val = pb_prim.float_value(); 840 val.data = *(uint32_t*)&float_val; 841 } break; 842 case pb::Primitive::kDimensionValue: { 843 val.dataType = android::Res_value::TYPE_DIMENSION; 844 val.data = pb_prim.dimension_value(); 845 } break; 846 case pb::Primitive::kFractionValue: { 847 val.dataType = android::Res_value::TYPE_FRACTION; 848 val.data = pb_prim.fraction_value(); 849 } break; 850 case pb::Primitive::kIntDecimalValue: { 851 val.dataType = android::Res_value::TYPE_INT_DEC; 852 val.data = static_cast<uint32_t>(pb_prim.int_decimal_value()); 853 } break; 854 case pb::Primitive::kIntHexadecimalValue: { 855 val.dataType = android::Res_value::TYPE_INT_HEX; 856 val.data = pb_prim.int_hexadecimal_value(); 857 } break; 858 case pb::Primitive::kBooleanValue: { 859 val.dataType = android::Res_value::TYPE_INT_BOOLEAN; 860 val.data = pb_prim.boolean_value() ? 0xFFFFFFFF : 0x0; 861 } break; 862 case pb::Primitive::kColorArgb8Value: { 863 val.dataType = android::Res_value::TYPE_INT_COLOR_ARGB8; 864 val.data = pb_prim.color_argb8_value(); 865 } break; 866 case pb::Primitive::kColorRgb8Value: { 867 val.dataType = android::Res_value::TYPE_INT_COLOR_RGB8; 868 val.data = pb_prim.color_rgb8_value(); 869 } break; 870 case pb::Primitive::kColorArgb4Value: { 871 val.dataType = android::Res_value::TYPE_INT_COLOR_ARGB4; 872 val.data = pb_prim.color_argb4_value(); 873 } break; 874 case pb::Primitive::kColorRgb4Value: { 875 val.dataType = android::Res_value::TYPE_INT_COLOR_RGB4; 876 val.data = pb_prim.color_rgb4_value(); 877 } break; 878 case pb::Primitive::kDimensionValueDeprecated: { // DEPRECATED 879 val.dataType = android::Res_value::TYPE_DIMENSION; 880 float dimen_val = pb_prim.dimension_value_deprecated(); 881 val.data = *(uint32_t*)&dimen_val; 882 } break; 883 case pb::Primitive::kFractionValueDeprecated: { // DEPRECATED 884 val.dataType = android::Res_value::TYPE_FRACTION; 885 float fraction_val = pb_prim.fraction_value_deprecated(); 886 val.data = *(uint32_t*)&fraction_val; 887 } break; 888 default: { 889 LOG(FATAL) << "Unexpected Primitive type: " 890 << static_cast<uint32_t>(pb_prim.oneof_value_case()); 891 return {}; 892 } break; 893 } 894 return util::make_unique<BinaryPrimitive>(val); 895 } break; 896 897 case pb::Item::kId: { 898 return util::make_unique<Id>(); 899 } break; 900 901 case pb::Item::kStr: { 902 return util::make_unique<String>( 903 value_pool->MakeRef(pb_item.str().value(), StringPool::Context(config))); 904 } break; 905 906 case pb::Item::kRawStr: { 907 return util::make_unique<RawString>( 908 value_pool->MakeRef(pb_item.raw_str().value(), StringPool::Context(config))); 909 } break; 910 911 case pb::Item::kStyledStr: { 912 const pb::StyledString& pb_str = pb_item.styled_str(); 913 StyleString style_str{pb_str.value()}; 914 for (const pb::StyledString::Span& pb_span : pb_str.span()) { 915 style_str.spans.push_back(Span{pb_span.tag(), pb_span.first_char(), pb_span.last_char()}); 916 } 917 return util::make_unique<StyledString>(value_pool->MakeRef( 918 style_str, StringPool::Context(StringPool::Context::kNormalPriority, config))); 919 } break; 920 921 case pb::Item::kFile: { 922 const pb::FileReference& pb_file = pb_item.file(); 923 std::unique_ptr<FileReference> file_ref = 924 util::make_unique<FileReference>(value_pool->MakeRef( 925 pb_file.path(), StringPool::Context(StringPool::Context::kHighPriority, config))); 926 file_ref->type = DeserializeFileReferenceTypeFromPb(pb_file.type()); 927 if (files != nullptr) { 928 file_ref->file = files->FindFile(*file_ref->path); 929 } 930 return std::move(file_ref); 931 } break; 932 933 default: 934 LOG(FATAL) << "unknown item: " << (int)pb_item.value_case(); 935 break; 936 } 937 return {}; 938 } 939 940 std::unique_ptr<xml::XmlResource> DeserializeXmlResourceFromPb(const pb::XmlNode& pb_node, 941 std::string* out_error) { 942 if (!pb_node.has_element()) { 943 return {}; 944 } 945 946 std::unique_ptr<xml::XmlResource> resource = util::make_unique<xml::XmlResource>(); 947 resource->root = util::make_unique<xml::Element>(); 948 if (!DeserializeXmlFromPb(pb_node, resource->root.get(), &resource->string_pool, out_error)) { 949 return {}; 950 } 951 return resource; 952 } 953 954 bool DeserializeXmlFromPb(const pb::XmlNode& pb_node, xml::Element* out_el, StringPool* value_pool, 955 std::string* out_error) { 956 const pb::XmlElement& pb_el = pb_node.element(); 957 out_el->name = pb_el.name(); 958 out_el->namespace_uri = pb_el.namespace_uri(); 959 out_el->line_number = pb_node.source().line_number(); 960 out_el->column_number = pb_node.source().column_number(); 961 962 for (const pb::XmlNamespace& pb_ns : pb_el.namespace_declaration()) { 963 xml::NamespaceDecl decl; 964 decl.uri = pb_ns.uri(); 965 decl.prefix = pb_ns.prefix(); 966 decl.line_number = pb_ns.source().line_number(); 967 decl.column_number = pb_ns.source().column_number(); 968 out_el->namespace_decls.push_back(std::move(decl)); 969 } 970 971 for (const pb::XmlAttribute& pb_attr : pb_el.attribute()) { 972 xml::Attribute attr; 973 attr.name = pb_attr.name(); 974 attr.namespace_uri = pb_attr.namespace_uri(); 975 attr.value = pb_attr.value(); 976 if (pb_attr.resource_id() != 0u) { 977 attr.compiled_attribute = xml::AaptAttribute{Attribute(), ResourceId(pb_attr.resource_id())}; 978 } 979 if (pb_attr.has_compiled_item()) { 980 attr.compiled_value = 981 DeserializeItemFromPb(pb_attr.compiled_item(), {}, {}, value_pool, nullptr, out_error); 982 if (attr.compiled_value == nullptr) { 983 return {}; 984 } 985 attr.compiled_value->SetSource(Source().WithLine(pb_attr.source().line_number())); 986 } 987 out_el->attributes.push_back(std::move(attr)); 988 } 989 990 // Deserialize the children. 991 for (const pb::XmlNode& pb_child : pb_el.child()) { 992 switch (pb_child.node_case()) { 993 case pb::XmlNode::NodeCase::kText: { 994 std::unique_ptr<xml::Text> text = util::make_unique<xml::Text>(); 995 text->line_number = pb_child.source().line_number(); 996 text->column_number = pb_child.source().column_number(); 997 text->text = pb_child.text(); 998 out_el->AppendChild(std::move(text)); 999 } break; 1000 1001 case pb::XmlNode::NodeCase::kElement: { 1002 std::unique_ptr<xml::Element> child_el = util::make_unique<xml::Element>(); 1003 if (!DeserializeXmlFromPb(pb_child, child_el.get(), value_pool, out_error)) { 1004 return false; 1005 } 1006 out_el->AppendChild(std::move(child_el)); 1007 } break; 1008 1009 default: 1010 LOG(FATAL) << "unknown XmlNode " << (int)pb_child.node_case(); 1011 break; 1012 } 1013 } 1014 return true; 1015 } 1016 1017 } // namespace aapt 1018