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

Commit 672384b4 authored by Pierre Lecesne's avatar Pierre Lecesne
Browse files

Allow for multiple preferred densities in the strip command.

Test: Unit tests pass.

Change-Id: I1f27ac8c36ff3489e4c8e4fce7f3d9cb31df6906
parent 85a05cd9
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -1634,7 +1634,7 @@ class LinkCommand {

    if (options_.static_lib) {
      if (options_.table_splitter_options.config_filter != nullptr ||
          options_.table_splitter_options.preferred_density) {
          !options_.table_splitter_options.preferred_densities.empty()) {
        context_->GetDiagnostics()
            ->Warn(DiagMessage()
                   << "can't strip resources when building static library");
@@ -2107,8 +2107,7 @@ int Link(const std::vector<StringPiece>& args) {
                        << "Preferred density must only be a density value");
      return 1;
    }
    options.table_splitter_options.preferred_density =
        preferred_density_config.density;
    options.table_splitter_options.preferred_densities.push_back(preferred_density_config.density);
  }

  if (!options.static_lib && stable_id_file_path) {
+23 −16
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <algorithm>
#include <map>
#include <set>
#include <unordered_set>
#include <unordered_map>
#include <vector>

@@ -124,29 +125,35 @@ class SplitValueSelector {
 * leaving only the preferred density behind.
 */
static void MarkNonPreferredDensitiesAsClaimed(
    uint16_t preferred_density, const ConfigDensityGroups& density_groups,
    const std::vector<uint16_t>& preferred_densities, const ConfigDensityGroups& density_groups,
    ConfigClaimedMap* config_claimed_map) {
  for (auto& entry : density_groups) {
    const ConfigDescription& config = entry.first;
    const std::vector<ResourceConfigValue*>& related_values = entry.second;

    // There can be multiple best values if there are multiple preferred densities.
    std::unordered_set<ResourceConfigValue*> best_values;

    // For each preferred density, find the value that is the best.
    for (uint16_t preferred_density : preferred_densities) {
      ConfigDescription target_density = config;
      target_density.density = preferred_density;
      ResourceConfigValue* best_value = nullptr;
      for (ResourceConfigValue* this_value : related_values) {
      if (!best_value) {
        best_value = this_value;
      } else if (this_value->config.isBetterThan(best_value->config,
                                                 &target_density)) {
        // Claim the previous value so that it is not included in the base.
        (*config_claimed_map)[best_value] = true;
        if (!best_value || this_value->config.isBetterThan(best_value->config, &target_density)) {
          best_value = this_value;
      } else {
        // Claim this value so that it is not included in the base.
        (*config_claimed_map)[this_value] = true;
        }
      }
      CHECK(best_value != nullptr);
      best_values.insert(best_value);
    }

    // Claim all the values that aren't the best so that they will be removed from the base.
    for (ResourceConfigValue* this_value : related_values) {
      if (best_values.find(this_value) == best_values.end()) {
        (*config_claimed_map)[this_value] = true;
      }
    }
  }
}
bool TableSplitter::VerifySplitConstraints(IAaptContext* context) {
@@ -263,8 +270,8 @@ void TableSplitter::SplitTable(ResourceTable* original_table) {
          }
        }

        if (options_.preferred_density) {
          MarkNonPreferredDensitiesAsClaimed(options_.preferred_density.value(),
        if (!options_.preferred_densities.empty()) {
          MarkNonPreferredDensitiesAsClaimed(options_.preferred_densities,
                                             density_groups,
                                             &config_claimed_map);
        }
+4 −4
Original line number Diff line number Diff line
@@ -34,14 +34,14 @@ struct SplitConstraints {

struct TableSplitterOptions {
  /**
   * The preferred density to keep in the table, stripping out all others.
   * The preferred densities to keep in the table, stripping out all others.
   * If empty, no stripping is done.
   */
  Maybe<uint16_t> preferred_density;
  std::vector<uint16_t> preferred_densities;

  /**
   * Configuration filter that determines which resource configuration values
   * end up in
   * the final table.
   * end up in the final table.
   */
  IConfigFilter* config_filter = nullptr;
};
+46 −1
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@ TEST(TableSplitterTest, NoSplitPreferredDensity) {
          .Build();

  TableSplitterOptions options;
  options.preferred_density = ConfigDescription::DENSITY_XHIGH;
  options.preferred_densities.push_back(ConfigDescription::DENSITY_XHIGH);
  TableSplitter splitter({}, options);
  splitter.SplitTable(table.get());

@@ -58,6 +58,51 @@ TEST(TableSplitterTest, NoSplitPreferredDensity) {
  EXPECT_NE(nullptr, test::GetValue<Id>(table.get(), "android:string/one"));
}

TEST(TableSplitterTest, NoSplitMultiplePreferredDensities) {
  std::unique_ptr<ResourceTable> table =
      test::ResourceTableBuilder()
          .AddFileReference("android:drawable/icon",
                            "res/drawable-mdpi/icon.png",
                            test::ParseConfigOrDie("mdpi"))
          .AddFileReference("android:drawable/icon",
                            "res/drawable-hdpi/icon.png",
                            test::ParseConfigOrDie("hdpi"))
          .AddFileReference("android:drawable/icon",
                            "res/drawable-xhdpi/icon.png",
                            test::ParseConfigOrDie("xhdpi"))
          .AddFileReference("android:drawable/icon",
                            "res/drawable-xxhdpi/icon.png",
                            test::ParseConfigOrDie("xxhdpi"))
          .AddSimple("android:string/one")
          .Build();

  TableSplitterOptions options;
  options.preferred_densities.push_back(ConfigDescription::DENSITY_LOW);
  options.preferred_densities.push_back(ConfigDescription::DENSITY_XXXHIGH);
  TableSplitter splitter({}, options);
  splitter.SplitTable(table.get());

  // Densities remaining:
  // "mdpi" is the closest available density for the requested "ldpi" density.
  EXPECT_NE(nullptr, test::GetValueForConfig<FileReference>(
                         table.get(), "android:drawable/icon",
                         test::ParseConfigOrDie("mdpi")));
  // "xxhdpi" is the closest available density for the requested "xxxhdpi" density.
  EXPECT_NE(nullptr, test::GetValueForConfig<FileReference>(
                         table.get(), "android:drawable/icon",
                         test::ParseConfigOrDie("xxhdpi")));
  EXPECT_NE(nullptr, test::GetValue<Id>(table.get(), "android:string/one"));

  // Removed densities:
  EXPECT_EQ(nullptr, test::GetValueForConfig<FileReference>(
                         table.get(), "android:drawable/icon",
                         test::ParseConfigOrDie("hdpi")));
  EXPECT_EQ(nullptr, test::GetValueForConfig<FileReference>(
                         table.get(), "android:drawable/icon",
                         test::ParseConfigOrDie("xhdpi")));
}


TEST(TableSplitterTest, SplitTableByDensity) {
  std::unique_ptr<ResourceTable> table =
      test::ResourceTableBuilder()
+4 −9
Original line number Diff line number Diff line
@@ -79,18 +79,13 @@ class StripCommand {
      context_->GetDiagnostics()->Note(DiagMessage() << "Stripping APK...");
    }

    // TODO(lecesne): Add support for more than one density.
    if (options_.target_configs.size() > 1) {
      context_->GetDiagnostics()->Error(DiagMessage()
                                        << "Multiple densities not supported at the moment");
      return 1;
    }

    // Stripping the APK using the TableSplitter with no splits and the target
    // density as the preferred density. The resource table is modified in
    // densities as the preferred densities. The resource table is modified in
    // place in the LoadedApk.
    TableSplitterOptions splitter_options;
    splitter_options.preferred_density = options_.target_configs[0].density;
    for (auto& config : options_.target_configs) {
      splitter_options.preferred_densities.push_back(config.density);
    }
    std::vector<SplitConstraints> splits;
    TableSplitter splitter(splits, splitter_options);
    splitter.SplitTable(apk->GetResourceTable());