18cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski/*
28cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski * Copyright (C) 2016 The Android Open Source Project
38cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski *
48cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
58cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski * you may not use this file except in compliance with the License.
68cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski * You may obtain a copy of the License at
78cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski *
88cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
98cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski *
108cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski * Unless required by applicable law or agreed to in writing, software
118cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
128cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski * See the License for the specific language governing permissions and
148cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski * limitations under the License.
158cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski */
168cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
174670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski#include "format/proto/ProtoDeserialize.h"
188cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
198cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski#include "android-base/logging.h"
208cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski#include "android-base/macros.h"
218cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski#include "androidfw/ResourceTypes.h"
228cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
238cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski#include "Locale.h"
248cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski#include "ResourceTable.h"
258cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski#include "ResourceUtils.h"
26d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz#include "ResourceValues.h"
278cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski#include "ValueVisitor.h"
288cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
298cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinskiusing ::android::ResStringPool;
308cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
318cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinskinamespace aapt {
328cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
338cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinskinamespace {
348cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
358cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinskiclass ReferenceIdToNameVisitor : public DescendingValueVisitor {
368cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski public:
378cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  using DescendingValueVisitor::Visit;
388cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
398cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  explicit ReferenceIdToNameVisitor(const std::map<ResourceId, ResourceNameRef>* mapping)
408cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      : mapping_(mapping) {
418cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    CHECK(mapping_ != nullptr);
428cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
438cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
448cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  void Visit(Reference* reference) override {
458cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    if (!reference->id || !reference->id.value().is_valid()) {
468cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      return;
478cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    }
488cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
498cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    ResourceId id = reference->id.value();
508cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    auto cache_iter = mapping_->find(id);
518cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    if (cache_iter != mapping_->end()) {
528cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      reference->name = cache_iter->second.ToResourceName();
538cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    }
548cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
558cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
568cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski private:
578cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  DISALLOW_COPY_AND_ASSIGN(ReferenceIdToNameVisitor);
588cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
598cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  const std::map<ResourceId, ResourceNameRef>* mapping_;
608cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski};
618cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
628cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski}  // namespace
638cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
648cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinskibool DeserializeConfigFromPb(const pb::Configuration& pb_config, ConfigDescription* out_config,
658cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                             std::string* out_error) {
668cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  out_config->mcc = static_cast<uint16_t>(pb_config.mcc());
678cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  out_config->mnc = static_cast<uint16_t>(pb_config.mnc());
688cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
698cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  if (!pb_config.locale().empty()) {
708cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    LocaleValue lv;
718cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    if (!lv.InitFromBcp47Tag(pb_config.locale())) {
728cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      std::ostringstream error;
738cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      error << "configuration has invalid locale '" << pb_config.locale() << "'";
748cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      *out_error = error.str();
758cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      return false;
768cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    }
778cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    lv.WriteTo(out_config);
788cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
798cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
808cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  switch (pb_config.layout_direction()) {
818cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_LayoutDirection_LAYOUT_DIRECTION_LTR:
828cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_LAYOUTDIR) |
838cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                                 ConfigDescription::LAYOUTDIR_LTR;
848cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
858cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
868cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_LayoutDirection_LAYOUT_DIRECTION_RTL:
878cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_LAYOUTDIR) |
888cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                                 ConfigDescription::LAYOUTDIR_RTL;
898cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
908cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
918cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    default:
928cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
938cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
948cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
958cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  out_config->smallestScreenWidthDp = static_cast<uint16_t>(pb_config.smallest_screen_width_dp());
968cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  out_config->screenWidthDp = static_cast<uint16_t>(pb_config.screen_width_dp());
978cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  out_config->screenHeightDp = static_cast<uint16_t>(pb_config.screen_height_dp());
988cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
998cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  switch (pb_config.screen_layout_size()) {
1008cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_ScreenLayoutSize_SCREEN_LAYOUT_SIZE_SMALL:
1018cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_SCREENSIZE) |
1028cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                                 ConfigDescription::SCREENSIZE_SMALL;
1038cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
1048cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
1058cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_ScreenLayoutSize_SCREEN_LAYOUT_SIZE_NORMAL:
1068cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_SCREENSIZE) |
1078cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                                 ConfigDescription::SCREENSIZE_NORMAL;
1088cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
1098cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
1108cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_ScreenLayoutSize_SCREEN_LAYOUT_SIZE_LARGE:
1118cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_SCREENSIZE) |
1128cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                                 ConfigDescription::SCREENSIZE_LARGE;
1138cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
1148cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
1158cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_ScreenLayoutSize_SCREEN_LAYOUT_SIZE_XLARGE:
1168cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_SCREENSIZE) |
1178cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                                 ConfigDescription::SCREENSIZE_XLARGE;
1188cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
1198cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
1208cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    default:
1218cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
1228cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
1238cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
1248cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  switch (pb_config.screen_layout_long()) {
1258cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_ScreenLayoutLong_SCREEN_LAYOUT_LONG_LONG:
1268cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_SCREENLONG) |
1278cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                                 ConfigDescription::SCREENLONG_YES;
1288cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
1298cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
1308cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_ScreenLayoutLong_SCREEN_LAYOUT_LONG_NOTLONG:
1318cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_SCREENLONG) |
1328cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                                 ConfigDescription::SCREENLONG_NO;
1338cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
1348cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
1358cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    default:
1368cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
1378cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
1388cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
1398cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  switch (pb_config.screen_round()) {
1408cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_ScreenRound_SCREEN_ROUND_ROUND:
1418cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->screenLayout2 =
1428cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          (out_config->screenLayout2 & ~ConfigDescription::MASK_SCREENROUND) |
1438cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          ConfigDescription::SCREENROUND_YES;
1448cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
1458cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
1468cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_ScreenRound_SCREEN_ROUND_NOTROUND:
1478cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->screenLayout2 =
1488cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          (out_config->screenLayout2 & ~ConfigDescription::MASK_SCREENROUND) |
1498cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          ConfigDescription::SCREENROUND_NO;
1508cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
1518cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
1528cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    default:
1538cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
1548cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
1558cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
1568cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  switch (pb_config.wide_color_gamut()) {
1578cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_WideColorGamut_WIDE_COLOR_GAMUT_WIDECG:
1588cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->colorMode = (out_config->colorMode & ~ConfigDescription::MASK_WIDE_COLOR_GAMUT) |
1598cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                              ConfigDescription::WIDE_COLOR_GAMUT_YES;
1608cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
1618cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
1628cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_WideColorGamut_WIDE_COLOR_GAMUT_NOWIDECG:
1638cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->colorMode = (out_config->colorMode & ~ConfigDescription::MASK_WIDE_COLOR_GAMUT) |
1648cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                              ConfigDescription::WIDE_COLOR_GAMUT_NO;
1658cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
1668cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
1678cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    default:
1688cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
1698cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
1708cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
1718cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  switch (pb_config.hdr()) {
1728cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_Hdr_HDR_HIGHDR:
1738cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->colorMode =
1748cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          (out_config->colorMode & ~ConfigDescription::MASK_HDR) | ConfigDescription::HDR_YES;
1758cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
1768cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
1778cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_Hdr_HDR_LOWDR:
1788cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->colorMode =
1798cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          (out_config->colorMode & ~ConfigDescription::MASK_HDR) | ConfigDescription::HDR_NO;
1808cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
1818cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
1828cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    default:
1838cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
1848cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
1858cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
1868cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  switch (pb_config.orientation()) {
1878cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_Orientation_ORIENTATION_PORT:
1888cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->orientation = ConfigDescription::ORIENTATION_PORT;
1898cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
1908cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
1918cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_Orientation_ORIENTATION_LAND:
1928cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->orientation = ConfigDescription::ORIENTATION_LAND;
1938cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
1948cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
1958cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_Orientation_ORIENTATION_SQUARE:
1968cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->orientation = ConfigDescription::ORIENTATION_SQUARE;
1978cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
1988cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
1998cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    default:
2008cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
2018cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
2028cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
2038cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  switch (pb_config.ui_mode_type()) {
2048cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_UiModeType_UI_MODE_TYPE_NORMAL:
2058cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) |
2068cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                           ConfigDescription::UI_MODE_TYPE_NORMAL;
2078cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
2088cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
2098cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_UiModeType_UI_MODE_TYPE_DESK:
2108cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) |
2118cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                           ConfigDescription::UI_MODE_TYPE_DESK;
2128cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
2138cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
2148cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_UiModeType_UI_MODE_TYPE_CAR:
2158cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) |
2168cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                           ConfigDescription::UI_MODE_TYPE_CAR;
2178cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
2188cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
2198cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_UiModeType_UI_MODE_TYPE_TELEVISION:
2208cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) |
2218cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                           ConfigDescription::UI_MODE_TYPE_TELEVISION;
2228cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
2238cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
2248cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_UiModeType_UI_MODE_TYPE_APPLIANCE:
2258cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) |
2268cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                           ConfigDescription::UI_MODE_TYPE_APPLIANCE;
2278cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
2288cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
2298cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_UiModeType_UI_MODE_TYPE_WATCH:
2308cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) |
2318cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                           ConfigDescription::UI_MODE_TYPE_WATCH;
2328cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
2338cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
2348cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_UiModeType_UI_MODE_TYPE_VRHEADSET:
2358cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) |
2368cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                           ConfigDescription::UI_MODE_TYPE_VR_HEADSET;
2378cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
2388cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
2398cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    default:
2408cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
2418cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
2428cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
2438cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  switch (pb_config.ui_mode_night()) {
2448cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_UiModeNight_UI_MODE_NIGHT_NIGHT:
2458cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_NIGHT) |
2468cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                           ConfigDescription::UI_MODE_NIGHT_YES;
2478cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
2488cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
2498cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_UiModeNight_UI_MODE_NIGHT_NOTNIGHT:
2508cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_NIGHT) |
2518cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                           ConfigDescription::UI_MODE_NIGHT_NO;
2528cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
2538cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
2548cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    default:
2558cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
2568cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
2578cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
2588cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  out_config->density = static_cast<uint16_t>(pb_config.density());
2598cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
2608cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  switch (pb_config.touchscreen()) {
2618cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_Touchscreen_TOUCHSCREEN_NOTOUCH:
2628cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->touchscreen = ConfigDescription::TOUCHSCREEN_NOTOUCH;
2638cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
2648cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
2658cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_Touchscreen_TOUCHSCREEN_STYLUS:
2668cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->touchscreen = ConfigDescription::TOUCHSCREEN_STYLUS;
2678cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
2688cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
2698cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_Touchscreen_TOUCHSCREEN_FINGER:
2708cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->touchscreen = ConfigDescription::TOUCHSCREEN_FINGER;
2718cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
2728cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
2738cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    default:
2748cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
2758cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
2768cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
2778cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  switch (pb_config.keys_hidden()) {
2788cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_KeysHidden_KEYS_HIDDEN_KEYSEXPOSED:
2798cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->inputFlags = (out_config->inputFlags & ~ConfigDescription::MASK_KEYSHIDDEN) |
2808cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                               ConfigDescription::KEYSHIDDEN_NO;
2818cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
2828cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
2838cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_KeysHidden_KEYS_HIDDEN_KEYSHIDDEN:
2848cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->inputFlags = (out_config->inputFlags & ~ConfigDescription::MASK_KEYSHIDDEN) |
2858cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                               ConfigDescription::KEYSHIDDEN_YES;
2868cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
2878cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
2888cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_KeysHidden_KEYS_HIDDEN_KEYSSOFT:
2898cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->inputFlags = (out_config->inputFlags & ~ConfigDescription::MASK_KEYSHIDDEN) |
2908cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                               ConfigDescription::KEYSHIDDEN_SOFT;
2918cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
2928cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
2938cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    default:
2948cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
2958cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
2968cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
2978cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  switch (pb_config.keyboard()) {
2988cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_Keyboard_KEYBOARD_NOKEYS:
2998cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->keyboard = ConfigDescription::KEYBOARD_NOKEYS;
3008cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
3018cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
3028cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_Keyboard_KEYBOARD_QWERTY:
3038cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->keyboard = ConfigDescription::KEYBOARD_QWERTY;
3048cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
3058cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
3068cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_Keyboard_KEYBOARD_TWELVEKEY:
3078cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->keyboard = ConfigDescription::KEYBOARD_12KEY;
3088cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
3098cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
3108cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    default:
3118cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
3128cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
3138cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
3148cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  switch (pb_config.nav_hidden()) {
3158cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_NavHidden_NAV_HIDDEN_NAVEXPOSED:
3168cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->inputFlags = (out_config->inputFlags & ~ConfigDescription::MASK_NAVHIDDEN) |
3178cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                               ConfigDescription::NAVHIDDEN_NO;
3188cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
3198cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
3208cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_NavHidden_NAV_HIDDEN_NAVHIDDEN:
3218cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->inputFlags = (out_config->inputFlags & ~ConfigDescription::MASK_NAVHIDDEN) |
3228cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                               ConfigDescription::NAVHIDDEN_YES;
3238cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
3248cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
3258cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    default:
3268cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
3278cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
3288cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
3298cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  switch (pb_config.navigation()) {
3308cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_Navigation_NAVIGATION_NONAV:
3318cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->navigation = ConfigDescription::NAVIGATION_NONAV;
3328cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
3338cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
3348cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_Navigation_NAVIGATION_DPAD:
3358cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->navigation = ConfigDescription::NAVIGATION_DPAD;
3368cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
3378cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
3388cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_Navigation_NAVIGATION_TRACKBALL:
3398cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->navigation = ConfigDescription::NAVIGATION_TRACKBALL;
3408cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
3418cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
3428cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Configuration_Navigation_NAVIGATION_WHEEL:
3438cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      out_config->navigation = ConfigDescription::NAVIGATION_WHEEL;
3448cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
3458cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
3468cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    default:
3478cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
3488cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
3498cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
3508cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  out_config->screenWidth = static_cast<uint16_t>(pb_config.screen_width());
3518cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  out_config->screenHeight = static_cast<uint16_t>(pb_config.screen_height());
3528cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  out_config->sdkVersion = static_cast<uint16_t>(pb_config.sdk_version());
3538cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  return true;
3548cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski}
3558cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
3568cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinskistatic void DeserializeSourceFromPb(const pb::Source& pb_source, const ResStringPool& src_pool,
3578cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                                    Source* out_source) {
3588cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  out_source->path = util::GetString(src_pool, pb_source.path_idx());
3598cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  out_source->line = static_cast<size_t>(pb_source.position().line_number());
3608cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski}
3618cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
36271be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinskistatic Visibility::Level DeserializeVisibilityFromPb(const pb::Visibility::Level& pb_level) {
36371be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski  switch (pb_level) {
36471be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski    case pb::Visibility::PRIVATE:
36571be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski      return Visibility::Level::kPrivate;
36671be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski    case pb::Visibility::PUBLIC:
36771be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski      return Visibility::Level::kPublic;
3688cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    default:
3698cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
3708cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
37171be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski  return Visibility::Level::kUndefined;
3728cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski}
3738cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
3748cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinskistatic bool DeserializePackageFromPb(const pb::Package& pb_package, const ResStringPool& src_pool,
3758780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski                                     io::IFileCollection* files, ResourceTable* out_table,
3768780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski                                     std::string* out_error) {
3778cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  Maybe<uint8_t> id;
3788cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  if (pb_package.has_package_id()) {
3798cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    id = static_cast<uint8_t>(pb_package.package_id().id());
3808cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
3818cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
3828cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  std::map<ResourceId, ResourceNameRef> id_index;
3838cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
384e3c1a4a9d21e7698e9e5196086198569ac5cc6cdDavid Chaloupka  ResourceTablePackage* pkg =
385e3c1a4a9d21e7698e9e5196086198569ac5cc6cdDavid Chaloupka      out_table->CreatePackageAllowingDuplicateNames(pb_package.package_name(), id);
3868cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  for (const pb::Type& pb_type : pb_package.type()) {
3878cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    const ResourceType* res_type = ParseResourceType(pb_type.name());
3888cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    if (res_type == nullptr) {
3898cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      std::ostringstream error;
3908cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      error << "unknown type '" << pb_type.name() << "'";
3918cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      *out_error = error.str();
3928cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      return false;
3938cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    }
3948cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
3958cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    ResourceTableType* type = pkg->FindOrCreateType(*res_type);
396e59f0d80ec19249f72c07ae191ad673d040443e3Adam Lesinski    if (pb_type.has_type_id()) {
397e59f0d80ec19249f72c07ae191ad673d040443e3Adam Lesinski      type->id = static_cast<uint8_t>(pb_type.type_id().id());
398e59f0d80ec19249f72c07ae191ad673d040443e3Adam Lesinski    }
399e59f0d80ec19249f72c07ae191ad673d040443e3Adam Lesinski
4008cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    for (const pb::Entry& pb_entry : pb_type.entry()) {
4018cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      ResourceEntry* entry = type->FindOrCreateEntry(pb_entry.name());
402e59f0d80ec19249f72c07ae191ad673d040443e3Adam Lesinski      if (pb_entry.has_entry_id()) {
403e59f0d80ec19249f72c07ae191ad673d040443e3Adam Lesinski        entry->id = static_cast<uint16_t>(pb_entry.entry_id().id());
404e59f0d80ec19249f72c07ae191ad673d040443e3Adam Lesinski      }
4058cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
4068cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      // Deserialize the symbol status (public/private with source and comments).
40771be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski      if (pb_entry.has_visibility()) {
40871be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski        const pb::Visibility& pb_visibility = pb_entry.visibility();
40971be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski        if (pb_visibility.has_source()) {
41071be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski          DeserializeSourceFromPb(pb_visibility.source(), src_pool, &entry->visibility.source);
4118cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        }
41271be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski        entry->visibility.comment = pb_visibility.comment();
4138cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
41471be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski        const Visibility::Level level = DeserializeVisibilityFromPb(pb_visibility.level());
41571be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski        entry->visibility.level = level;
41671be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski        if (level == Visibility::Level::kPublic) {
417e59f0d80ec19249f72c07ae191ad673d040443e3Adam Lesinski          // Propagate the public visibility up to the Type.
41871be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski          type->visibility_level = Visibility::Level::kPublic;
41971be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski        } else if (level == Visibility::Level::kPrivate) {
420e59f0d80ec19249f72c07ae191ad673d040443e3Adam Lesinski          // Only propagate if no previous state was assigned.
42171be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski          if (type->visibility_level == Visibility::Level::kUndefined) {
42271be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski            type->visibility_level = Visibility::Level::kPrivate;
4238cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          }
4248cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        }
4258cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      }
4268cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
42771be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski      if (pb_entry.has_allow_new()) {
42871be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski        const pb::AllowNew& pb_allow_new = pb_entry.allow_new();
42971be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski
43071be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski        AllowNew allow_new;
43171be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski        if (pb_allow_new.has_source()) {
43271be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski          DeserializeSourceFromPb(pb_allow_new.source(), src_pool, &allow_new.source);
43371be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski        }
43471be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski        allow_new.comment = pb_allow_new.comment();
43571be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski        entry->allow_new = std::move(allow_new);
43671be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski      }
43771be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski
43871be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski      if (pb_entry.has_overlayable()) {
43971be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski        const pb::Overlayable& pb_overlayable = pb_entry.overlayable();
44071be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski
44171be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski        Overlayable overlayable;
44271be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski        if (pb_overlayable.has_source()) {
44371be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski          DeserializeSourceFromPb(pb_overlayable.source(), src_pool, &overlayable.source);
44471be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski        }
44571be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski        overlayable.comment = pb_overlayable.comment();
44671be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski        entry->overlayable = std::move(overlayable);
44771be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski      }
44871be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski
4498cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      ResourceId resid(pb_package.package_id().id(), pb_type.type_id().id(),
4508cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                       pb_entry.entry_id().id());
4518cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      if (resid.is_valid()) {
4528cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        id_index[resid] = ResourceNameRef(pkg->name, type->type, entry->name);
4538cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      }
4548cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
4558cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      for (const pb::ConfigValue& pb_config_value : pb_entry.config_value()) {
4568cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        const pb::Configuration& pb_config = pb_config_value.config();
4578cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
4588cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        ConfigDescription config;
4598cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        if (!DeserializeConfigFromPb(pb_config, &config, out_error)) {
4608cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          return false;
4618cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        }
4628cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
4638cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        ResourceConfigValue* config_value = entry->FindOrCreateValue(config, pb_config.product());
4648cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        if (config_value->value != nullptr) {
4658cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          *out_error = "duplicate configuration in resource table";
4668cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          return false;
4678cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        }
4688cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
4698cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        config_value->value = DeserializeValueFromPb(pb_config_value.value(), src_pool, config,
4708780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski                                                     &out_table->string_pool, files, out_error);
4718cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        if (config_value->value == nullptr) {
4728cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          return false;
4738cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        }
4748cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      }
4758cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    }
4768cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
4778cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
4788cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  ReferenceIdToNameVisitor visitor(&id_index);
4798cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  VisitAllValuesInPackage(pkg, &visitor);
4808cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  return true;
4818cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski}
4828cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
4838780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinskibool DeserializeTableFromPb(const pb::ResourceTable& pb_table, io::IFileCollection* files,
4848780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski                            ResourceTable* out_table, std::string* out_error) {
4858cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  // We import the android namespace because on Windows NO_ERROR is a macro, not an enum, which
4868cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  // causes errors when qualifying it with android::
4878cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  using namespace android;
4888cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
4898cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  ResStringPool source_pool;
4908cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  if (pb_table.has_source_pool()) {
4918cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    status_t result = source_pool.setTo(pb_table.source_pool().data().data(),
4928cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                                        pb_table.source_pool().data().size());
4938cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    if (result != NO_ERROR) {
4948cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      *out_error = "invalid source pool";
4958cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      return false;
4968cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    }
4978cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
4988cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
4998cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  for (const pb::Package& pb_package : pb_table.package()) {
5008780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski    if (!DeserializePackageFromPb(pb_package, source_pool, files, out_table, out_error)) {
5018cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      return false;
5028cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    }
5038cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
5048cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  return true;
5058cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski}
5068cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
507e59f0d80ec19249f72c07ae191ad673d040443e3Adam Lesinskistatic ResourceFile::Type DeserializeFileReferenceTypeFromPb(const pb::FileReference::Type& type) {
508e59f0d80ec19249f72c07ae191ad673d040443e3Adam Lesinski  switch (type) {
509e59f0d80ec19249f72c07ae191ad673d040443e3Adam Lesinski    case pb::FileReference::BINARY_XML:
510004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski      return ResourceFile::Type::kBinaryXml;
511e59f0d80ec19249f72c07ae191ad673d040443e3Adam Lesinski    case pb::FileReference::PROTO_XML:
512004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski      return ResourceFile::Type::kProtoXml;
513e59f0d80ec19249f72c07ae191ad673d040443e3Adam Lesinski    case pb::FileReference::PNG:
514e59f0d80ec19249f72c07ae191ad673d040443e3Adam Lesinski      return ResourceFile::Type::kPng;
515004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    default:
516004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski      return ResourceFile::Type::kUnknown;
517004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  }
518004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski}
519004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
5208cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinskibool DeserializeCompiledFileFromPb(const pb::internal::CompiledFile& pb_file,
5218cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                                   ResourceFile* out_file, std::string* out_error) {
5228cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  ResourceNameRef name_ref;
5238cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  if (!ResourceUtils::ParseResourceName(pb_file.resource_name(), &name_ref)) {
5248cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    std::ostringstream error;
5258cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    error << "invalid resource name in compiled file header: " << pb_file.resource_name();
5268cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    *out_error = error.str();
5278cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    return false;
5288cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
5298cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
5308cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  out_file->name = name_ref.ToResourceName();
5318cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  out_file->source.path = pb_file.source_path();
532e59f0d80ec19249f72c07ae191ad673d040443e3Adam Lesinski  out_file->type = DeserializeFileReferenceTypeFromPb(pb_file.type());
5338cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
5348cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  std::string config_error;
5358cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  if (!DeserializeConfigFromPb(pb_file.config(), &out_file->config, &config_error)) {
5368cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    std::ostringstream error;
5378cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    error << "invalid resource configuration in compiled file header: " << config_error;
5388cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    *out_error = error.str();
5398cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    return false;
5408cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
5418cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
5428cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  for (const pb::internal::CompiledFile_Symbol& pb_symbol : pb_file.exported_symbol()) {
5438cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    if (!ResourceUtils::ParseResourceName(pb_symbol.resource_name(), &name_ref)) {
5448cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      std::ostringstream error;
5458cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      error << "invalid resource name for exported symbol in compiled file header: "
5468cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski            << pb_file.resource_name();
5478cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      *out_error = error.str();
5488cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      return false;
5498cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    }
5508cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
5518cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    size_t line = 0u;
5528cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    if (pb_symbol.has_source()) {
5538cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      line = pb_symbol.source().line_number();
5548cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    }
5558cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    out_file->exported_symbols.push_back(SourcedResourceName{name_ref.ToResourceName(), line});
5568cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
5578cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  return true;
5588cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski}
5598cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
5608cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinskistatic Reference::Type DeserializeReferenceTypeFromPb(const pb::Reference_Type& pb_type) {
5618cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  switch (pb_type) {
5628cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Reference_Type_REFERENCE:
5638cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      return Reference::Type::kResource;
5648cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Reference_Type_ATTRIBUTE:
5658cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      return Reference::Type::kAttribute;
5668cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    default:
5678cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
5688cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
5698cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  return Reference::Type::kResource;
5708cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski}
5718cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
5728cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinskistatic bool DeserializeReferenceFromPb(const pb::Reference& pb_ref, Reference* out_ref,
5738cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                                       std::string* out_error) {
5748cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  out_ref->reference_type = DeserializeReferenceTypeFromPb(pb_ref.type());
5758cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  out_ref->private_reference = pb_ref.private_();
5768cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
5778cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  if (pb_ref.id() != 0) {
5788cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    out_ref->id = ResourceId(pb_ref.id());
5798cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
5808cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
5818cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  if (!pb_ref.name().empty()) {
5828cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    ResourceNameRef name_ref;
5838cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    if (!ResourceUtils::ParseResourceName(pb_ref.name(), &name_ref, nullptr)) {
5848cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      std::ostringstream error;
5858cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      error << "reference has invalid resource name '" << pb_ref.name() << "'";
5868cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      *out_error = error.str();
5878cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      return false;
5888cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    }
5898cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    out_ref->name = name_ref.ToResourceName();
5908cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
5918cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  return true;
5928cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski}
5938cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
5948cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinskitemplate <typename T>
5958cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinskistatic void DeserializeItemMetaDataFromPb(const T& pb_item, const android::ResStringPool& src_pool,
5968cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                                          Value* out_value) {
5978cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  if (pb_item.has_source()) {
5988cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    Source source;
5998cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    DeserializeSourceFromPb(pb_item.source(), src_pool, &source);
6008cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    out_value->SetSource(std::move(source));
6018cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
6028cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  out_value->SetComment(pb_item.comment());
6038cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski}
6048cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
6058cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinskistatic size_t DeserializePluralEnumFromPb(const pb::Plural_Arity& arity) {
6068cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  switch (arity) {
6078cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Plural_Arity_ZERO:
6088cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      return Plural::Zero;
6098cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Plural_Arity_ONE:
6108cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      return Plural::One;
6118cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Plural_Arity_TWO:
6128cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      return Plural::Two;
6138cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Plural_Arity_FEW:
6148cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      return Plural::Few;
6158cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Plural_Arity_MANY:
6168cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      return Plural::Many;
6178cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    default:
6188cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
6198cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
6208cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  return Plural::Other;
6218cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski}
6228cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
6238cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinskistd::unique_ptr<Value> DeserializeValueFromPb(const pb::Value& pb_value,
6248cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                                              const android::ResStringPool& src_pool,
6258cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                                              const ConfigDescription& config,
6268780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski                                              StringPool* value_pool, io::IFileCollection* files,
6278780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski                                              std::string* out_error) {
6288cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  std::unique_ptr<Value> value;
6298cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  if (pb_value.has_item()) {
6308780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski    value = DeserializeItemFromPb(pb_value.item(), src_pool, config, value_pool, files, out_error);
6318cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    if (value == nullptr) {
6328cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      return {};
6338cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    }
6348cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
6358cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  } else if (pb_value.has_compound_value()) {
6368cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    const pb::CompoundValue& pb_compound_value = pb_value.compound_value();
6378cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    switch (pb_compound_value.value_case()) {
6388cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      case pb::CompoundValue::kAttr: {
6398cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        const pb::Attribute& pb_attr = pb_compound_value.attr();
64073bff1e8519bb73f17a801f45977d41b69b5b0d0Adam Lesinski        std::unique_ptr<Attribute> attr = util::make_unique<Attribute>(pb_attr.format_flags());
6418cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        attr->min_int = pb_attr.min_int();
6428cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        attr->max_int = pb_attr.max_int();
6438cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        for (const pb::Attribute_Symbol& pb_symbol : pb_attr.symbol()) {
6448cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          Attribute::Symbol symbol;
6458cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          DeserializeItemMetaDataFromPb(pb_symbol, src_pool, &symbol.symbol);
6468cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          if (!DeserializeReferenceFromPb(pb_symbol.name(), &symbol.symbol, out_error)) {
6478cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski            return {};
6488cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          }
6498cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          symbol.value = pb_symbol.value();
6508cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          attr->symbols.push_back(std::move(symbol));
6518cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        }
6528cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        value = std::move(attr);
6538cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      } break;
6548cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
6558cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      case pb::CompoundValue::kStyle: {
6568cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        const pb::Style& pb_style = pb_compound_value.style();
6578cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        std::unique_ptr<Style> style = util::make_unique<Style>();
6588cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        if (pb_style.has_parent()) {
6598cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          style->parent = Reference();
6608cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          if (!DeserializeReferenceFromPb(pb_style.parent(), &style->parent.value(), out_error)) {
6618cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski            return {};
6628cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          }
6638cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
6648cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          if (pb_style.has_parent_source()) {
6658cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski            Source parent_source;
6668cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski            DeserializeSourceFromPb(pb_style.parent_source(), src_pool, &parent_source);
6678cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski            style->parent.value().SetSource(std::move(parent_source));
6688cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          }
6698cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        }
6708cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
6718cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        for (const pb::Style_Entry& pb_entry : pb_style.entry()) {
6728cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          Style::Entry entry;
6738cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          if (!DeserializeReferenceFromPb(pb_entry.key(), &entry.key, out_error)) {
6748cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski            return {};
6758cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          }
6768cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          DeserializeItemMetaDataFromPb(pb_entry, src_pool, &entry.key);
6778780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski          entry.value = DeserializeItemFromPb(pb_entry.item(), src_pool, config, value_pool, files,
6788780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski                                              out_error);
6798cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          if (entry.value == nullptr) {
6808cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski            return {};
6818cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          }
6828cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
6838cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          // Copy the meta-data into the value as well.
6848cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          DeserializeItemMetaDataFromPb(pb_entry, src_pool, entry.value.get());
6858cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          style->entries.push_back(std::move(entry));
6868cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        }
6878cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        value = std::move(style);
6888cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      } break;
6898cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
6908cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      case pb::CompoundValue::kStyleable: {
6918cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        const pb::Styleable& pb_styleable = pb_compound_value.styleable();
6928cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        std::unique_ptr<Styleable> styleable = util::make_unique<Styleable>();
6938cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        for (const pb::Styleable_Entry& pb_entry : pb_styleable.entry()) {
6948cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          Reference attr_ref;
6958cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          DeserializeItemMetaDataFromPb(pb_entry, src_pool, &attr_ref);
6968cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          DeserializeReferenceFromPb(pb_entry.attr(), &attr_ref, out_error);
6978cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          styleable->entries.push_back(std::move(attr_ref));
6988cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        }
6998cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        value = std::move(styleable);
7008cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      } break;
7018cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
7028cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      case pb::CompoundValue::kArray: {
7038cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        const pb::Array& pb_array = pb_compound_value.array();
7048cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        std::unique_ptr<Array> array = util::make_unique<Array>();
7058cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        for (const pb::Array_Element& pb_entry : pb_array.element()) {
7068780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski          std::unique_ptr<Item> item = DeserializeItemFromPb(pb_entry.item(), src_pool, config,
7078780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski                                                             value_pool, files, out_error);
7088cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          if (item == nullptr) {
7098cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski            return {};
7108cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          }
7118cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
7128cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          DeserializeItemMetaDataFromPb(pb_entry, src_pool, item.get());
7138cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          array->elements.push_back(std::move(item));
7148cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        }
7158cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        value = std::move(array);
7168cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      } break;
7178cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
7188cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      case pb::CompoundValue::kPlural: {
7198cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        const pb::Plural& pb_plural = pb_compound_value.plural();
7208cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        std::unique_ptr<Plural> plural = util::make_unique<Plural>();
7218cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        for (const pb::Plural_Entry& pb_entry : pb_plural.entry()) {
7228cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          size_t plural_idx = DeserializePluralEnumFromPb(pb_entry.arity());
7238780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski          plural->values[plural_idx] = DeserializeItemFromPb(pb_entry.item(), src_pool, config,
7248780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski                                                             value_pool, files, out_error);
7258cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          if (!plural->values[plural_idx]) {
7268cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski            return {};
7278cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          }
7288cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
7298cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          DeserializeItemMetaDataFromPb(pb_entry, src_pool, plural->values[plural_idx].get());
7308cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        }
7318cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        value = std::move(plural);
7328cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      } break;
7338cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
7348cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      default:
7354670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski        LOG(FATAL) << "unknown compound value: " << (int)pb_compound_value.value_case();
7368cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        break;
7378cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    }
7388cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  } else {
7394670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski    LOG(FATAL) << "unknown value: " << (int)pb_value.value_case();
7408cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    return {};
7418cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
7428cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
7438cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  CHECK(value) << "forgot to set value";
7448cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
7458cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  value->SetWeak(pb_value.weak());
7468cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  DeserializeItemMetaDataFromPb(pb_value, src_pool, value.get());
7478cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  return value;
7488cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski}
7498cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
7508cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinskistd::unique_ptr<Item> DeserializeItemFromPb(const pb::Item& pb_item,
7518cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                                            const android::ResStringPool& src_pool,
7528cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                                            const ConfigDescription& config, StringPool* value_pool,
7538780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski                                            io::IFileCollection* files, std::string* out_error) {
7548cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  switch (pb_item.value_case()) {
7558cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Item::kRef: {
7568cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      const pb::Reference& pb_ref = pb_item.ref();
7578cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      std::unique_ptr<Reference> ref = util::make_unique<Reference>();
7588cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      if (!DeserializeReferenceFromPb(pb_ref, ref.get(), out_error)) {
7598cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        return {};
7608cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      }
7618cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      return std::move(ref);
7628cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    } break;
7638cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
7648cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Item::kPrim: {
7658cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      const pb::Primitive& pb_prim = pb_item.prim();
766d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz      android::Res_value val = {};
767d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz      switch (pb_prim.oneof_value_case()) {
768d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz        case pb::Primitive::kNullValue: {
769d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz          val.dataType = android::Res_value::TYPE_NULL;
770d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz          val.data = android::Res_value::DATA_NULL_UNDEFINED;
771d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz        } break;
772d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz        case pb::Primitive::kEmptyValue: {
773d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz          val.dataType = android::Res_value::TYPE_NULL;
774d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz          val.data = android::Res_value::DATA_NULL_EMPTY;
775d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz        } break;
776d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz        case pb::Primitive::kFloatValue: {
777d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz          val.dataType = android::Res_value::TYPE_FLOAT;
778d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz          float float_val = pb_prim.float_value();
779d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz          val.data = *(uint32_t*)&float_val;
780d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz        } break;
781d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz        case pb::Primitive::kDimensionValue: {
782d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz          val.dataType = android::Res_value::TYPE_DIMENSION;
7838b74927e9ecf4d14898d09c168d0d38f164a92bcMichael Wachenschwanz          val.data  = pb_prim.dimension_value();
784d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz        } break;
785d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz        case pb::Primitive::kFractionValue: {
786d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz          val.dataType = android::Res_value::TYPE_FRACTION;
7878b74927e9ecf4d14898d09c168d0d38f164a92bcMichael Wachenschwanz          val.data  = pb_prim.fraction_value();
788d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz        } break;
789d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz        case pb::Primitive::kIntDecimalValue: {
790d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz          val.dataType = android::Res_value::TYPE_INT_DEC;
791d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz          val.data = static_cast<uint32_t>(pb_prim.int_decimal_value());
792d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz        } break;
79322ed4122e7849a4538208c65f403298fe0fff891Dave Ingram        case pb::Primitive::kIntHexadecimalValue: {
794d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz          val.dataType = android::Res_value::TYPE_INT_HEX;
79522ed4122e7849a4538208c65f403298fe0fff891Dave Ingram          val.data = pb_prim.int_hexadecimal_value();
796d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz        } break;
797d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz        case pb::Primitive::kBooleanValue: {
798d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz          val.dataType = android::Res_value::TYPE_INT_BOOLEAN;
799d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz          val.data = pb_prim.boolean_value() ? 0xFFFFFFFF : 0x0;
800d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz        } break;
801d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz        case pb::Primitive::kColorArgb8Value: {
802d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz          val.dataType = android::Res_value::TYPE_INT_COLOR_ARGB8;
803d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz          val.data = pb_prim.color_argb8_value();
804d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz        } break;
805d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz        case pb::Primitive::kColorRgb8Value: {
806d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz          val.dataType = android::Res_value::TYPE_INT_COLOR_RGB8;
807d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz          val.data = pb_prim.color_rgb8_value();
808d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz        } break;
809d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz        case pb::Primitive::kColorArgb4Value: {
810d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz          val.dataType = android::Res_value::TYPE_INT_COLOR_ARGB4;
811d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz          val.data = pb_prim.color_argb4_value();
812d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz        } break;
813d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz        case pb::Primitive::kColorRgb4Value: {
814d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz          val.dataType = android::Res_value::TYPE_INT_COLOR_RGB4;
815d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz          val.data = pb_prim.color_rgb4_value();
816d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz        } break;
8178b74927e9ecf4d14898d09c168d0d38f164a92bcMichael Wachenschwanz        case pb::Primitive::kDimensionValueDeprecated: {  // DEPRECATED
8188b74927e9ecf4d14898d09c168d0d38f164a92bcMichael Wachenschwanz          val.dataType = android::Res_value::TYPE_DIMENSION;
8198b74927e9ecf4d14898d09c168d0d38f164a92bcMichael Wachenschwanz          float dimen_val = pb_prim.dimension_value_deprecated();
8208b74927e9ecf4d14898d09c168d0d38f164a92bcMichael Wachenschwanz          val.data = *(uint32_t*)&dimen_val;
8218b74927e9ecf4d14898d09c168d0d38f164a92bcMichael Wachenschwanz        } break;
8228b74927e9ecf4d14898d09c168d0d38f164a92bcMichael Wachenschwanz        case pb::Primitive::kFractionValueDeprecated: {  // DEPRECATED
8238b74927e9ecf4d14898d09c168d0d38f164a92bcMichael Wachenschwanz          val.dataType = android::Res_value::TYPE_FRACTION;
8248b74927e9ecf4d14898d09c168d0d38f164a92bcMichael Wachenschwanz          float fraction_val = pb_prim.fraction_value_deprecated();
8258b74927e9ecf4d14898d09c168d0d38f164a92bcMichael Wachenschwanz          val.data = *(uint32_t*)&fraction_val;
8268b74927e9ecf4d14898d09c168d0d38f164a92bcMichael Wachenschwanz        } break;
827d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz        default: {
828d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz          LOG(FATAL) << "Unexpected Primitive type: "
829d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz                     << static_cast<uint32_t>(pb_prim.oneof_value_case());
830d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz          return {};
831d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz        } break;
832d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz      }
833d06f1f38a9266f4674a89d69d33198abd12b0e78Michael Wachenschwanz      return util::make_unique<BinaryPrimitive>(val);
8348cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    } break;
8358cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
8368cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Item::kId: {
8378cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      return util::make_unique<Id>();
8388cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    } break;
8398cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
8408cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Item::kStr: {
8418cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      return util::make_unique<String>(
8428cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          value_pool->MakeRef(pb_item.str().value(), StringPool::Context(config)));
8438cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    } break;
8448cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
8458cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Item::kRawStr: {
8468cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      return util::make_unique<RawString>(
8478cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          value_pool->MakeRef(pb_item.raw_str().value(), StringPool::Context(config)));
8488cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    } break;
8498cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
8508cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Item::kStyledStr: {
8518cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      const pb::StyledString& pb_str = pb_item.styled_str();
8528cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      StyleString style_str{pb_str.value()};
8538cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      for (const pb::StyledString::Span& pb_span : pb_str.span()) {
8548cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        style_str.spans.push_back(Span{pb_span.tag(), pb_span.first_char(), pb_span.last_char()});
8558cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      }
8568cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      return util::make_unique<StyledString>(value_pool->MakeRef(
8578cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          style_str, StringPool::Context(StringPool::Context::kNormalPriority, config)));
8588cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    } break;
8598cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
8608cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    case pb::Item::kFile: {
861e59f0d80ec19249f72c07ae191ad673d040443e3Adam Lesinski      const pb::FileReference& pb_file = pb_item.file();
862e59f0d80ec19249f72c07ae191ad673d040443e3Adam Lesinski      std::unique_ptr<FileReference> file_ref =
863e59f0d80ec19249f72c07ae191ad673d040443e3Adam Lesinski          util::make_unique<FileReference>(value_pool->MakeRef(
864e59f0d80ec19249f72c07ae191ad673d040443e3Adam Lesinski              pb_file.path(), StringPool::Context(StringPool::Context::kHighPriority, config)));
865e59f0d80ec19249f72c07ae191ad673d040443e3Adam Lesinski      file_ref->type = DeserializeFileReferenceTypeFromPb(pb_file.type());
8668780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski      if (files != nullptr) {
8678780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski        file_ref->file = files->FindFile(*file_ref->path);
8688780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski      }
869e59f0d80ec19249f72c07ae191ad673d040443e3Adam Lesinski      return std::move(file_ref);
8708cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    } break;
8718cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
8728cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    default:
8734670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski      LOG(FATAL) << "unknown item: " << (int)pb_item.value_case();
8748cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      break;
8758cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
8768cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  return {};
8778cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski}
8788cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
8798cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinskistd::unique_ptr<xml::XmlResource> DeserializeXmlResourceFromPb(const pb::XmlNode& pb_node,
8808cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                                                               std::string* out_error) {
8818cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  if (!pb_node.has_element()) {
8828cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    return {};
8838cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
8848cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
8858cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  std::unique_ptr<xml::XmlResource> resource = util::make_unique<xml::XmlResource>();
8868cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  resource->root = util::make_unique<xml::Element>();
8878cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  if (!DeserializeXmlFromPb(pb_node, resource->root.get(), &resource->string_pool, out_error)) {
8888cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    return {};
8898cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
8908cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  return resource;
8918cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski}
8928cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
8938cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinskibool DeserializeXmlFromPb(const pb::XmlNode& pb_node, xml::Element* out_el, StringPool* value_pool,
8948cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                          std::string* out_error) {
8958cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  const pb::XmlElement& pb_el = pb_node.element();
8968cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  out_el->name = pb_el.name();
8978cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  out_el->namespace_uri = pb_el.namespace_uri();
8988cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  out_el->line_number = pb_node.source().line_number();
8998cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  out_el->column_number = pb_node.source().column_number();
9008cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
9018cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  for (const pb::XmlNamespace& pb_ns : pb_el.namespace_declaration()) {
9028cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    xml::NamespaceDecl decl;
9038cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    decl.uri = pb_ns.uri();
9048cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    decl.prefix = pb_ns.prefix();
9058cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    decl.line_number = pb_ns.source().line_number();
9068cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    decl.column_number = pb_ns.source().column_number();
9078cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    out_el->namespace_decls.push_back(std::move(decl));
9088cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
9098cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
9108cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  for (const pb::XmlAttribute& pb_attr : pb_el.attribute()) {
9118cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    xml::Attribute attr;
9128cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    attr.name = pb_attr.name();
9138cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    attr.namespace_uri = pb_attr.namespace_uri();
9148cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    attr.value = pb_attr.value();
9158cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    if (pb_attr.resource_id() != 0u) {
9168cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      attr.compiled_attribute = xml::AaptAttribute{Attribute(), ResourceId(pb_attr.resource_id())};
9178cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    }
9188cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    if (pb_attr.has_compiled_item()) {
9198cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      attr.compiled_value =
9208780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski          DeserializeItemFromPb(pb_attr.compiled_item(), {}, {}, value_pool, nullptr, out_error);
9218cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      if (attr.compiled_value == nullptr) {
9228cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        return {};
9238cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      }
9248cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      attr.compiled_value->SetSource(Source().WithLine(pb_attr.source().line_number()));
9258cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    }
9268cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    out_el->attributes.push_back(std::move(attr));
9278cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
9288cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
9298cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  // Deserialize the children.
9308cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  for (const pb::XmlNode& pb_child : pb_el.child()) {
9318cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    switch (pb_child.node_case()) {
9328cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      case pb::XmlNode::NodeCase::kText: {
9338cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        std::unique_ptr<xml::Text> text = util::make_unique<xml::Text>();
9348cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        text->line_number = pb_child.source().line_number();
9358cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        text->column_number = pb_child.source().column_number();
9368cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        text->text = pb_child.text();
9378cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        out_el->AppendChild(std::move(text));
9388cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      } break;
9398cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
9408cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      case pb::XmlNode::NodeCase::kElement: {
9418cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        std::unique_ptr<xml::Element> child_el = util::make_unique<xml::Element>();
9428cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        if (!DeserializeXmlFromPb(pb_child, child_el.get(), value_pool, out_error)) {
9438cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski          return false;
9448cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        }
9458cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        out_el->AppendChild(std::move(child_el));
9468cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      } break;
9478cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
9488cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      default:
9494670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski        LOG(FATAL) << "unknown XmlNode " << (int)pb_child.node_case();
9508cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        break;
9518cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    }
9528cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
9538cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  return true;
9548cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski}
9558cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
9568cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski}  // namespace aapt
957