diff options
| -rw-r--r-- | cmds/idmap2/idmap2d/Idmap2Service.cpp | 3 | ||||
| -rw-r--r-- | cmds/idmap2/idmap2d/aidl/core/android/os/FabricatedOverlayInternalEntry.aidl | 2 | ||||
| -rw-r--r-- | cmds/idmap2/include/idmap2/FabricatedOverlay.h | 14 | ||||
| -rw-r--r-- | cmds/idmap2/include/idmap2/ResourceUtils.h | 2 | ||||
| -rw-r--r-- | cmds/idmap2/libidmap2/FabricatedOverlay.cpp | 34 | ||||
| -rw-r--r-- | cmds/idmap2/self_targeting/SelfTargeting.cpp | 1 | ||||
| -rw-r--r-- | cmds/idmap2/tests/FabricatedOverlayTests.cpp | 2 | ||||
| -rw-r--r-- | cmds/idmap2/tests/IdmapTests.cpp | 2 | ||||
| -rw-r--r-- | cmds/idmap2/tests/ResourceMappingTests.cpp | 2 | ||||
| -rw-r--r-- | core/api/current.txt | 1 | ||||
| -rw-r--r-- | core/java/android/content/om/FabricatedOverlay.java | 61 | ||||
| -rw-r--r-- | core/jni/com_android_internal_content_om_OverlayManagerImpl.cpp | 15 | ||||
| -rw-r--r-- | libs/androidfw/include/androidfw/ResourceTypes.h | 2 |
13 files changed, 118 insertions, 23 deletions
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp index b94b3b458065..d76ca5bdce42 100644 --- a/cmds/idmap2/idmap2d/Idmap2Service.cpp +++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp @@ -265,7 +265,8 @@ Status Idmap2Service::createFabricatedOverlay( res.configuration.value_or(std::string())); } else if (res.binaryData.has_value()) { builder.SetResourceValue(res.resourceName, res.binaryData->get(), - res.configuration.value_or(std::string())); + res.binaryDataOffset, res.binaryDataSize, + res.configuration.value_or(std::string())); } else { builder.SetResourceValue(res.resourceName, res.dataType, res.data, res.configuration.value_or(std::string())); diff --git a/cmds/idmap2/idmap2d/aidl/core/android/os/FabricatedOverlayInternalEntry.aidl b/cmds/idmap2/idmap2d/aidl/core/android/os/FabricatedOverlayInternalEntry.aidl index 3ad6d58e8253..8ebd454705f0 100644 --- a/cmds/idmap2/idmap2d/aidl/core/android/os/FabricatedOverlayInternalEntry.aidl +++ b/cmds/idmap2/idmap2d/aidl/core/android/os/FabricatedOverlayInternalEntry.aidl @@ -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 diff --git a/cmds/idmap2/include/idmap2/FabricatedOverlay.h b/cmds/idmap2/include/idmap2/FabricatedOverlay.h index a29fa8f3e1ab..1e7d4c28f45c 100644 --- a/cmds/idmap2/include/idmap2/FabricatedOverlay.h +++ b/cmds/idmap2/include/idmap2/FabricatedOverlay.h @@ -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_; diff --git a/cmds/idmap2/include/idmap2/ResourceUtils.h b/cmds/idmap2/include/idmap2/ResourceUtils.h index c2b0abed442c..d4490ef47b25 100644 --- a/cmds/idmap2/include/idmap2/ResourceUtils.h +++ b/cmds/idmap2/include/idmap2/ResourceUtils.h @@ -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 { diff --git a/cmds/idmap2/libidmap2/FabricatedOverlay.cpp b/cmds/idmap2/libidmap2/FabricatedOverlay.cpp index dd5be21cd164..47daf23c6381 100644 --- a/cmds/idmap2/libidmap2/FabricatedOverlay.cpp +++ b/cmds/idmap2/libidmap2/FabricatedOverlay.cpp @@ -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()); diff --git a/cmds/idmap2/self_targeting/SelfTargeting.cpp b/cmds/idmap2/self_targeting/SelfTargeting.cpp index a8aa03309b16..c7f5cf3632c5 100644 --- a/cmds/idmap2/self_targeting/SelfTargeting.cpp +++ b/cmds/idmap2/self_targeting/SelfTargeting.cpp @@ -52,6 +52,7 @@ CreateFrroFile(std::string& out_err_result, const std::string& packageName, const auto dataType = entry_params.data_type; if (entry_params.data_binary_value.has_value()) { builder.SetResourceValue(entry_params.resource_name, *entry_params.data_binary_value, + entry_params.binary_data_offset, entry_params.binary_data_size, entry_params.configuration); } else if (dataType >= Res_value::TYPE_FIRST_INT && dataType <= Res_value::TYPE_LAST_INT) { builder.SetResourceValue(entry_params.resource_name, dataType, diff --git a/cmds/idmap2/tests/FabricatedOverlayTests.cpp b/cmds/idmap2/tests/FabricatedOverlayTests.cpp index e13a0eb5d488..b460bb33f559 100644 --- a/cmds/idmap2/tests/FabricatedOverlayTests.cpp +++ b/cmds/idmap2/tests/FabricatedOverlayTests.cpp @@ -59,7 +59,7 @@ TEST(FabricatedOverlayTests, SetResourceValue) { Res_value::TYPE_STRING, "foobar", "en-rUS-normal-xxhdpi-v21") - .SetResourceValue("com.example.target:drawable/dr1", fd, "port-xxhdpi-v7") + .SetResourceValue("com.example.target:drawable/dr1", fd, 0, 8341, "port-xxhdpi-v7") .setFrroPath("/foo/bar/biz.frro") .Build(); ASSERT_TRUE(overlay); diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp index f6e48ba7a1f4..a3448fda60d9 100644 --- a/cmds/idmap2/tests/IdmapTests.cpp +++ b/cmds/idmap2/tests/IdmapTests.cpp @@ -269,7 +269,7 @@ TEST(IdmapTests, FabricatedOverlay) { .SetResourceValue("integer/int1", Res_value::TYPE_INT_DEC, 2U, "land-xxhdpi-v7") .SetResourceValue("string/str1", Res_value::TYPE_REFERENCE, 0x7f010000, "land") .SetResourceValue("string/str2", Res_value::TYPE_STRING, "foobar", "xxhdpi-v7") - .SetResourceValue("drawable/dr1", fd, "port-xxhdpi-v7") + .SetResourceValue("drawable/dr1", fd, 0, 8341, "port-xxhdpi-v7") .setFrroPath("/foo/bar/biz.frro") .Build(); diff --git a/cmds/idmap2/tests/ResourceMappingTests.cpp b/cmds/idmap2/tests/ResourceMappingTests.cpp index 380e462a3aba..40f98c2f351b 100644 --- a/cmds/idmap2/tests/ResourceMappingTests.cpp +++ b/cmds/idmap2/tests/ResourceMappingTests.cpp @@ -212,7 +212,7 @@ TEST(ResourceMappingTests, FabricatedOverlay) { .SetResourceValue("integer/int1", Res_value::TYPE_INT_DEC, 2U, "") .SetResourceValue("string/str1", Res_value::TYPE_REFERENCE, 0x7f010000, "") .SetResourceValue("string/str2", Res_value::TYPE_STRING, "foobar", "") - .SetResourceValue("drawable/dr1", fd, "") + .SetResourceValue("drawable/dr1", fd, 0, 8341, "") .setFrroPath("/foo/bar/biz.frro") .Build(); diff --git a/core/api/current.txt b/core/api/current.txt index 490195051f6a..0d9633e17376 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -11702,6 +11702,7 @@ package android.content.om { method @NonNull public void setResourceValue(@NonNull String, @IntRange(from=android.util.TypedValue.TYPE_FIRST_INT, to=android.util.TypedValue.TYPE_LAST_INT) int, int, @Nullable String); method @NonNull public void setResourceValue(@NonNull String, int, @NonNull String, @Nullable String); method @NonNull public void setResourceValue(@NonNull String, @NonNull android.os.ParcelFileDescriptor, @Nullable String); + method @NonNull public void setResourceValue(@NonNull String, @NonNull android.content.res.AssetFileDescriptor, @Nullable String); method public void setTargetOverlayable(@Nullable String); } diff --git a/core/java/android/content/om/FabricatedOverlay.java b/core/java/android/content/om/FabricatedOverlay.java index 7e787c9c3a8c..c4547b8acc2b 100644 --- a/core/java/android/content/om/FabricatedOverlay.java +++ b/core/java/android/content/om/FabricatedOverlay.java @@ -20,6 +20,7 @@ import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; +import android.content.res.AssetFileDescriptor; import android.os.FabricatedOverlayInternal; import android.os.FabricatedOverlayInternalEntry; import android.os.ParcelFileDescriptor; @@ -269,7 +270,7 @@ public class FabricatedOverlay { * @param configuration The string representation of the config this overlay is enabled for * @return the builder itself * @deprecated Framework should use {@link FabricatedOverlay#setResourceValue(String, - ParcelFileDescriptor, String)} instead. + ParcelFileDescriptor, String)} instead. * @hide */ @Deprecated(since = "Please use FabricatedOverlay#setResourceValue instead") @@ -285,6 +286,30 @@ public class FabricatedOverlay { } /** + * Sets the value of the fabricated overlay for the file descriptor type. + * + * @param resourceName name of the target resource to overlay (in the form + * [package]:type/entry) + * @param value the file descriptor whose contents are the value of the frro + * @param configuration The string representation of the config this overlay is enabled for + * @return the builder itself + * @deprecated Framework should use {@link FabricatedOverlay#setResourceValue(String, + ParcelFileDescriptor, String)} instead. + * @hide + */ + @Deprecated(since = "Please use FabricatedOverlay#setResourceValue instead") + @NonNull + public Builder setResourceValue( + @NonNull String resourceName, + @NonNull AssetFileDescriptor value, + @Nullable String configuration) { + ensureValidResourceName(resourceName); + mEntries.add( + generateFabricatedOverlayInternalEntry(resourceName, value, configuration)); + return this; + } + + /** * Builds an immutable fabricated overlay. * * @return the fabricated overlay @@ -421,6 +446,21 @@ public class FabricatedOverlay { entry.resourceName = resourceName; entry.binaryData = Objects.requireNonNull(parcelFileDescriptor); entry.configuration = configuration; + entry.binaryDataOffset = 0; + entry.binaryDataSize = parcelFileDescriptor.getStatSize(); + return entry; + } + + @NonNull + private static FabricatedOverlayInternalEntry generateFabricatedOverlayInternalEntry( + @NonNull String resourceName, @NonNull AssetFileDescriptor assetFileDescriptor, + @Nullable String configuration) { + final FabricatedOverlayInternalEntry entry = new FabricatedOverlayInternalEntry(); + entry.resourceName = resourceName; + entry.binaryData = Objects.requireNonNull(assetFileDescriptor.getParcelFileDescriptor()); + entry.binaryDataOffset = assetFileDescriptor.getStartOffset(); + entry.binaryDataSize = assetFileDescriptor.getLength(); + entry.configuration = configuration; return entry; } @@ -495,4 +535,23 @@ public class FabricatedOverlay { mOverlay.entries.add( generateFabricatedOverlayInternalEntry(resourceName, value, configuration)); } + + /** + * Sets the resource value in the fabricated overlay for the file descriptor type with the + * configuration. + * + * @param resourceName name of the target resource to overlay (in the form + * [package]:type/entry) + * @param value the file descriptor whose contents are the value of the frro + * @param configuration The string representation of the config this overlay is enabled for + */ + @NonNull + public void setResourceValue( + @NonNull String resourceName, + @NonNull AssetFileDescriptor value, + @Nullable String configuration) { + ensureValidResourceName(resourceName); + mOverlay.entries.add( + generateFabricatedOverlayInternalEntry(resourceName, value, configuration)); + } } diff --git a/core/jni/com_android_internal_content_om_OverlayManagerImpl.cpp b/core/jni/com_android_internal_content_om_OverlayManagerImpl.cpp index bba1760bc45c..d4f6e1868695 100644 --- a/core/jni/com_android_internal_content_om_OverlayManagerImpl.cpp +++ b/core/jni/com_android_internal_content_om_OverlayManagerImpl.cpp @@ -44,6 +44,8 @@ static struct fabricated_overlay_internal_entry_offsets_t { jfieldID stringData; jfieldID binaryData; jfieldID configuration; + jfieldID binaryDataOffset; + jfieldID binaryDataSize; } gFabricatedOverlayInternalEntryOffsets; static struct parcel_file_descriptor_offsets_t { @@ -281,10 +283,17 @@ static void CreateFrroFile(JNIEnv* env, jclass /*clazz*/, jstring jsFrroFilePath auto binary_data = getNullableFileDescriptor(env, entry, gFabricatedOverlayInternalEntryOffsets.binaryData); + + const auto data_offset = + env->GetLongField(entry, gFabricatedOverlayInternalEntryOffsets.binaryDataOffset); + const auto data_size = + env->GetLongField(entry, gFabricatedOverlayInternalEntryOffsets.binaryDataSize); entries_params.push_back( FabricatedOverlayEntryParameters{resourceName.c_str(), (DataType)dataType, (DataValue)data, string_data.value_or(std::string()), binary_data, + static_cast<off64_t>(data_offset), + static_cast<size_t>(data_size), configuration.value_or(std::string())}); ALOGV("resourceName = %s, dataType = 0x%08x, data = 0x%08x, dataString = %s," " binaryData = %d, configuration = %s", @@ -440,6 +449,12 @@ int register_com_android_internal_content_om_OverlayManagerImpl(JNIEnv* env) { gFabricatedOverlayInternalEntryOffsets.configuration = GetFieldIDOrDie(env, gFabricatedOverlayInternalEntryOffsets.classObject, "configuration", "Ljava/lang/String;"); + gFabricatedOverlayInternalEntryOffsets.binaryDataOffset = + GetFieldIDOrDie(env, gFabricatedOverlayInternalEntryOffsets.classObject, + "binaryDataOffset", "J"); + gFabricatedOverlayInternalEntryOffsets.binaryDataSize = + GetFieldIDOrDie(env, gFabricatedOverlayInternalEntryOffsets.classObject, + "binaryDataSize", "J"); jclass parcelFileDescriptorClass = android::FindClassOrDie(env, "android/os/ParcelFileDescriptor"); diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h index 52666ab8d1d5..fdb355192676 100644 --- a/libs/androidfw/include/androidfw/ResourceTypes.h +++ b/libs/androidfw/include/androidfw/ResourceTypes.h @@ -1872,6 +1872,8 @@ struct FabricatedOverlayEntryParameters { DataValue data_value; std::string data_string_value; std::optional<android::base::borrowed_fd> data_binary_value; + off64_t binary_data_offset; + size_t binary_data_size; std::string configuration; }; |