AAPT2: Convert binary ResTable_config to proto

Test: make aapt2_tests
Change-Id: I8641f13ce41cd58ac8bc3da31c4e15a7b3f06092
diff --git a/tools/aapt2/proto/ProtoHelpers.cpp b/tools/aapt2/proto/ProtoHelpers.cpp
index 59ca8e4..18f7e1d 100644
--- a/tools/aapt2/proto/ProtoHelpers.cpp
+++ b/tools/aapt2/proto/ProtoHelpers.cpp
@@ -16,6 +16,8 @@
 
 #include "proto/ProtoHelpers.h"
 
+#include "Locale.h"
+
 namespace aapt {
 
 void SerializeStringPoolToPb(const StringPool& pool, pb::StringPool* out_pb_pool) {
@@ -70,27 +72,507 @@
   return SymbolState::kUndefined;
 }
 
-void SerializeConfig(const ConfigDescription& config, pb::ConfigDescription* out_pb_config) {
-  android::ResTable_config flat_config = config;
-  flat_config.size = sizeof(flat_config);
-  flat_config.swapHtoD();
-  out_pb_config->set_data(&flat_config, sizeof(flat_config));
+void SerializeConfig(const ConfigDescription& config, pb::Configuration* out_pb_config) {
+  out_pb_config->set_mcc(config.mcc);
+  out_pb_config->set_mnc(config.mnc);
+  out_pb_config->set_locale(config.GetBcp47LanguageTag());
+
+  switch (config.screenLayout & ConfigDescription::MASK_LAYOUTDIR) {
+    case ConfigDescription::LAYOUTDIR_LTR:
+      out_pb_config->set_layout_direction(pb::Configuration_LayoutDirection_LAYOUT_DIRECTION_LTR);
+      break;
+
+    case ConfigDescription::LAYOUTDIR_RTL:
+      out_pb_config->set_layout_direction(pb::Configuration_LayoutDirection_LAYOUT_DIRECTION_RTL);
+      break;
+  }
+
+  out_pb_config->set_screen_width(config.screenWidth);
+  out_pb_config->set_screen_height(config.screenHeight);
+  out_pb_config->set_screen_width_dp(config.screenWidthDp);
+  out_pb_config->set_screen_height_dp(config.screenHeightDp);
+  out_pb_config->set_smallest_screen_width_dp(config.smallestScreenWidthDp);
+
+  switch (config.screenLayout & ConfigDescription::MASK_SCREENSIZE) {
+    case ConfigDescription::SCREENSIZE_SMALL:
+      out_pb_config->set_screen_layout_size(
+          pb::Configuration_ScreenLayoutSize_SCREEN_LAYOUT_SIZE_SMALL);
+      break;
+
+    case ConfigDescription::SCREENSIZE_NORMAL:
+      out_pb_config->set_screen_layout_size(
+          pb::Configuration_ScreenLayoutSize_SCREEN_LAYOUT_SIZE_NORMAL);
+      break;
+
+    case ConfigDescription::SCREENSIZE_LARGE:
+      out_pb_config->set_screen_layout_size(
+          pb::Configuration_ScreenLayoutSize_SCREEN_LAYOUT_SIZE_LARGE);
+      break;
+
+    case ConfigDescription::SCREENSIZE_XLARGE:
+      out_pb_config->set_screen_layout_size(
+          pb::Configuration_ScreenLayoutSize_SCREEN_LAYOUT_SIZE_XLARGE);
+      break;
+  }
+
+  switch (config.screenLayout & ConfigDescription::MASK_SCREENLONG) {
+    case ConfigDescription::SCREENLONG_YES:
+      out_pb_config->set_screen_layout_long(
+          pb::Configuration_ScreenLayoutLong_SCREEN_LAYOUT_LONG_LONG);
+      break;
+
+    case ConfigDescription::SCREENLONG_NO:
+      out_pb_config->set_screen_layout_long(
+          pb::Configuration_ScreenLayoutLong_SCREEN_LAYOUT_LONG_NOTLONG);
+      break;
+  }
+
+  switch (config.screenLayout2 & ConfigDescription::MASK_SCREENROUND) {
+    case ConfigDescription::SCREENROUND_YES:
+      out_pb_config->set_screen_round(pb::Configuration_ScreenRound_SCREEN_ROUND_ROUND);
+      break;
+
+    case ConfigDescription::SCREENROUND_NO:
+      out_pb_config->set_screen_round(pb::Configuration_ScreenRound_SCREEN_ROUND_NOTROUND);
+      break;
+  }
+
+  switch (config.colorMode & ConfigDescription::MASK_WIDE_COLOR_GAMUT) {
+    case ConfigDescription::WIDE_COLOR_GAMUT_YES:
+      out_pb_config->set_wide_color_gamut(pb::Configuration_WideColorGamut_WIDE_COLOR_GAMUT_WIDECG);
+      break;
+
+    case ConfigDescription::WIDE_COLOR_GAMUT_NO:
+      out_pb_config->set_wide_color_gamut(
+          pb::Configuration_WideColorGamut_WIDE_COLOR_GAMUT_NOWIDECG);
+      break;
+  }
+
+  switch (config.colorMode & ConfigDescription::MASK_HDR) {
+    case ConfigDescription::HDR_YES:
+      out_pb_config->set_hdr(pb::Configuration_Hdr_HDR_HIGHDR);
+      break;
+
+    case ConfigDescription::HDR_NO:
+      out_pb_config->set_hdr(pb::Configuration_Hdr_HDR_LOWDR);
+      break;
+  }
+
+  switch (config.orientation) {
+    case ConfigDescription::ORIENTATION_PORT:
+      out_pb_config->set_orientation(pb::Configuration_Orientation_ORIENTATION_PORT);
+      break;
+
+    case ConfigDescription::ORIENTATION_LAND:
+      out_pb_config->set_orientation(pb::Configuration_Orientation_ORIENTATION_LAND);
+      break;
+
+    case ConfigDescription::ORIENTATION_SQUARE:
+      out_pb_config->set_orientation(pb::Configuration_Orientation_ORIENTATION_SQUARE);
+      break;
+  }
+
+  switch (config.uiMode & ConfigDescription::MASK_UI_MODE_TYPE) {
+    case ConfigDescription::UI_MODE_TYPE_NORMAL:
+      out_pb_config->set_ui_mode_type(pb::Configuration_UiModeType_UI_MODE_TYPE_NORMAL);
+      break;
+
+    case ConfigDescription::UI_MODE_TYPE_DESK:
+      out_pb_config->set_ui_mode_type(pb::Configuration_UiModeType_UI_MODE_TYPE_DESK);
+      break;
+
+    case ConfigDescription::UI_MODE_TYPE_CAR:
+      out_pb_config->set_ui_mode_type(pb::Configuration_UiModeType_UI_MODE_TYPE_CAR);
+      break;
+
+    case ConfigDescription::UI_MODE_TYPE_TELEVISION:
+      out_pb_config->set_ui_mode_type(pb::Configuration_UiModeType_UI_MODE_TYPE_TELEVISION);
+      break;
+
+    case ConfigDescription::UI_MODE_TYPE_APPLIANCE:
+      out_pb_config->set_ui_mode_type(pb::Configuration_UiModeType_UI_MODE_TYPE_APPLIANCE);
+      break;
+
+    case ConfigDescription::UI_MODE_TYPE_WATCH:
+      out_pb_config->set_ui_mode_type(pb::Configuration_UiModeType_UI_MODE_TYPE_WATCH);
+      break;
+
+    case ConfigDescription::UI_MODE_TYPE_VR_HEADSET:
+      out_pb_config->set_ui_mode_type(pb::Configuration_UiModeType_UI_MODE_TYPE_VRHEADSET);
+      break;
+  }
+
+  switch (config.uiMode & ConfigDescription::MASK_UI_MODE_NIGHT) {
+    case ConfigDescription::UI_MODE_NIGHT_YES:
+      out_pb_config->set_ui_mode_night(pb::Configuration_UiModeNight_UI_MODE_NIGHT_NIGHT);
+      break;
+
+    case ConfigDescription::UI_MODE_NIGHT_NO:
+      out_pb_config->set_ui_mode_night(pb::Configuration_UiModeNight_UI_MODE_NIGHT_NOTNIGHT);
+      break;
+  }
+
+  out_pb_config->set_density(config.density);
+
+  switch (config.touchscreen) {
+    case ConfigDescription::TOUCHSCREEN_NOTOUCH:
+      out_pb_config->set_touchscreen(pb::Configuration_Touchscreen_TOUCHSCREEN_NOTOUCH);
+      break;
+
+    case ConfigDescription::TOUCHSCREEN_STYLUS:
+      out_pb_config->set_touchscreen(pb::Configuration_Touchscreen_TOUCHSCREEN_STYLUS);
+      break;
+
+    case ConfigDescription::TOUCHSCREEN_FINGER:
+      out_pb_config->set_touchscreen(pb::Configuration_Touchscreen_TOUCHSCREEN_FINGER);
+      break;
+  }
+
+  switch (config.inputFlags & ConfigDescription::MASK_KEYSHIDDEN) {
+    case ConfigDescription::KEYSHIDDEN_NO:
+      out_pb_config->set_keys_hidden(pb::Configuration_KeysHidden_KEYS_HIDDEN_KEYSEXPOSED);
+      break;
+
+    case ConfigDescription::KEYSHIDDEN_YES:
+      out_pb_config->set_keys_hidden(pb::Configuration_KeysHidden_KEYS_HIDDEN_KEYSHIDDEN);
+      break;
+
+    case ConfigDescription::KEYSHIDDEN_SOFT:
+      out_pb_config->set_keys_hidden(pb::Configuration_KeysHidden_KEYS_HIDDEN_KEYSSOFT);
+      break;
+  }
+
+  switch (config.keyboard) {
+    case ConfigDescription::KEYBOARD_NOKEYS:
+      out_pb_config->set_keyboard(pb::Configuration_Keyboard_KEYBOARD_NOKEYS);
+      break;
+
+    case ConfigDescription::KEYBOARD_QWERTY:
+      out_pb_config->set_keyboard(pb::Configuration_Keyboard_KEYBOARD_QWERTY);
+      break;
+
+    case ConfigDescription::KEYBOARD_12KEY:
+      out_pb_config->set_keyboard(pb::Configuration_Keyboard_KEYBOARD_TWELVEKEY);
+      break;
+  }
+
+  switch (config.inputFlags & ConfigDescription::MASK_NAVHIDDEN) {
+    case ConfigDescription::NAVHIDDEN_NO:
+      out_pb_config->set_nav_hidden(pb::Configuration_NavHidden_NAV_HIDDEN_NAVEXPOSED);
+      break;
+
+    case ConfigDescription::NAVHIDDEN_YES:
+      out_pb_config->set_nav_hidden(pb::Configuration_NavHidden_NAV_HIDDEN_NAVHIDDEN);
+      break;
+  }
+
+  switch (config.navigation) {
+    case ConfigDescription::NAVIGATION_NONAV:
+      out_pb_config->set_navigation(pb::Configuration_Navigation_NAVIGATION_NONAV);
+      break;
+
+    case ConfigDescription::NAVIGATION_DPAD:
+      out_pb_config->set_navigation(pb::Configuration_Navigation_NAVIGATION_DPAD);
+      break;
+
+    case ConfigDescription::NAVIGATION_TRACKBALL:
+      out_pb_config->set_navigation(pb::Configuration_Navigation_NAVIGATION_TRACKBALL);
+      break;
+
+    case ConfigDescription::NAVIGATION_WHEEL:
+      out_pb_config->set_navigation(pb::Configuration_Navigation_NAVIGATION_WHEEL);
+      break;
+  }
+
+  out_pb_config->set_sdk_version(config.sdkVersion);
 }
 
-bool DeserializeConfigDescriptionFromPb(const pb::ConfigDescription& pb_config,
+bool DeserializeConfigDescriptionFromPb(const pb::Configuration& pb_config,
                                         ConfigDescription* out_config) {
-  // a ConfigDescription must be at least 4 bytes to store the size.
-  if (pb_config.data().size() < 4) {
-    return false;
+  out_config->mcc = static_cast<uint16_t>(pb_config.mcc());
+  out_config->mnc = static_cast<uint16_t>(pb_config.mnc());
+
+  if (!pb_config.locale().empty()) {
+    LocaleValue lv;
+    if (!lv.InitFromBcp47Tag(pb_config.locale())) {
+      return false;
+    }
+    lv.WriteTo(out_config);
   }
 
-  const android::ResTable_config* config;
-  if (pb_config.data().size() > sizeof(*config)) {
-    return false;
+  switch (pb_config.layout_direction()) {
+    case pb::Configuration_LayoutDirection_LAYOUT_DIRECTION_LTR:
+      out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_LAYOUTDIR) |
+                                 ConfigDescription::LAYOUTDIR_LTR;
+      break;
+
+    case pb::Configuration_LayoutDirection_LAYOUT_DIRECTION_RTL:
+      out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_LAYOUTDIR) |
+                                 ConfigDescription::LAYOUTDIR_RTL;
+      break;
+
+    default:
+      break;
   }
 
-  config = reinterpret_cast<const android::ResTable_config*>(pb_config.data().data());
-  out_config->copyFromDtoH(*config);
+  out_config->smallestScreenWidthDp = static_cast<uint16_t>(pb_config.smallest_screen_width_dp());
+  out_config->screenWidthDp = static_cast<uint16_t>(pb_config.screen_width_dp());
+  out_config->screenHeightDp = static_cast<uint16_t>(pb_config.screen_height_dp());
+
+  switch (pb_config.screen_layout_size()) {
+    case pb::Configuration_ScreenLayoutSize_SCREEN_LAYOUT_SIZE_SMALL:
+      out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_SCREENSIZE) |
+                                 ConfigDescription::SCREENSIZE_SMALL;
+      break;
+
+    case pb::Configuration_ScreenLayoutSize_SCREEN_LAYOUT_SIZE_NORMAL:
+      out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_SCREENSIZE) |
+                                 ConfigDescription::SCREENSIZE_NORMAL;
+      break;
+
+    case pb::Configuration_ScreenLayoutSize_SCREEN_LAYOUT_SIZE_LARGE:
+      out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_SCREENSIZE) |
+                                 ConfigDescription::SCREENSIZE_LARGE;
+      break;
+
+    case pb::Configuration_ScreenLayoutSize_SCREEN_LAYOUT_SIZE_XLARGE:
+      out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_SCREENSIZE) |
+                                 ConfigDescription::SCREENSIZE_XLARGE;
+      break;
+
+    default:
+      break;
+  }
+
+  switch (pb_config.screen_layout_long()) {
+    case pb::Configuration_ScreenLayoutLong_SCREEN_LAYOUT_LONG_LONG:
+      out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_SCREENLONG) |
+                                 ConfigDescription::SCREENLONG_YES;
+      break;
+
+    case pb::Configuration_ScreenLayoutLong_SCREEN_LAYOUT_LONG_NOTLONG:
+      out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_SCREENLONG) |
+                                 ConfigDescription::SCREENLONG_NO;
+      break;
+
+    default:
+      break;
+  }
+
+  switch (pb_config.screen_round()) {
+    case pb::Configuration_ScreenRound_SCREEN_ROUND_ROUND:
+      out_config->screenLayout2 =
+          (out_config->screenLayout2 & ~ConfigDescription::MASK_SCREENROUND) |
+          ConfigDescription::SCREENROUND_YES;
+      break;
+
+    case pb::Configuration_ScreenRound_SCREEN_ROUND_NOTROUND:
+      out_config->screenLayout2 =
+          (out_config->screenLayout2 & ~ConfigDescription::MASK_SCREENROUND) |
+          ConfigDescription::SCREENROUND_NO;
+      break;
+
+    default:
+      break;
+  }
+
+  switch (pb_config.wide_color_gamut()) {
+    case pb::Configuration_WideColorGamut_WIDE_COLOR_GAMUT_WIDECG:
+      out_config->colorMode = (out_config->colorMode & ~ConfigDescription::MASK_WIDE_COLOR_GAMUT) |
+                              ConfigDescription::WIDE_COLOR_GAMUT_YES;
+      break;
+
+    case pb::Configuration_WideColorGamut_WIDE_COLOR_GAMUT_NOWIDECG:
+      out_config->colorMode = (out_config->colorMode & ~ConfigDescription::MASK_WIDE_COLOR_GAMUT) |
+                              ConfigDescription::WIDE_COLOR_GAMUT_NO;
+      break;
+
+    default:
+      break;
+  }
+
+  switch (pb_config.hdr()) {
+    case pb::Configuration_Hdr_HDR_HIGHDR:
+      out_config->colorMode =
+          (out_config->colorMode & ~ConfigDescription::MASK_HDR) | ConfigDescription::HDR_YES;
+      break;
+
+    case pb::Configuration_Hdr_HDR_LOWDR:
+      out_config->colorMode =
+          (out_config->colorMode & ~ConfigDescription::MASK_HDR) | ConfigDescription::HDR_NO;
+      break;
+
+    default:
+      break;
+  }
+
+  switch (pb_config.orientation()) {
+    case pb::Configuration_Orientation_ORIENTATION_PORT:
+      out_config->orientation = ConfigDescription::ORIENTATION_PORT;
+      break;
+
+    case pb::Configuration_Orientation_ORIENTATION_LAND:
+      out_config->orientation = ConfigDescription::ORIENTATION_LAND;
+      break;
+
+    case pb::Configuration_Orientation_ORIENTATION_SQUARE:
+      out_config->orientation = ConfigDescription::ORIENTATION_SQUARE;
+      break;
+
+    default:
+      break;
+  }
+
+  switch (pb_config.ui_mode_type()) {
+    case pb::Configuration_UiModeType_UI_MODE_TYPE_NORMAL:
+      out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) |
+                           ConfigDescription::UI_MODE_TYPE_NORMAL;
+      break;
+
+    case pb::Configuration_UiModeType_UI_MODE_TYPE_DESK:
+      out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) |
+                           ConfigDescription::UI_MODE_TYPE_DESK;
+      break;
+
+    case pb::Configuration_UiModeType_UI_MODE_TYPE_CAR:
+      out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) |
+                           ConfigDescription::UI_MODE_TYPE_CAR;
+      break;
+
+    case pb::Configuration_UiModeType_UI_MODE_TYPE_TELEVISION:
+      out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) |
+                           ConfigDescription::UI_MODE_TYPE_TELEVISION;
+      break;
+
+    case pb::Configuration_UiModeType_UI_MODE_TYPE_APPLIANCE:
+      out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) |
+                           ConfigDescription::UI_MODE_TYPE_APPLIANCE;
+      break;
+
+    case pb::Configuration_UiModeType_UI_MODE_TYPE_WATCH:
+      out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) |
+                           ConfigDescription::UI_MODE_TYPE_WATCH;
+      break;
+
+    case pb::Configuration_UiModeType_UI_MODE_TYPE_VRHEADSET:
+      out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) |
+                           ConfigDescription::UI_MODE_TYPE_VR_HEADSET;
+      break;
+
+    default:
+      break;
+  }
+
+  switch (pb_config.ui_mode_night()) {
+    case pb::Configuration_UiModeNight_UI_MODE_NIGHT_NIGHT:
+      out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_NIGHT) |
+                           ConfigDescription::UI_MODE_NIGHT_YES;
+      break;
+
+    case pb::Configuration_UiModeNight_UI_MODE_NIGHT_NOTNIGHT:
+      out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_NIGHT) |
+                           ConfigDescription::UI_MODE_NIGHT_NO;
+      break;
+
+    default:
+      break;
+  }
+
+  out_config->density = static_cast<uint16_t>(pb_config.density());
+
+  switch (pb_config.touchscreen()) {
+    case pb::Configuration_Touchscreen_TOUCHSCREEN_NOTOUCH:
+      out_config->touchscreen = ConfigDescription::TOUCHSCREEN_NOTOUCH;
+      break;
+
+    case pb::Configuration_Touchscreen_TOUCHSCREEN_STYLUS:
+      out_config->touchscreen = ConfigDescription::TOUCHSCREEN_STYLUS;
+      break;
+
+    case pb::Configuration_Touchscreen_TOUCHSCREEN_FINGER:
+      out_config->touchscreen = ConfigDescription::TOUCHSCREEN_FINGER;
+      break;
+
+    default:
+      break;
+  }
+
+  switch (pb_config.keys_hidden()) {
+    case pb::Configuration_KeysHidden_KEYS_HIDDEN_KEYSEXPOSED:
+      out_config->inputFlags = (out_config->inputFlags & ~ConfigDescription::MASK_KEYSHIDDEN) |
+                               ConfigDescription::KEYSHIDDEN_NO;
+      break;
+
+    case pb::Configuration_KeysHidden_KEYS_HIDDEN_KEYSHIDDEN:
+      out_config->inputFlags = (out_config->inputFlags & ~ConfigDescription::MASK_KEYSHIDDEN) |
+                               ConfigDescription::KEYSHIDDEN_YES;
+      break;
+
+    case pb::Configuration_KeysHidden_KEYS_HIDDEN_KEYSSOFT:
+      out_config->inputFlags = (out_config->inputFlags & ~ConfigDescription::MASK_KEYSHIDDEN) |
+                               ConfigDescription::KEYSHIDDEN_SOFT;
+      break;
+
+    default:
+      break;
+  }
+
+  switch (pb_config.keyboard()) {
+    case pb::Configuration_Keyboard_KEYBOARD_NOKEYS:
+      out_config->keyboard = ConfigDescription::KEYBOARD_NOKEYS;
+      break;
+
+    case pb::Configuration_Keyboard_KEYBOARD_QWERTY:
+      out_config->keyboard = ConfigDescription::KEYBOARD_QWERTY;
+      break;
+
+    case pb::Configuration_Keyboard_KEYBOARD_TWELVEKEY:
+      out_config->keyboard = ConfigDescription::KEYBOARD_12KEY;
+      break;
+
+    default:
+      break;
+  }
+
+  switch (pb_config.nav_hidden()) {
+    case pb::Configuration_NavHidden_NAV_HIDDEN_NAVEXPOSED:
+      out_config->inputFlags = (out_config->inputFlags & ~ConfigDescription::MASK_NAVHIDDEN) |
+                               ConfigDescription::NAVHIDDEN_NO;
+      break;
+
+    case pb::Configuration_NavHidden_NAV_HIDDEN_NAVHIDDEN:
+      out_config->inputFlags = (out_config->inputFlags & ~ConfigDescription::MASK_NAVHIDDEN) |
+                               ConfigDescription::NAVHIDDEN_YES;
+      break;
+
+    default:
+      break;
+  }
+
+  switch (pb_config.navigation()) {
+    case pb::Configuration_Navigation_NAVIGATION_NONAV:
+      out_config->navigation = ConfigDescription::NAVIGATION_NONAV;
+      break;
+
+    case pb::Configuration_Navigation_NAVIGATION_DPAD:
+      out_config->navigation = ConfigDescription::NAVIGATION_DPAD;
+      break;
+
+    case pb::Configuration_Navigation_NAVIGATION_TRACKBALL:
+      out_config->navigation = ConfigDescription::NAVIGATION_TRACKBALL;
+      break;
+
+    case pb::Configuration_Navigation_NAVIGATION_WHEEL:
+      out_config->navigation = ConfigDescription::NAVIGATION_WHEEL;
+      break;
+
+    default:
+      break;
+  }
+
+  out_config->screenWidth = static_cast<uint16_t>(pb_config.screen_width());
+  out_config->screenHeight = static_cast<uint16_t>(pb_config.screen_height());
+  out_config->sdkVersion = static_cast<uint16_t>(pb_config.sdk_version());
   return true;
 }
 
diff --git a/tools/aapt2/proto/ProtoHelpers.h b/tools/aapt2/proto/ProtoHelpers.h
index 2f268f4..714a2b2 100644
--- a/tools/aapt2/proto/ProtoHelpers.h
+++ b/tools/aapt2/proto/ProtoHelpers.h
@@ -20,11 +20,12 @@
 #include "androidfw/ResourceTypes.h"
 
 #include "ConfigDescription.h"
+#include "Configuration.pb.h"
 #include "ResourceTable.h"
-#include "Source.h"
-#include "StringPool.h"
 #include "Resources.pb.h"
 #include "ResourcesInternal.pb.h"
+#include "Source.h"
+#include "StringPool.h"
 
 namespace aapt {
 
@@ -39,9 +40,9 @@
 
 SymbolState DeserializeVisibilityFromPb(pb::SymbolStatus_Visibility pb_visibility);
 
-void SerializeConfig(const ConfigDescription& config, pb::ConfigDescription* out_pb_config);
+void SerializeConfig(const ConfigDescription& config, pb::Configuration* out_pb_config);
 
-bool DeserializeConfigDescriptionFromPb(const pb::ConfigDescription& pb_config,
+bool DeserializeConfigDescriptionFromPb(const pb::Configuration& pb_config,
                                         ConfigDescription* out_config);
 
 pb::Reference_Type SerializeReferenceTypeToPb(Reference::Type type);
diff --git a/tools/aapt2/proto/TableProtoDeserializer.cpp b/tools/aapt2/proto/TableProtoDeserializer.cpp
index f4a2b1e..4a88d61 100644
--- a/tools/aapt2/proto/TableProtoDeserializer.cpp
+++ b/tools/aapt2/proto/TableProtoDeserializer.cpp
@@ -123,7 +123,7 @@
         }
 
         for (const pb::ConfigValue& pb_config_value : pb_entry.config_value()) {
-          const pb::ConfigDescription& pb_config = pb_config_value.config();
+          const pb::Configuration& pb_config = pb_config_value.config();
 
           ConfigDescription config;
           if (!DeserializeConfigDescriptionFromPb(pb_config, &config)) {
@@ -395,14 +395,16 @@
   }
   file->name = name_ref.ToResourceName();
   file->source.path = pb_file.source_path();
-  DeserializeConfigDescriptionFromPb(pb_file.config(), &file->config);
+  if (!DeserializeConfigDescriptionFromPb(pb_file.config(), &file->config)) {
+    diag->Error(DiagMessage(source) << "invalid resource configuration in compiled file header");
+    return {};
+  }
 
   for (const pb::internal::CompiledFile_Symbol& pb_symbol : pb_file.exported_symbol()) {
     // Need to create an lvalue here so that nameRef can point to something real.
     if (!ResourceUtils::ParseResourceName(pb_symbol.resource_name(), &name_ref)) {
       diag->Error(DiagMessage(source)
-                  << "invalid resource name for exported symbol in "
-                     "compiled file header: "
+                  << "invalid resource name for exported symbol in compiled file header: "
                   << pb_file.resource_name());
       return {};
     }
diff --git a/tools/aapt2/proto/TableProtoSerializer.cpp b/tools/aapt2/proto/TableProtoSerializer.cpp
index 981b72a..3d5407c 100644
--- a/tools/aapt2/proto/TableProtoSerializer.cpp
+++ b/tools/aapt2/proto/TableProtoSerializer.cpp
@@ -282,10 +282,10 @@
 }
 
 void CompiledFileOutputStream::EnsureAlignedWrite() {
-  const int padding = out_.ByteCount() % 4;
-  if (padding > 0) {
+  const int overflow = out_.ByteCount() % 4;
+  if (overflow > 0) {
     uint32_t zero = 0u;
-    out_.WriteRaw(&zero, padding);
+    out_.WriteRaw(&zero, 4 - overflow);
   }
 }
 
@@ -322,10 +322,10 @@
     : in_(static_cast<const uint8_t*>(data), size) {}
 
 void CompiledFileInputStream::EnsureAlignedRead() {
-  const int padding = in_.CurrentPosition() % 4;
-  if (padding > 0) {
+  const int overflow = in_.CurrentPosition() % 4;
+  if (overflow > 0) {
     // Reads are always 4 byte aligned.
-    in_.Skip(padding);
+    in_.Skip(4 - overflow);
   }
 }
 
diff --git a/tools/aapt2/proto/TableProtoSerializer_test.cpp b/tools/aapt2/proto/TableProtoSerializer_test.cpp
index 80608b3..8f6414c 100644
--- a/tools/aapt2/proto/TableProtoSerializer_test.cpp
+++ b/tools/aapt2/proto/TableProtoSerializer_test.cpp
@@ -19,6 +19,7 @@
 #include "ResourceTable.h"
 #include "test/Test.h"
 
+using ::android::StringPiece;
 using ::google::protobuf::io::StringOutputStream;
 using ::testing::Eq;
 using ::testing::NotNull;
@@ -239,4 +240,97 @@
   EXPECT_FALSE(in_file_stream.ReadDataMetaData(&offset, &len));
 }
 
+static void ExpectConfigSerializes(const StringPiece& config_str) {
+  const ConfigDescription expected_config = test::ParseConfigOrDie(config_str);
+  pb::Configuration pb_config;
+  SerializeConfig(expected_config, &pb_config);
+
+  ConfigDescription actual_config;
+  ASSERT_TRUE(DeserializeConfigDescriptionFromPb(pb_config, &actual_config));
+  EXPECT_EQ(expected_config, actual_config);
+}
+
+TEST(TableProtoSerializer, SerializeDeserializeConfiguration) {
+  ExpectConfigSerializes("");
+
+  ExpectConfigSerializes("mcc123");
+
+  ExpectConfigSerializes("mnc123");
+
+  ExpectConfigSerializes("en");
+  ExpectConfigSerializes("en-rGB");
+  ExpectConfigSerializes("b+en+GB");
+
+  ExpectConfigSerializes("ldltr");
+  ExpectConfigSerializes("ldrtl");
+
+  ExpectConfigSerializes("sw3600dp");
+
+  ExpectConfigSerializes("w300dp");
+
+  ExpectConfigSerializes("h400dp");
+
+  ExpectConfigSerializes("small");
+  ExpectConfigSerializes("normal");
+  ExpectConfigSerializes("large");
+  ExpectConfigSerializes("xlarge");
+
+  ExpectConfigSerializes("long");
+  ExpectConfigSerializes("notlong");
+
+  ExpectConfigSerializes("round");
+  ExpectConfigSerializes("notround");
+
+  ExpectConfigSerializes("widecg");
+  ExpectConfigSerializes("nowidecg");
+
+  ExpectConfigSerializes("highdr");
+  ExpectConfigSerializes("lowdr");
+
+  ExpectConfigSerializes("port");
+  ExpectConfigSerializes("land");
+  ExpectConfigSerializes("square");
+
+  ExpectConfigSerializes("desk");
+  ExpectConfigSerializes("car");
+  ExpectConfigSerializes("television");
+  ExpectConfigSerializes("appliance");
+  ExpectConfigSerializes("watch");
+  ExpectConfigSerializes("vrheadset");
+
+  ExpectConfigSerializes("night");
+  ExpectConfigSerializes("notnight");
+
+  ExpectConfigSerializes("300dpi");
+  ExpectConfigSerializes("hdpi");
+
+  ExpectConfigSerializes("notouch");
+  ExpectConfigSerializes("stylus");
+  ExpectConfigSerializes("finger");
+
+  ExpectConfigSerializes("keysexposed");
+  ExpectConfigSerializes("keyshidden");
+  ExpectConfigSerializes("keyssoft");
+
+  ExpectConfigSerializes("nokeys");
+  ExpectConfigSerializes("qwerty");
+  ExpectConfigSerializes("12key");
+
+  ExpectConfigSerializes("navhidden");
+  ExpectConfigSerializes("navexposed");
+
+  ExpectConfigSerializes("nonav");
+  ExpectConfigSerializes("dpad");
+  ExpectConfigSerializes("trackball");
+  ExpectConfigSerializes("wheel");
+
+  ExpectConfigSerializes("300x200");
+
+  ExpectConfigSerializes("v8");
+
+  ExpectConfigSerializes(
+      "mcc123-mnc456-b+en+GB-ldltr-sw300dp-w300dp-h400dp-large-long-round-widecg-highdr-land-car-"
+      "night-xhdpi-stylus-keysexposed-qwerty-navhidden-dpad-300x200-v23");
+}
+
 }  // namespace aapt