Merge "AAPT2: Convert binary ResTable_config to proto"

This commit is contained in:
TreeHugger Robot
2017-09-27 18:37:39 +00:00
committed by Android (Google) Code Review
13 changed files with 906 additions and 103 deletions

View File

@@ -139,6 +139,7 @@ cc_library_host_static {
"xml/XmlDom.cpp",
"xml/XmlPullParser.cpp",
"xml/XmlUtil.cpp",
"Configuration.proto",
"Resources.proto",
"ResourcesInternal.proto",
],

View File

@@ -876,6 +876,12 @@ ConfigDescription ConfigDescription::CopyWithoutSdkVersion() const {
return copy;
}
std::string ConfigDescription::GetBcp47LanguageTag(bool canonicalize) const {
char locale[RESTABLE_MAX_LOCALE_LEN];
getBcp47Locale(locale, canonicalize);
return std::string(locale);
}
bool ConfigDescription::Dominates(const ConfigDescription& o) const {
if (*this == o) {
return true;

View File

@@ -61,6 +61,9 @@ struct ConfigDescription : public android::ResTable_config {
ConfigDescription CopyWithoutSdkVersion() const;
// Returns the BCP-47 language tag of this configuration's locale.
std::string GetBcp47LanguageTag(bool canonicalize = false) const;
/**
* A configuration X dominates another configuration Y, if X has at least the
* precedence of Y and X is strictly more general than Y: for any type defined

View File

@@ -0,0 +1,207 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
syntax = "proto3";
package aapt.pb;
option java_package = "com.android.aapt";
option optimize_for = LITE_RUNTIME;
// A description of the requirements a device must have in order for a
// resource to be matched and selected.
message Configuration {
enum LayoutDirection {
LAYOUT_DIRECTION_UNSET = 0;
LAYOUT_DIRECTION_LTR = 1;
LAYOUT_DIRECTION_RTL = 2;
}
enum ScreenLayoutSize {
SCREEN_LAYOUT_SIZE_UNSET = 0;
SCREEN_LAYOUT_SIZE_SMALL = 1;
SCREEN_LAYOUT_SIZE_NORMAL = 2;
SCREEN_LAYOUT_SIZE_LARGE = 3;
SCREEN_LAYOUT_SIZE_XLARGE = 4;
}
enum ScreenLayoutLong {
SCREEN_LAYOUT_LONG_UNSET = 0;
SCREEN_LAYOUT_LONG_LONG = 1;
SCREEN_LAYOUT_LONG_NOTLONG = 2;
}
enum ScreenRound {
SCREEN_ROUND_UNSET = 0;
SCREEN_ROUND_ROUND = 1;
SCREEN_ROUND_NOTROUND = 2;
}
enum WideColorGamut {
WIDE_COLOR_GAMUT_UNSET = 0;
WIDE_COLOR_GAMUT_WIDECG = 1;
WIDE_COLOR_GAMUT_NOWIDECG = 2;
}
enum Hdr {
HDR_UNSET = 0;
HDR_HIGHDR = 1;
HDR_LOWDR = 2;
}
enum Orientation {
ORIENTATION_UNSET = 0;
ORIENTATION_PORT = 1;
ORIENTATION_LAND = 2;
ORIENTATION_SQUARE = 3;
}
enum UiModeType {
UI_MODE_TYPE_UNSET = 0;
UI_MODE_TYPE_NORMAL = 1;
UI_MODE_TYPE_DESK = 2;
UI_MODE_TYPE_CAR = 3;
UI_MODE_TYPE_TELEVISION = 4;
UI_MODE_TYPE_APPLIANCE = 5;
UI_MODE_TYPE_WATCH = 6;
UI_MODE_TYPE_VRHEADSET = 7;
}
enum UiModeNight {
UI_MODE_NIGHT_UNSET = 0;
UI_MODE_NIGHT_NIGHT = 1;
UI_MODE_NIGHT_NOTNIGHT = 2;
}
enum Touchscreen {
TOUCHSCREEN_UNSET = 0;
TOUCHSCREEN_NOTOUCH = 1;
TOUCHSCREEN_STYLUS = 2;
TOUCHSCREEN_FINGER = 3;
}
enum KeysHidden {
KEYS_HIDDEN_UNSET = 0;
KEYS_HIDDEN_KEYSEXPOSED = 1;
KEYS_HIDDEN_KEYSHIDDEN = 2;
KEYS_HIDDEN_KEYSSOFT = 3;
}
enum Keyboard {
KEYBOARD_UNSET = 0;
KEYBOARD_NOKEYS = 1;
KEYBOARD_QWERTY = 2;
KEYBOARD_TWELVEKEY = 3;
}
enum NavHidden {
NAV_HIDDEN_UNSET = 0;
NAV_HIDDEN_NAVEXPOSED = 1;
NAV_HIDDEN_NAVHIDDEN = 2;
}
enum Navigation {
NAVIGATION_UNSET = 0;
NAVIGATION_NONAV = 1;
NAVIGATION_DPAD = 2;
NAVIGATION_TRACKBALL = 3;
NAVIGATION_WHEEL = 4;
}
//
// Axis/dimensions that are understood by the runtime.
//
// Mobile country code.
uint32 mcc = 1;
// Mobile network code.
uint32 mnc = 2;
// BCP-47 locale tag.
string locale = 3;
// Left-to-right, right-to-left...
LayoutDirection layout_direction = 4;
// Screen width in pixels. Prefer screen_width_dp.
uint32 screen_width = 5;
// Screen height in pixels. Prefer screen_height_dp.
uint32 screen_height = 6;
// Screen width in density independent pixels (dp).
uint32 screen_width_dp = 7;
// Screen height in density independent pixels (dp).
uint32 screen_height_dp = 8;
// The smallest screen dimension, regardless of orientation, in dp.
uint32 smallest_screen_width_dp = 9;
// Whether the device screen is classified as small, normal, large, xlarge.
ScreenLayoutSize screen_layout_size = 10;
// Whether the device screen is long.
ScreenLayoutLong screen_layout_long = 11;
// Whether the screen is round (Android Wear).
ScreenRound screen_round = 12;
// Whether the screen supports wide color gamut.
WideColorGamut wide_color_gamut = 13;
// Whether the screen has high dynamic range.
Hdr hdr = 14;
// Which orientation the device is in (portrait, landscape).
Orientation orientation = 15;
// Which type of UI mode the device is in (television, car, etc.).
UiModeType ui_mode_type = 16;
// Whether the device is in night mode.
UiModeNight ui_mode_night = 17;
// The device's screen density in dots-per-inch (dpi).
uint32 density = 18;
// Whether a touchscreen exists, supports a stylus, or finger.
Touchscreen touchscreen = 19;
// Whether the keyboard hardware keys are currently hidden, exposed, or
// if the keyboard is a software keyboard.
KeysHidden keys_hidden = 20;
// The type of keyboard present (none, QWERTY, 12-key).
Keyboard keyboard = 21;
// Whether the navigation is exposed or hidden.
NavHidden nav_hidden = 22;
// The type of navigation present on the device
// (trackball, wheel, dpad, etc.).
Navigation navigation = 23;
// The minimum SDK version of the device.
uint32 sdk_version = 24;
//
// Build-time only dimensions.
//
string product = 25;
}

View File

@@ -24,9 +24,10 @@
#include "util/Util.h"
namespace aapt {
using ::android::ResTable_config;
using ::android::StringPiece;
using android::ResTable_config;
namespace aapt {
void LocaleValue::set_language(const char* language_chars) {
size_t i = 0;
@@ -72,7 +73,7 @@ static inline bool is_number(const std::string& str) {
return std::all_of(std::begin(str), std::end(str), ::isdigit);
}
bool LocaleValue::InitFromFilterString(const android::StringPiece& str) {
bool LocaleValue::InitFromFilterString(const StringPiece& str) {
// A locale (as specified in the filter) is an underscore separated name such
// as "en_US", "en_Latn_US", or "en_US_POSIX".
std::vector<std::string> parts = util::SplitAndLowercase(str, '_');
@@ -138,6 +139,71 @@ bool LocaleValue::InitFromFilterString(const android::StringPiece& str) {
return true;
}
bool LocaleValue::InitFromBcp47Tag(const StringPiece& bcp47tag) {
return InitFromBcp47TagImpl(bcp47tag, '-');
}
bool LocaleValue::InitFromBcp47TagImpl(const StringPiece& bcp47tag, const char separator) {
std::vector<std::string> subtags = util::SplitAndLowercase(bcp47tag, separator);
if (subtags.size() == 1) {
set_language(subtags[0].c_str());
} else if (subtags.size() == 2) {
set_language(subtags[0].c_str());
// The second tag can either be a region, a variant or a script.
switch (subtags[1].size()) {
case 2:
case 3:
set_region(subtags[1].c_str());
break;
case 4:
if ('0' <= subtags[1][0] && subtags[1][0] <= '9') {
// This is a variant: fall through
} else {
set_script(subtags[1].c_str());
break;
}
case 5:
case 6:
case 7:
case 8:
set_variant(subtags[1].c_str());
break;
default:
return false;
}
} else if (subtags.size() == 3) {
// The language is always the first subtag.
set_language(subtags[0].c_str());
// The second subtag can either be a script or a region code.
// If its size is 4, it's a script code, else it's a region code.
if (subtags[1].size() == 4) {
set_script(subtags[1].c_str());
} else if (subtags[1].size() == 2 || subtags[1].size() == 3) {
set_region(subtags[1].c_str());
} else {
return false;
}
// The third tag can either be a region code (if the second tag was
// a script), else a variant code.
if (subtags[2].size() >= 4) {
set_variant(subtags[2].c_str());
} else {
set_region(subtags[2].c_str());
}
} else if (subtags.size() == 4) {
set_language(subtags[0].c_str());
set_script(subtags[1].c_str());
set_region(subtags[2].c_str());
set_variant(subtags[3].c_str());
} else {
return false;
}
return true;
}
ssize_t LocaleValue::InitFromParts(std::vector<std::string>::iterator iter,
std::vector<std::string>::iterator end) {
const std::vector<std::string>::iterator start_iter = iter;
@@ -145,71 +211,13 @@ ssize_t LocaleValue::InitFromParts(std::vector<std::string>::iterator iter,
std::string& part = *iter;
if (part[0] == 'b' && part[1] == '+') {
// This is a "modified" BCP 47 language tag. Same semantics as BCP 47 tags,
// except that the separator is "+" and not "-".
std::vector<std::string> subtags = util::SplitAndLowercase(part, '+');
subtags.erase(subtags.begin());
if (subtags.size() == 1) {
set_language(subtags[0].c_str());
} else if (subtags.size() == 2) {
set_language(subtags[0].c_str());
// The second tag can either be a region, a variant or a script.
switch (subtags[1].size()) {
case 2:
case 3:
set_region(subtags[1].c_str());
break;
case 4:
if ('0' <= subtags[1][0] && subtags[1][0] <= '9') {
// This is a variant: fall through
} else {
set_script(subtags[1].c_str());
break;
}
case 5:
case 6:
case 7:
case 8:
set_variant(subtags[1].c_str());
break;
default:
return -1;
}
} else if (subtags.size() == 3) {
// The language is always the first subtag.
set_language(subtags[0].c_str());
// The second subtag can either be a script or a region code.
// If its size is 4, it's a script code, else it's a region code.
if (subtags[1].size() == 4) {
set_script(subtags[1].c_str());
} else if (subtags[1].size() == 2 || subtags[1].size() == 3) {
set_region(subtags[1].c_str());
} else {
return -1;
}
// The third tag can either be a region code (if the second tag was
// a script), else a variant code.
if (subtags[2].size() >= 4) {
set_variant(subtags[2].c_str());
} else {
set_region(subtags[2].c_str());
}
} else if (subtags.size() == 4) {
set_language(subtags[0].c_str());
set_script(subtags[1].c_str());
set_region(subtags[2].c_str());
set_variant(subtags[3].c_str());
} else {
// except that the separator is "+" and not "-". Skip the prefix 'b+'.
if (!InitFromBcp47TagImpl(StringPiece(part).substr(2), '+')) {
return -1;
}
++iter;
} else {
if ((part.length() == 2 || part.length() == 3) && is_alpha(part) &&
part != "car") {
if ((part.length() == 2 || part.length() == 3) && is_alpha(part) && part != "car") {
set_language(part.c_str());
++iter;
@@ -222,7 +230,6 @@ ssize_t LocaleValue::InitFromParts(std::vector<std::string>::iterator iter,
}
}
}
return static_cast<ssize_t>(iter - start_iter);
}

View File

@@ -41,6 +41,9 @@ struct LocaleValue {
*/
bool InitFromFilterString(const android::StringPiece& config);
// Initializes this LocaleValue from a BCP-47 locale tag.
bool InitFromBcp47Tag(const android::StringPiece& bcp47tag);
/**
* Initialize this LocaleValue from parts of a vector.
*/
@@ -67,6 +70,8 @@ struct LocaleValue {
inline bool operator>(const LocaleValue& o) const;
private:
bool InitFromBcp47TagImpl(const android::StringPiece& bcp47tag, const char separator);
void set_language(const char* language);
void set_region(const char* language);
void set_script(const char* script);

View File

@@ -16,19 +16,13 @@
syntax = "proto3";
import "frameworks/base/tools/aapt2/Configuration.proto";
package aapt.pb;
option java_package = "com.android.aapt";
option optimize_for = LITE_RUNTIME;
// A configuration description that wraps the binary form of the C++ class
// aapt::ConfigDescription, with an added product definition.
// TODO(adamlesinski): Flesh this out to be represented in proto.
message ConfigDescription {
bytes data = 1;
string product = 2;
}
// A string pool that wraps the binary form of the C++ class android::ResStringPool.
message StringPool {
bytes data = 1;
@@ -163,7 +157,7 @@ message Entry {
// A Configuration/Value pair.
message ConfigValue {
ConfigDescription config = 1;
Configuration config = 1;
Value value = 2;
}

View File

@@ -16,6 +16,7 @@
syntax = "proto3";
import "frameworks/base/tools/aapt2/Configuration.proto";
import "frameworks/base/tools/aapt2/Resources.proto";
package aapt.pb.internal;
@@ -38,7 +39,7 @@ message CompiledFile {
string resource_name = 1;
// The configuration for which the resource is defined.
aapt.pb.ConfigDescription config = 2;
aapt.pb.Configuration config = 2;
// The filesystem path to where the source file originated.
// Mainly used to display helpful error messages.

View File

@@ -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 @@ SymbolState DeserializeVisibilityFromPb(pb::SymbolStatus_Visibility pb_visibilit
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;
}

View File

@@ -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 @@ pb::SymbolStatus_Visibility SerializeVisibilityToPb(SymbolState state);
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);

View File

@@ -123,7 +123,7 @@ class PackagePbDeserializer {
}
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 @@ std::unique_ptr<ResourceFile> DeserializeCompiledFileFromPb(
}
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 {};
}

View File

@@ -282,10 +282,10 @@ CompiledFileOutputStream::CompiledFileOutputStream(ZeroCopyOutputStream* out) :
}
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 @@ CompiledFileInputStream::CompiledFileInputStream(const void* data, size_t size)
: 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);
}
}

View File

@@ -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 @@ TEST(TableProtoSerializer, DeserializeCorruptHeaderSafely) {
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