Home | History | Annotate | Download | only in proto
      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