Store frro configs in idmap file
This also includes the change to use the configs to decide which (if
any) frros to use at runtime
Bug: 243066074
Test: Manual, updated and created automated tests
Change-Id: I3f1d23e2958ad170799880b9f5eb5bd8ceb1fa67
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index 39c7d19..235700b 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -601,10 +601,6 @@
return base::unexpected(result.error());
}
- if (type_idx == 0x1c) {
- LOG(ERROR) << base::StringPrintf("foobar first result %s", result->package_name->c_str());
- }
-
bool overlaid = false;
if (!stop_at_first_match && !ignore_configuration && !apk_assets_[result->cookie]->IsLoader()) {
for (const auto& id_map : package_group.overlays_) {
@@ -615,7 +611,21 @@
}
if (overlay_entry.IsInlineValue()) {
// The target resource is overlaid by an inline value not represented by a resource.
- result->entry = overlay_entry.GetInlineValue();
+ ConfigDescription best_frro_config;
+ Res_value best_frro_value;
+ bool frro_found = false;
+ for( const auto& [config, value] : overlay_entry.GetInlineValue()) {
+ if ((!frro_found || config.isBetterThan(best_frro_config, desired_config))
+ && config.match(*desired_config)) {
+ frro_found = true;
+ best_frro_config = config;
+ best_frro_value = value;
+ }
+ }
+ if (!frro_found) {
+ continue;
+ }
+ result->entry = best_frro_value;
result->dynamic_ref_table = id_map.overlay_res_maps_.GetOverlayDynamicRefTable();
result->cookie = id_map.cookie;
diff --git a/libs/androidfw/Idmap.cpp b/libs/androidfw/Idmap.cpp
index efd1f6a..e122d48 100644
--- a/libs/androidfw/Idmap.cpp
+++ b/libs/androidfw/Idmap.cpp
@@ -56,6 +56,8 @@
struct Idmap_data_header {
uint32_t target_entry_count;
uint32_t target_inline_entry_count;
+ uint32_t target_inline_entry_value_count;
+ uint32_t configuration_count;
uint32_t overlay_entry_count;
uint32_t string_pool_index_offset;
@@ -68,6 +70,12 @@
struct Idmap_target_entry_inline {
uint32_t target_id;
+ uint32_t start_value_index;
+ uint32_t value_count;
+};
+
+struct Idmap_target_entry_inline_value {
+ uint32_t config_index;
Res_value value;
};
@@ -138,11 +146,15 @@
IdmapResMap::IdmapResMap(const Idmap_data_header* data_header,
const Idmap_target_entry* entries,
const Idmap_target_entry_inline* inline_entries,
+ const Idmap_target_entry_inline_value* inline_entry_values,
+ const ConfigDescription* configs,
uint8_t target_assigned_package_id,
const OverlayDynamicRefTable* overlay_ref_table)
: data_header_(data_header),
entries_(entries),
inline_entries_(inline_entries),
+ inline_entry_values_(inline_entry_values),
+ configurations_(configs),
target_assigned_package_id_(target_assigned_package_id),
overlay_ref_table_(overlay_ref_table) { }
@@ -183,7 +195,13 @@
if (inline_entry != end_inline_entry &&
(0x00FFFFFFU & dtohl(inline_entry->target_id)) == target_res_id) {
- return Result(inline_entry->value);
+ std::map<ConfigDescription, Res_value> values_map;
+ for (int i = 0; i < inline_entry->value_count; i++) {
+ const auto& value = inline_entry_values_[inline_entry->start_value_index + i];
+ const auto& config = configurations_[value.config_index];
+ values_map[config] = value.value;
+ }
+ return Result(values_map);
}
return {};
}
@@ -237,6 +255,8 @@
const Idmap_data_header* data_header,
const Idmap_target_entry* target_entries,
const Idmap_target_entry_inline* target_inline_entries,
+ const Idmap_target_entry_inline_value* inline_entry_values,
+ const ConfigDescription* configs,
const Idmap_overlay_entry* overlay_entries,
std::unique_ptr<ResStringPool>&& string_pool,
std::string_view overlay_apk_path,
@@ -245,6 +265,8 @@
data_header_(data_header),
target_entries_(target_entries),
target_inline_entries_(target_inline_entries),
+ inline_entry_values_(inline_entry_values),
+ configurations_(configs),
overlay_entries_(overlay_entries),
string_pool_(std::move(string_pool)),
idmap_path_(std::move(idmap_path)),
@@ -303,6 +325,21 @@
if (target_inline_entries == nullptr) {
return {};
}
+
+ auto target_inline_entry_values = ReadType<Idmap_target_entry_inline_value>(
+ &data_ptr, &data_size, "target inline values",
+ dtohl(data_header->target_inline_entry_value_count));
+ if (target_inline_entry_values == nullptr) {
+ return {};
+ }
+
+ auto configurations = ReadType<ConfigDescription>(
+ &data_ptr, &data_size, "configurations",
+ dtohl(data_header->configuration_count));
+ if (configurations == nullptr) {
+ return {};
+ }
+
auto overlay_entries = ReadType<Idmap_overlay_entry>(&data_ptr, &data_size, "target inline",
dtohl(data_header->overlay_entry_count));
if (overlay_entries == nullptr) {
@@ -329,8 +366,8 @@
// Can't use make_unique because LoadedIdmap constructor is private.
return std::unique_ptr<LoadedIdmap>(
new LoadedIdmap(idmap_path.to_string(), header, data_header, target_entries,
- target_inline_entries, overlay_entries, std::move(idmap_string_pool),
- *target_path, *overlay_path));
+ target_inline_entries, target_inline_entry_values, configurations,
+ overlay_entries, std::move(idmap_string_pool), *target_path, *overlay_path));
}
bool LoadedIdmap::IsUpToDate() const {
diff --git a/libs/androidfw/include/androidfw/Idmap.h b/libs/androidfw/include/androidfw/Idmap.h
index 6804472..a1cbbbf 100644
--- a/libs/androidfw/include/androidfw/Idmap.h
+++ b/libs/androidfw/include/androidfw/Idmap.h
@@ -23,6 +23,7 @@
#include <variant>
#include "android-base/macros.h"
+#include "androidfw/ConfigDescription.h"
#include "androidfw/StringPiece.h"
#include "androidfw/ResourceTypes.h"
#include "utils/ByteOrder.h"
@@ -35,6 +36,7 @@
struct Idmap_data_header;
struct Idmap_target_entry;
struct Idmap_target_entry_inline;
+struct Idmap_target_entry_inline_value;
struct Idmap_overlay_entry;
// A string pool for overlay apk assets. The string pool holds the strings of the overlay resources
@@ -91,7 +93,8 @@
public:
Result() = default;
explicit Result(uint32_t value) : data_(value) {};
- explicit Result(const Res_value& value) : data_(value) { };
+ explicit Result(const std::map<ConfigDescription, Res_value> &value)
+ : data_(value) { };
// Returns `true` if the resource is overlaid.
explicit operator bool() const {
@@ -107,15 +110,16 @@
}
bool IsInlineValue() const {
- return std::get_if<Res_value>(&data_) != nullptr;
+ return std::get_if<2>(&data_) != nullptr;
}
- const Res_value& GetInlineValue() const {
- return std::get<Res_value>(data_);
+ const std::map<ConfigDescription, Res_value>& GetInlineValue() const {
+ return std::get<2>(data_);
}
private:
- std::variant<std::monostate, uint32_t, Res_value> data_;
+ std::variant<std::monostate, uint32_t,
+ std::map<ConfigDescription, Res_value> > data_;
};
// Looks up the value that overlays the target resource id.
@@ -129,12 +133,16 @@
explicit IdmapResMap(const Idmap_data_header* data_header,
const Idmap_target_entry* entries,
const Idmap_target_entry_inline* inline_entries,
+ const Idmap_target_entry_inline_value* inline_entry_values,
+ const ConfigDescription* configs,
uint8_t target_assigned_package_id,
const OverlayDynamicRefTable* overlay_ref_table);
const Idmap_data_header* data_header_;
const Idmap_target_entry* entries_;
const Idmap_target_entry_inline* inline_entries_;
+ const Idmap_target_entry_inline_value* inline_entry_values_;
+ const ConfigDescription* configurations_;
const uint8_t target_assigned_package_id_;
const OverlayDynamicRefTable* overlay_ref_table_;
@@ -170,8 +178,8 @@
// Returns a mapping from target resource ids to overlay values.
const IdmapResMap GetTargetResourcesMap(uint8_t target_assigned_package_id,
const OverlayDynamicRefTable* overlay_ref_table) const {
- return IdmapResMap(data_header_, target_entries_, target_inline_entries_,
- target_assigned_package_id, overlay_ref_table);
+ return IdmapResMap(data_header_, target_entries_, target_inline_entries_, inline_entry_values_,
+ configurations_, target_assigned_package_id, overlay_ref_table);
}
// Returns a dynamic reference table for a loaded overlay package.
@@ -191,6 +199,8 @@
const Idmap_data_header* data_header_;
const Idmap_target_entry* target_entries_;
const Idmap_target_entry_inline* target_inline_entries_;
+ const Idmap_target_entry_inline_value* inline_entry_values_;
+ const ConfigDescription* configurations_;
const Idmap_overlay_entry* overlay_entries_;
const std::unique_ptr<ResStringPool> string_pool_;
@@ -207,6 +217,8 @@
const Idmap_data_header* data_header,
const Idmap_target_entry* target_entries,
const Idmap_target_entry_inline* target_inline_entries,
+ const Idmap_target_entry_inline_value* inline_entry_values_,
+ const ConfigDescription* configs,
const Idmap_overlay_entry* overlay_entries,
std::unique_ptr<ResStringPool>&& string_pool,
std::string_view overlay_apk_path,
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index 8c614bc..9309091 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -45,7 +45,7 @@
namespace android {
constexpr const uint32_t kIdmapMagic = 0x504D4449u;
-constexpr const uint32_t kIdmapCurrentVersion = 0x00000008u;
+constexpr const uint32_t kIdmapCurrentVersion = 0x00000009u;
// This must never change.
constexpr const uint32_t kFabricatedOverlayMagic = 0x4f525246; // FRRO (big endian)
@@ -1098,7 +1098,7 @@
SDKVERSION_ANY = 0
};
- enum {
+ enum {
MINORVERSION_ANY = 0
};
diff --git a/libs/androidfw/tests/data/overlay/overlay.idmap b/libs/androidfw/tests/data/overlay/overlay.idmap
index 88eadcc..8e847e8 100644
--- a/libs/androidfw/tests/data/overlay/overlay.idmap
+++ b/libs/androidfw/tests/data/overlay/overlay.idmap
Binary files differ