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

Commit c04bcb39 authored by Jeremy Meyer's avatar Jeremy Meyer
Browse files

Allow AssetFileDescriptors to be used to create FRROs

Before this change, if a (system) app tried to use an image from its
assets to create an FRRO it would succeed but no image would display.
That is because when it is an asset we have an AssetFileDescriptor which
internally has a file descriptor, offset, and size and the file
descriptor would point at the apk itself. When this would get passed to
the native layer to create the frro only the file descriptor would get
passed so we would copy the whole apk, not just the image.

This allows apps to pass in an AssetFileDescriptor directly which we can
then use to also pass down the offset and size to the native layer and
only copy the image part.

Fixes: 289739832
Test: atest FabricatedOverlayTest
Change-Id: I80dceb19229a6a3c02851a5451ea6d46798981b3
parent 5e483b04
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -265,6 +265,7 @@ Status Idmap2Service::createFabricatedOverlay(
            res.configuration.value_or(std::string()));
    } else if (res.binaryData.has_value()) {
      builder.SetResourceValue(res.resourceName, res.binaryData->get(),
                               res.binaryDataOffset, res.binaryDataSize,
                               res.configuration.value_or(std::string()));
    } else {
      builder.SetResourceValue(res.resourceName, res.dataType, res.data,
+2 −0
Original line number Diff line number Diff line
@@ -26,4 +26,6 @@ parcelable FabricatedOverlayInternalEntry {
    @nullable @utf8InCpp String stringData;
    @nullable ParcelFileDescriptor binaryData;
    @nullable @utf8InCpp String configuration;
    long binaryDataOffset;
    long binaryDataSize;
}
 No newline at end of file
+12 −2
Original line number Diff line number Diff line
@@ -49,6 +49,8 @@ struct FabricatedOverlay {

    Builder& SetResourceValue(const std::string& resource_name,
                              std::optional<android::base::borrowed_fd>&& binary_value,
                              off64_t data_binary_offset,
                              size_t data_binary_size,
                              const std::string& configuration);

    inline Builder& setFrroPath(std::string frro_path) {
@@ -65,6 +67,8 @@ struct FabricatedOverlay {
      DataValue data_value;
      std::string data_string_value;
      std::optional<android::base::borrowed_fd> data_binary_value;
      off64_t data_binary_offset;
      size_t data_binary_size;
      std::string configuration;
    };

@@ -76,6 +80,12 @@ struct FabricatedOverlay {
    std::vector<Entry> entries_;
  };

  struct BinaryData {
    android::base::borrowed_fd file_descriptor;
    off64_t offset;
    size_t size;
  };

  Result<Unit> ToBinaryStream(std::ostream& stream) const;
  static Result<FabricatedOverlay> FromBinaryStream(std::istream& stream);

@@ -92,13 +102,13 @@ struct FabricatedOverlay {

  explicit FabricatedOverlay(pb::FabricatedOverlay&& overlay,
                             std::string&& string_pool_data_,
                             std::vector<android::base::borrowed_fd> binary_files_,
                             std::vector<FabricatedOverlay::BinaryData> binary_files_,
                             off_t total_binary_bytes_,
                             std::optional<uint32_t> crc_from_disk = {});

  pb::FabricatedOverlay overlay_pb_;
  std::string string_pool_data_;
  std::vector<android::base::borrowed_fd> binary_files_;
  std::vector<FabricatedOverlay::BinaryData> binary_files_;
  uint32_t total_binary_bytes_;
  std::optional<uint32_t> crc_from_disk_;
  mutable std::optional<SerializedData> data_;
+2 −0
Original line number Diff line number Diff line
@@ -43,6 +43,8 @@ struct TargetValue {
  DataValue data_value;
  std::string data_string_value;
  std::optional<android::base::borrowed_fd> data_binary_value;
  off64_t data_binary_offset;
  size_t data_binary_size;
};

struct TargetValueWithConfig {
+18 −16
Original line number Diff line number Diff line
@@ -55,7 +55,7 @@ void Write32(std::ostream& stream, uint32_t value) {

FabricatedOverlay::FabricatedOverlay(pb::FabricatedOverlay&& overlay,
                                     std::string&& string_pool_data,
                                     std::vector<android::base::borrowed_fd> binary_files,
                                     std::vector<FabricatedOverlay::BinaryData> binary_files,
                                     off_t total_binary_bytes,
                                     std::optional<uint32_t> crc_from_disk)
    : overlay_pb_(std::forward<pb::FabricatedOverlay>(overlay)),
@@ -81,7 +81,7 @@ FabricatedOverlay::Builder& FabricatedOverlay::Builder::SetResourceValue(
    const std::string& resource_name, uint8_t data_type, uint32_t data_value,
    const std::string& configuration) {
  entries_.emplace_back(
      Entry{resource_name, data_type, data_value, "", std::nullopt, configuration});
      Entry{resource_name, data_type, data_value, "", std::nullopt, 0, 0, configuration});
  return *this;
}

@@ -89,14 +89,15 @@ FabricatedOverlay::Builder& FabricatedOverlay::Builder::SetResourceValue(
    const std::string& resource_name, uint8_t data_type, const std::string& data_string_value,
    const std::string& configuration) {
  entries_.emplace_back(
      Entry{resource_name, data_type, 0, data_string_value, std::nullopt, configuration});
      Entry{resource_name, data_type, 0, data_string_value, std::nullopt, 0, 0, configuration});
  return *this;
}

FabricatedOverlay::Builder& FabricatedOverlay::Builder::SetResourceValue(
    const std::string& resource_name, std::optional<android::base::borrowed_fd>&& binary_value,
    const std::string& configuration) {
  entries_.emplace_back(Entry{resource_name, 0, 0, "", binary_value, configuration});
    off64_t data_binary_offset, size_t data_binary_size, const std::string& configuration) {
  entries_.emplace_back(Entry{resource_name, 0, 0, "", binary_value,
                              data_binary_offset, data_binary_size, configuration});
  return *this;
}

@@ -148,7 +149,8 @@ Result<FabricatedOverlay> FabricatedOverlay::Builder::Build() {
    }

    value->second = TargetValue{res_entry.data_type, res_entry.data_value,
        res_entry.data_string_value, res_entry.data_binary_value};
                                res_entry.data_string_value, res_entry.data_binary_value,
                                res_entry.data_binary_offset, res_entry.data_binary_size};
  }

  pb::FabricatedOverlay overlay_pb;
@@ -157,7 +159,7 @@ Result<FabricatedOverlay> FabricatedOverlay::Builder::Build() {
  overlay_pb.set_target_package_name(target_package_name_);
  overlay_pb.set_target_overlayable(target_overlayable_);

  std::vector<android::base::borrowed_fd> binary_files;
  std::vector<FabricatedOverlay::BinaryData> binary_files;
  size_t total_binary_bytes = 0;
  // 16 for the number of bytes in the frro file before the binary data
  const size_t FRRO_HEADER_SIZE = 16;
@@ -182,16 +184,15 @@ Result<FabricatedOverlay> FabricatedOverlay::Builder::Build() {
            pb_value->set_data_value(ref.index());
          } else if (value.second.data_binary_value.has_value()) {
              pb_value->set_data_type(Res_value::TYPE_STRING);
              struct stat s;
              if (fstat(value.second.data_binary_value->get(), &s) == -1) {
                return Error("unable to get size of binary file: %d", errno);
              }
              std::string uri
                  = StringPrintf("frro:/%s?offset=%d&size=%d", frro_path_.c_str(),
                                 static_cast<int> (FRRO_HEADER_SIZE + total_binary_bytes),
                                 static_cast<int> (s.st_size));
              total_binary_bytes += s.st_size;
              binary_files.emplace_back(value.second.data_binary_value->get());
                                 static_cast<int> (value.second.data_binary_size));
              total_binary_bytes += value.second.data_binary_size;
              binary_files.emplace_back(FabricatedOverlay::BinaryData{
                  value.second.data_binary_value->get(),
                  value.second.data_binary_offset,
                  value.second.data_binary_size});
              auto ref = string_pool.MakeRef(std::move(uri));
              pb_value->set_data_value(ref.index());
          } else {
@@ -310,8 +311,9 @@ Result<Unit> FabricatedOverlay::ToBinaryStream(std::ostream& stream) const {
  Write32(stream, (*data)->pb_crc);
  Write32(stream, total_binary_bytes_);
  std::string file_contents;
  for (const android::base::borrowed_fd fd : binary_files_) {
    if (!ReadFdToString(fd, &file_contents)) {
  for (const FabricatedOverlay::BinaryData fd : binary_files_) {
    file_contents.resize(fd.size);
    if (!ReadFullyAtOffset(fd.file_descriptor, file_contents.data(), fd.size, fd.offset)) {
      return Error("Failed to read binary file data.");
    }
    stream.write(file_contents.data(), file_contents.length());
Loading