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