Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 837cefb8 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Don't allow splitting on an empty configuration"

parents 6acca823 9fbdf89d
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -1842,9 +1842,15 @@ class Linker {
    } else {
      // Adjust the SplitConstraints so that their SDK version is stripped if it is less than or
      // equal to the minSdk.
      const size_t origConstraintSize = options_.split_constraints.size();
      options_.split_constraints =
          AdjustSplitConstraintsForMinSdk(context_->GetMinSdkVersion(), options_.split_constraints);

      if (origConstraintSize != options_.split_constraints.size()) {
        context_->GetDiagnostics()->Warn(DiagMessage()
                                         << "requested to split resources prior to min sdk of "
                                         << context_->GetMinSdkVersion());
      }
      TableSplitter table_splitter(options_.split_constraints, options_.table_splitter_options);
      if (!table_splitter.VerifySplitConstraints(context_)) {
        return 1;
+8 −4
Original line number Diff line number Diff line
@@ -73,6 +73,7 @@ bool ParseSplitParameter(const StringPiece& arg, IDiagnostics* diag, std::string
  }

  *out_path = parts[0];
  out_split->name = parts[1];
  for (const StringPiece& config_str : util::Tokenize(parts[1], ',')) {
    ConfigDescription config;
    if (!ConfigDescription::Parse(config_str, &config)) {
@@ -119,12 +120,15 @@ std::vector<SplitConstraints> AdjustSplitConstraintsForMinSdk(
  for (const SplitConstraints& constraints : split_constraints) {
    SplitConstraints constraint;
    for (const ConfigDescription& config : constraints.configs) {
      if (config.sdkVersion <= min_sdk) {
        constraint.configs.insert(config.CopyWithoutSdkVersion());
      } else {
        constraint.configs.insert(config);
      const ConfigDescription &configToInsert = (config.sdkVersion <= min_sdk)
          ? config.CopyWithoutSdkVersion()
          : config;
      // only add the config if it actually selects something
      if (configToInsert != ConfigDescription::DefaultConfig()) {
        constraint.configs.insert(configToInsert);
      }
    }
    constraint.name = constraints.name;
    adjusted_constraints.push_back(std::move(constraint));
  }
  return adjusted_constraints;
+287 −0
Original line number Diff line number Diff line
@@ -22,6 +22,10 @@
#include "test/Test.h"

namespace aapt {
#define EXPECT_CONFIG_EQ(constraints, config) \
    EXPECT_EQ(constraints.configs.size(), 1); \
    EXPECT_EQ(*constraints.configs.begin(), config); \
    constraints.configs.clear();

TEST(UtilTest, SplitNamesAreSanitized) {
    AppInfo app_info{"com.pkg"};
@@ -84,4 +88,287 @@ TEST (UtilTest, LongVersionCodeUndefined) {
  EXPECT_EQ(compiled_version_code_major->value.data, 0x61);
}


TEST (UtilTest, ParseSplitParameter) {
  IDiagnostics* diagnostics = test::ContextBuilder().Build().get()->GetDiagnostics();
  std::string path;
  SplitConstraints constraints;
  ConfigDescription expected_configuration;

  // ========== Test IMSI ==========
  // mcc: 'mcc[0-9]{3}'
  // mnc: 'mnc[0-9]{1,3}'
  ASSERT_TRUE(ParseSplitParameter(":mcc310",
                                  diagnostics, &path, &constraints));
  expected_configuration = test::ConfigDescriptionBuilder()
      .setMcc(0x0136)
      .Build();
  EXPECT_CONFIG_EQ(constraints, expected_configuration);

  ASSERT_TRUE(ParseSplitParameter(":mcc310-mnc004",
                                  diagnostics, &path, &constraints));
  expected_configuration = test::ConfigDescriptionBuilder()
      .setMcc(0x0136)
      .setMnc(0x0004)
      .Build();
  EXPECT_CONFIG_EQ(constraints, expected_configuration);

  ASSERT_TRUE(ParseSplitParameter(":mcc310-mnc000",
                                  diagnostics, &path, &constraints));
  expected_configuration = test::ConfigDescriptionBuilder()
      .setMcc(0x0136)
      .setMnc(0xFFFF)
      .Build();
  EXPECT_CONFIG_EQ(constraints, expected_configuration);

  // ========== Test LOCALE ==========
  // locale: '[a-z]{2,3}(-r[a-z]{2})?'
  // locale: 'b+[a-z]{2,3}(+[a-z[0-9]]{2})?'
  ASSERT_TRUE(ParseSplitParameter(":es",
                                  diagnostics, &path, &constraints));
  expected_configuration = test::ConfigDescriptionBuilder()
      .setLanguage(0x6573)
      .Build();
  EXPECT_CONFIG_EQ(constraints, expected_configuration);

  ASSERT_TRUE(ParseSplitParameter(":fr-rCA",
                                  diagnostics, &path, &constraints));
  expected_configuration = test::ConfigDescriptionBuilder()
      .setLanguage(0x6672)
      .setCountry(0x4341)
      .Build();
  EXPECT_CONFIG_EQ(constraints, expected_configuration);

  ASSERT_TRUE(ParseSplitParameter(":b+es+419",
                                  diagnostics, &path, &constraints));
  expected_configuration = test::ConfigDescriptionBuilder()
      .setLanguage(0x6573)
      .setCountry(0xA424)
      .Build();
  EXPECT_CONFIG_EQ(constraints, expected_configuration);

  // ========== Test SCREEN_TYPE ==========
  // orientation: '(port|land|square)'
  // touchscreen: '(notouch|stylus|finger)'
  // density" '(anydpi|nodpi|ldpi|mdpi|tvdpi|hdpi|xhdpi|xxhdpi|xxxhdpi|[0-9]*dpi)'
  ASSERT_TRUE(ParseSplitParameter(":square",
                                  diagnostics, &path, &constraints));
  expected_configuration = test::ConfigDescriptionBuilder()
      .setOrientation(0x03)
      .Build();
  EXPECT_CONFIG_EQ(constraints, expected_configuration);

  ASSERT_TRUE(ParseSplitParameter(":stylus",
                                  diagnostics, &path, &constraints));
  expected_configuration = test::ConfigDescriptionBuilder()
      .setTouchscreen(0x02)
      .Build();
  EXPECT_CONFIG_EQ(constraints, expected_configuration);

  ASSERT_TRUE(ParseSplitParameter(":xxxhdpi",
                                  diagnostics, &path, &constraints));
  expected_configuration = test::ConfigDescriptionBuilder()
      .setDensity(0x0280)
      .setSdkVersion(0x0004) // version [any density requires donut]
      .Build();
  EXPECT_CONFIG_EQ(constraints, expected_configuration);

  ASSERT_TRUE(ParseSplitParameter(":land-xhdpi-finger",
                                  diagnostics, &path, &constraints));
  expected_configuration = test::ConfigDescriptionBuilder()
      .setOrientation(0x02)
      .setTouchscreen(0x03)
      .setDensity(0x0140)
      .setSdkVersion(0x0004) // version [any density requires donut]
      .Build();
  EXPECT_CONFIG_EQ(constraints, expected_configuration);

  // ========== Test INPUT ==========
  // keyboard: '(nokeys|qwerty|12key)'
  // navigation: '(nonav|dpad|trackball|wheel)'
  // inputFlags: '(keysexposed|keyshidden|keyssoft)'
  // inputFlags: '(navexposed|navhidden)'
  ASSERT_TRUE(ParseSplitParameter(":qwerty",
                                  diagnostics, &path, &constraints));
  expected_configuration = test::ConfigDescriptionBuilder()
      .setKeyboard(0x02)
      .Build();
  EXPECT_CONFIG_EQ(constraints, expected_configuration);

  ASSERT_TRUE(ParseSplitParameter(":dpad",
                                  diagnostics, &path, &constraints));
  expected_configuration = test::ConfigDescriptionBuilder()
      .setNavigation(0x02)
      .Build();
  EXPECT_CONFIG_EQ(constraints, expected_configuration);

  ASSERT_TRUE(ParseSplitParameter(":keyssoft-navhidden",
                                  diagnostics, &path, &constraints));
  expected_configuration = test::ConfigDescriptionBuilder()
      .setInputFlags(0x0B)
      .Build();
  EXPECT_CONFIG_EQ(constraints, expected_configuration);

  ASSERT_TRUE(ParseSplitParameter(":keyshidden-nokeys-navexposed-trackball",
                                  diagnostics, &path, &constraints));
  expected_configuration = test::ConfigDescriptionBuilder()
      .setKeyboard(0x01)
      .setNavigation(0x03)
      .setInputFlags(0x06)
      .Build();
  EXPECT_CONFIG_EQ(constraints, expected_configuration);

  // ========== Test SCREEN_SIZE ==========
  // screenWidth/screenHeight: '[0-9]+x[0-9]+'
  ASSERT_TRUE(ParseSplitParameter(":1920x1080",
                                  diagnostics, &path, &constraints));
  expected_configuration = test::ConfigDescriptionBuilder()
      .setScreenWidth(0x0780)
      .setScreenHeight(0x0438)
      .Build();
  EXPECT_CONFIG_EQ(constraints, expected_configuration);

  // ========== Test VERSION ==========
  // version 'v[0-9]+'

  // ========== Test SCREEN_CONFIG ==========
  // screenLayout [direction]: '(ldltr|ldrtl)'
  // screenLayout [size]: '(small|normal|large|xlarge)'
  // screenLayout [long]: '(long|notlong)'
  // uiMode [type]: '(desk|car|television|appliance|watch|vrheadset)'
  // uiMode [night]: '(night|notnight)'
  // smallestScreenWidthDp: 'sw[0-9]dp'
  ASSERT_TRUE(ParseSplitParameter(":ldrtl",
                                  diagnostics, &path, &constraints));
  expected_configuration = test::ConfigDescriptionBuilder()
      .setScreenLayout(0x80)
      .Build();
  EXPECT_CONFIG_EQ(constraints, expected_configuration);

  ASSERT_TRUE(ParseSplitParameter(":small",
                                  diagnostics, &path, &constraints));
  expected_configuration = test::ConfigDescriptionBuilder()
      .setScreenLayout(0x01)
      .setSdkVersion(0x0004) // screenLayout (size) requires donut
      .Build();
  EXPECT_CONFIG_EQ(constraints, expected_configuration);

  ASSERT_TRUE(ParseSplitParameter(":notlong",
                                  diagnostics, &path, &constraints));
  expected_configuration = test::ConfigDescriptionBuilder()
      .setScreenLayout(0x10)
      .setSdkVersion(0x0004) // screenLayout (long) requires donut
      .Build();
  EXPECT_CONFIG_EQ(constraints, expected_configuration);

  ASSERT_TRUE(ParseSplitParameter(":ldltr-normal-long",
                                  diagnostics, &path, &constraints));
  expected_configuration = test::ConfigDescriptionBuilder()
      .setScreenLayout(0x62)
      .setSdkVersion(0x0004) // screenLayout (size|long) requires donut
      .Build();
  EXPECT_CONFIG_EQ(constraints, expected_configuration);

  ASSERT_TRUE(ParseSplitParameter(":car",
                                  diagnostics, &path, &constraints));
  expected_configuration = test::ConfigDescriptionBuilder()
      .setUiMode(0x03)
      .setSdkVersion(0x0008) // uiMode requires froyo
      .Build();
  EXPECT_CONFIG_EQ(constraints, expected_configuration);

  ASSERT_TRUE(ParseSplitParameter(":vrheadset",
                                  diagnostics, &path, &constraints));
  expected_configuration = test::ConfigDescriptionBuilder()
      .setUiMode(0x07)
      .setSdkVersion(0x001A) // uiMode 'vrheadset' requires oreo
      .Build();
  EXPECT_CONFIG_EQ(constraints, expected_configuration);

  ASSERT_TRUE(ParseSplitParameter(":television-night",
                                  diagnostics, &path, &constraints));
  expected_configuration = test::ConfigDescriptionBuilder()
      .setUiMode(0x24)
      .setSdkVersion(0x0008) // uiMode requires froyo
      .Build();
  EXPECT_CONFIG_EQ(constraints, expected_configuration);

  ASSERT_TRUE(ParseSplitParameter(":sw1920dp",
                                  diagnostics, &path, &constraints));
  expected_configuration = test::ConfigDescriptionBuilder()
      .setSmallestScreenWidthDp(0x0780)
      .setSdkVersion(0x000D) // smallestScreenWidthDp requires honeycomb mr2
      .Build();
  EXPECT_CONFIG_EQ(constraints, expected_configuration);

  // ========== Test SCREEN_SIZE_DP ==========
  // screenWidthDp: 'w[0-9]dp'
  // screenHeightDp: 'h[0-9]dp'
  ASSERT_TRUE(ParseSplitParameter(":w1920dp",
                                  diagnostics, &path, &constraints));
  expected_configuration = test::ConfigDescriptionBuilder()
      .setScreenWidthDp(0x0780)
      .setSdkVersion(0x000D) // screenWidthDp requires honeycomb mr2
      .Build();
  EXPECT_CONFIG_EQ(constraints, expected_configuration);

  ASSERT_TRUE(ParseSplitParameter(":h1080dp",
                                  diagnostics, &path, &constraints));
  expected_configuration = test::ConfigDescriptionBuilder()
      .setScreenHeightDp(0x0438)
      .setSdkVersion(0x000D) // screenHeightDp requires honeycomb mr2
      .Build();
  EXPECT_CONFIG_EQ(constraints, expected_configuration);

  // ========== Test SCREEN_CONFIG_2 ==========
  // screenLayout2: '(round|notround)'
  // colorMode: '(widecg|nowidecg)'
  // colorMode: '(highhdr|lowdr)'
  ASSERT_TRUE(ParseSplitParameter(":round",
                                  diagnostics, &path, &constraints));
  expected_configuration = test::ConfigDescriptionBuilder()
      .setScreenLayout2(0x02)
      .setSdkVersion(0x0017) // screenLayout2 (round) requires marshmallow
      .Build();
  EXPECT_CONFIG_EQ(constraints, expected_configuration);

  ASSERT_TRUE(ParseSplitParameter(":widecg-highdr",
                                  diagnostics, &path, &constraints));
  expected_configuration = test::ConfigDescriptionBuilder()
      .setColorMode(0x0A)
      .setSdkVersion(0x001A) // colorMode (hdr|colour gamut) requires oreo
      .Build();
  EXPECT_CONFIG_EQ(constraints, expected_configuration);
}

TEST (UtilTest, AdjustSplitConstraintsForMinSdk) {
  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();

  IDiagnostics* diagnostics = context.get()->GetDiagnostics();
  std::vector<SplitConstraints> test_constraints;
  std::string path;

  test_constraints.push_back({});
  ASSERT_TRUE(ParseSplitParameter(":v7",
                                  diagnostics, &path, &test_constraints.back()));
  test_constraints.push_back({});
  ASSERT_TRUE(ParseSplitParameter(":xhdpi",
                                  diagnostics, &path, &test_constraints.back()));
  EXPECT_EQ(test_constraints.size(), 2);
  EXPECT_EQ(test_constraints[0].name, "v7");
  EXPECT_EQ(test_constraints[0].configs.size(), 1);
  EXPECT_NE(*test_constraints[0].configs.begin(), ConfigDescription::DefaultConfig());
  EXPECT_EQ(test_constraints[1].name, "xhdpi");
  EXPECT_EQ(test_constraints[1].configs.size(), 1);
  EXPECT_NE(*test_constraints[0].configs.begin(), ConfigDescription::DefaultConfig());

  auto adjusted_contraints = AdjustSplitConstraintsForMinSdk(26, test_constraints);
  EXPECT_EQ(adjusted_contraints.size(), 2);
  EXPECT_EQ(adjusted_contraints[0].name, "v7");
  EXPECT_EQ(adjusted_contraints[0].configs.size(), 0);
  EXPECT_EQ(adjusted_contraints[1].name, "xhdpi");
  EXPECT_EQ(adjusted_contraints[1].configs.size(), 1);
  EXPECT_NE(*adjusted_contraints[1].configs.begin(), ConfigDescription::DefaultConfig());
}

}  // namespace aapt
+6 −0
Original line number Diff line number Diff line
@@ -154,6 +154,12 @@ static void MarkNonPreferredDensitiesAsClaimed(
bool TableSplitter::VerifySplitConstraints(IAaptContext* context) {
  bool error = false;
  for (size_t i = 0; i < split_constraints_.size(); i++) {
    if (split_constraints_[i].configs.size() == 0) {
      // For now, treat this as a warning. We may consider aborting processing.
      context->GetDiagnostics()->Warn(DiagMessage()
                                       << "no configurations for constraint '"
                                       << split_constraints_[i].name << "'");
    }
    for (size_t j = i + 1; j < split_constraints_.size(); j++) {
      for (const ConfigDescription& config : split_constraints_[i].configs) {
        if (split_constraints_[j].configs.find(config) != split_constraints_[j].configs.end()) {
+1 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ namespace aapt {

struct SplitConstraints {
  std::set<ConfigDescription> configs;
  std::string name;
};

struct TableSplitterOptions {
Loading