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

Commit fc7aba63 authored by Jeremy Meyer's avatar Jeremy Meyer Committed by Android Build Cherrypicker Worker
Browse files

Add ability to pass flag read only status to aapt2

Also adds the ability to pass flags to the compile command

Test: automated
Bug: 344979955
Flag: EXEMPT tools change
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:b5c0ef0843f1426b9237b050994e8753b0921617)
Merged-In: I29997712d262be6d89eef16daf67d37cbafe3cba
Change-Id: I29997712d262be6d89eef16daf67d37cbafe3cba
parent a5a22663
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -836,6 +836,28 @@ int CompileCommand::Action(const std::vector<std::string>& args) {
    return 1;
  }

  // Parse the feature flag values. An argument that starts with '@' points to a file to read flag
  // values from.
  std::vector<std::string> all_feature_flags_args;
  for (const std::string& arg : feature_flags_args_) {
    if (util::StartsWith(arg, "@")) {
      const std::string path = arg.substr(1, arg.size() - 1);
      std::string error;
      if (!file::AppendArgsFromFile(path, &all_feature_flags_args, &error)) {
        context.GetDiagnostics()->Error(android::DiagMessage(path) << error);
        return 1;
      }
    } else {
      all_feature_flags_args.push_back(arg);
    }
  }

  for (const std::string& arg : all_feature_flags_args) {
    if (!ParseFeatureFlagsParameter(arg, context.GetDiagnostics(), &options_.feature_flag_values)) {
      return 1;
    }
  }

  return Compile(&context, file_collection.get(), archive_writer.get(), options_);
}

+9 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include "Command.h"
#include "ResourceTable.h"
#include "androidfw/IDiagnostics.h"
#include "cmd/Util.h"
#include "format/Archive.h"
#include "process/IResourceTableConsumer.h"

@@ -45,6 +46,7 @@ struct CompileOptions {
  bool preserve_visibility_of_styleables = false;
  bool verbose = false;
  std::optional<std::string> product_;
  FeatureFlagValues feature_flag_values;
};

/** Parses flags and compiles resources to be used in linking.  */
@@ -92,6 +94,12 @@ class CompileCommand : public Command {
                    "Leave only resources specific to the given product. All "
                    "other resources (including defaults) are removed.",
                    &options_.product_);
    AddOptionalFlagList("--feature-flags",
                        "Specify the values of feature flags. The pairs in the argument\n"
                        "are separated by ',' the name is separated from the value by '='.\n"
                        "The name can have a suffix of ':ro' to indicate it is read only."
                        "Example: \"flag1=true,flag2:ro=false,flag3=\" (flag3 has no given value).",
                        &feature_flags_args_);
  }

  int Action(const std::vector<std::string>& args) override;
@@ -101,6 +109,7 @@ class CompileCommand : public Command {
  CompileOptions options_;
  std::optional<std::string> visibility_;
  std::optional<std::string> trace_folder_;
  std::vector<std::string> feature_flags_args_;
};

int Compile(IAaptContext* context, io::IFileCollection* inputs, IArchiveWriter* output_writer,
+3 −2
Original line number Diff line number Diff line
@@ -332,8 +332,9 @@ class LinkCommand : public Command {
    AddOptionalSwitch("-v", "Enables verbose logging.", &verbose_);
    AddOptionalFlagList("--feature-flags",
                        "Specify the values of feature flags. The pairs in the argument\n"
                        "are separated by ',' and the name is separated from the value by '='.\n"
                        "Example: \"flag1=true,flag2=false,flag3=\" (flag3 has no given value).",
                        "are separated by ',' the name is separated from the value by '='.\n"
                        "The name can have a suffix of ':ro' to indicate it is read only."
                        "Example: \"flag1=true,flag2:ro=false,flag3=\" (flag3 has no given value).",
                        &feature_flags_args_);
    AddOptionalSwitch("--non-updatable-system",
                      "Mark the app as a non-updatable system app. This inserts\n"
+23 −4
Original line number Diff line number Diff line
@@ -128,7 +128,7 @@ bool ParseFeatureFlagsParameter(StringPiece arg, android::IDiagnostics* diag,
    if (parts.size() > 2) {
      diag->Error(android::DiagMessage()
                  << "Invalid feature flag and optional value '" << flag_and_value
                  << "'. Must be in the format 'flag_name[=true|false]");
                  << "'. Must be in the format 'flag_name[:ro][=true|false]");
      return false;
    }

@@ -137,6 +137,25 @@ bool ParseFeatureFlagsParameter(StringPiece arg, android::IDiagnostics* diag,
      diag->Error(android::DiagMessage() << "No name given for one or more flags in: " << arg);
      return false;
    }
    std::vector<std::string> name_parts = util::Split(flag_name, ':');
    if (name_parts.size() > 2) {
      diag->Error(android::DiagMessage()
                  << "Invalid feature flag and optional value '" << flag_and_value
                  << "'. Must be in the format 'flag_name[:ro][=true|false]");
      return false;
    }
    flag_name = name_parts[0];
    bool read_only = false;
    if (name_parts.size() == 2) {
      if (name_parts[1] == "ro") {
        read_only = true;
      } else {
        diag->Error(android::DiagMessage()
                    << "Invalid feature flag and optional value '" << flag_and_value
                    << "'. Must be in the format 'flag_name[:ro][=true|false]");
        return false;
      }
    }

    std::optional<bool> flag_value = {};
    if (parts.size() == 2) {
@@ -151,13 +170,13 @@ bool ParseFeatureFlagsParameter(StringPiece arg, android::IDiagnostics* diag,
      }
    }

    if (auto [it, inserted] =
            out_feature_flag_values->try_emplace(std::string(flag_name), flag_value);
    auto ffp = FeatureFlagProperties{read_only, flag_value};
    if (auto [it, inserted] = out_feature_flag_values->try_emplace(std::string(flag_name), ffp);
        !inserted) {
      // We are allowing the same flag to appear multiple times, last value wins.
      diag->Note(android::DiagMessage()
                 << "Value for feature flag '" << flag_name << "' was given more than once");
      it->second = flag_value;
      it->second = ffp;
    }
  }
  return true;
+11 −1
Original line number Diff line number Diff line
@@ -37,7 +37,17 @@

namespace aapt {

using FeatureFlagValues = std::map<std::string, std::optional<bool>, std::less<>>;
struct FeatureFlagProperties {
  bool read_only;
  std::optional<bool> enabled;

  FeatureFlagProperties(bool ro, std::optional<bool> e) : read_only(ro), enabled(e) {
  }

  bool operator==(const FeatureFlagProperties&) const = default;
};

using FeatureFlagValues = std::map<std::string, FeatureFlagProperties, std::less<>>;

// Parses a configuration density (ex. hdpi, xxhdpi, 234dpi, anydpi, etc).
// Returns Nothing and logs a human friendly error message if the string was not legal.
Loading