Merge changes from topic "idmap2-prerequisites"
* changes: AssetManager2: optionally keep non-matching configs AAPT2: optionally keep resources without default value libandroidfw: add resource ID iterator
This commit is contained in:
@@ -20,4 +20,6 @@ LOCAL_PACKAGE_NAME := OverlayDeviceTests_AppOverlayOne
|
||||
LOCAL_SDK_VERSION := current
|
||||
LOCAL_COMPATIBILITY_SUITE := device-tests
|
||||
LOCAL_CERTIFICATE := platform
|
||||
LOCAL_USE_AAPT2 := true
|
||||
LOCAL_AAPT_FLAGS := --no-resource-removal
|
||||
include $(BUILD_PACKAGE)
|
||||
|
||||
@@ -20,4 +20,6 @@ LOCAL_PACKAGE_NAME := OverlayDeviceTests_AppOverlayTwo
|
||||
LOCAL_SDK_VERSION := current
|
||||
LOCAL_COMPATIBILITY_SUITE := device-tests
|
||||
LOCAL_CERTIFICATE := platform
|
||||
LOCAL_USE_AAPT2 := true
|
||||
LOCAL_AAPT_FLAGS := --no-resource-removal
|
||||
include $(BUILD_PACKAGE)
|
||||
|
||||
@@ -20,4 +20,6 @@ LOCAL_PACKAGE_NAME := OverlayDeviceTests_FrameworkOverlay
|
||||
LOCAL_SDK_VERSION := current
|
||||
LOCAL_COMPATIBILITY_SUITE := device-tests
|
||||
LOCAL_CERTIFICATE := platform
|
||||
LOCAL_USE_AAPT2 := true
|
||||
LOCAL_AAPT_FLAGS := --no-resource-removal
|
||||
include $(BUILD_PACKAGE)
|
||||
|
||||
@@ -21,6 +21,8 @@ LOCAL_PACKAGE_NAME := OverlayHostTests_UpdateOverlay
|
||||
LOCAL_SDK_VERSION := current
|
||||
LOCAL_COMPATIBILITY_SUITE := general-tests
|
||||
LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
|
||||
LOCAL_USE_AAPT2 := true
|
||||
LOCAL_AAPT_FLAGS := --no-resource-removal
|
||||
include $(BUILD_PACKAGE)
|
||||
|
||||
my_package_prefix := com.android.server.om.hosttest.framework_overlay
|
||||
|
||||
@@ -67,10 +67,10 @@ AssetManager2::AssetManager2() {
|
||||
}
|
||||
|
||||
bool AssetManager2::SetApkAssets(const std::vector<const ApkAssets*>& apk_assets,
|
||||
bool invalidate_caches) {
|
||||
bool invalidate_caches, bool filter_incompatible_configs) {
|
||||
apk_assets_ = apk_assets;
|
||||
BuildDynamicRefTable();
|
||||
RebuildFilterList();
|
||||
RebuildFilterList(filter_incompatible_configs);
|
||||
if (invalidate_caches) {
|
||||
InvalidateCaches(static_cast<uint32_t>(-1));
|
||||
}
|
||||
@@ -825,7 +825,7 @@ uint32_t AssetManager2::GetResourceId(const std::string& resource_name,
|
||||
return 0u;
|
||||
}
|
||||
|
||||
void AssetManager2::RebuildFilterList() {
|
||||
void AssetManager2::RebuildFilterList(bool filter_incompatible_configs) {
|
||||
for (PackageGroup& group : package_groups_) {
|
||||
for (ConfiguredPackage& impl : group.packages_) {
|
||||
// Destroy it.
|
||||
@@ -841,7 +841,7 @@ void AssetManager2::RebuildFilterList() {
|
||||
for (auto iter = spec->types; iter != iter_end; ++iter) {
|
||||
ResTable_config this_config;
|
||||
this_config.copyFromDtoH((*iter)->config);
|
||||
if (this_config.match(configuration_)) {
|
||||
if (!filter_incompatible_configs || this_config.match(configuration_)) {
|
||||
group.configurations.push_back(this_config);
|
||||
group.types.push_back(*iter);
|
||||
}
|
||||
|
||||
@@ -203,6 +203,39 @@ static bool VerifyResTableEntry(const ResTable_type* type, uint32_t entry_offset
|
||||
return true;
|
||||
}
|
||||
|
||||
LoadedPackage::iterator::iterator(const LoadedPackage* lp, size_t ti, size_t ei)
|
||||
: loadedPackage_(lp),
|
||||
typeIndex_(ti),
|
||||
entryIndex_(ei),
|
||||
typeIndexEnd_(lp->resource_ids_.size() + 1) {
|
||||
while (typeIndex_ < typeIndexEnd_ && loadedPackage_->resource_ids_[typeIndex_] == 0) {
|
||||
typeIndex_++;
|
||||
}
|
||||
}
|
||||
|
||||
LoadedPackage::iterator& LoadedPackage::iterator::operator++() {
|
||||
while (typeIndex_ < typeIndexEnd_) {
|
||||
if (entryIndex_ + 1 < loadedPackage_->resource_ids_[typeIndex_]) {
|
||||
entryIndex_++;
|
||||
break;
|
||||
}
|
||||
entryIndex_ = 0;
|
||||
typeIndex_++;
|
||||
if (typeIndex_ < typeIndexEnd_ && loadedPackage_->resource_ids_[typeIndex_] != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint32_t LoadedPackage::iterator::operator*() const {
|
||||
if (typeIndex_ >= typeIndexEnd_) {
|
||||
return 0;
|
||||
}
|
||||
return make_resid(loadedPackage_->package_id_, typeIndex_ + loadedPackage_->type_id_offset_,
|
||||
entryIndex_);
|
||||
}
|
||||
|
||||
const ResTable_entry* LoadedPackage::GetEntry(const ResTable_type* type_chunk,
|
||||
uint16_t entry_index) {
|
||||
uint32_t entry_offset = GetEntryOffset(type_chunk, entry_index);
|
||||
@@ -488,6 +521,7 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk,
|
||||
std::unique_ptr<TypeSpecPtrBuilder>& builder_ptr = type_builder_map[type_spec->id - 1];
|
||||
if (builder_ptr == nullptr) {
|
||||
builder_ptr = util::make_unique<TypeSpecPtrBuilder>(type_spec, idmap_entry_header);
|
||||
loaded_package->resource_ids_.set(type_spec->id, entry_count);
|
||||
} else {
|
||||
LOG(WARNING) << StringPrintf("RES_TABLE_TYPE_SPEC_TYPE already defined for ID %02x",
|
||||
type_spec->id);
|
||||
|
||||
@@ -96,7 +96,12 @@ class AssetManager2 {
|
||||
// Only pass invalidate_caches=false when it is known that the structure
|
||||
// change in ApkAssets is due to a safe addition of resources with completely
|
||||
// new resource IDs.
|
||||
bool SetApkAssets(const std::vector<const ApkAssets*>& apk_assets, bool invalidate_caches = true);
|
||||
//
|
||||
// Only pass in filter_incompatible_configs=false when you want to load all
|
||||
// configurations (including incompatible ones) such as when constructing an
|
||||
// idmap.
|
||||
bool SetApkAssets(const std::vector<const ApkAssets*>& apk_assets, bool invalidate_caches = true,
|
||||
bool filter_incompatible_configs = true);
|
||||
|
||||
inline const std::vector<const ApkAssets*> GetApkAssets() const {
|
||||
return apk_assets_;
|
||||
@@ -274,7 +279,7 @@ class AssetManager2 {
|
||||
|
||||
// Triggers the re-construction of lists of types that match the set configuration.
|
||||
// This should always be called when mutating the AssetManager's configuration or ApkAssets set.
|
||||
void RebuildFilterList();
|
||||
void RebuildFilterList(bool filter_incompatible_configs = true);
|
||||
|
||||
// AssetManager2::GetBag(resid) wraps this function to track which resource ids have already
|
||||
// been seen while traversing bag parents.
|
||||
|
||||
@@ -78,6 +78,55 @@ using TypeSpecPtr = util::unique_cptr<TypeSpec>;
|
||||
|
||||
class LoadedPackage {
|
||||
public:
|
||||
class iterator {
|
||||
public:
|
||||
iterator& operator=(const iterator& rhs) {
|
||||
loadedPackage_ = rhs.loadedPackage_;
|
||||
typeIndex_ = rhs.typeIndex_;
|
||||
entryIndex_ = rhs.entryIndex_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const iterator& rhs) const {
|
||||
return loadedPackage_ == rhs.loadedPackage_ &&
|
||||
typeIndex_ == rhs.typeIndex_ &&
|
||||
entryIndex_ == rhs.entryIndex_;
|
||||
}
|
||||
|
||||
bool operator!=(const iterator& rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
iterator operator++(int) {
|
||||
size_t prevTypeIndex_ = typeIndex_;
|
||||
size_t prevEntryIndex_ = entryIndex_;
|
||||
operator++();
|
||||
return iterator(loadedPackage_, prevTypeIndex_, prevEntryIndex_);
|
||||
}
|
||||
|
||||
iterator& operator++();
|
||||
|
||||
uint32_t operator*() const;
|
||||
|
||||
private:
|
||||
friend class LoadedPackage;
|
||||
|
||||
iterator(const LoadedPackage* lp, size_t ti, size_t ei);
|
||||
|
||||
const LoadedPackage* loadedPackage_;
|
||||
size_t typeIndex_;
|
||||
size_t entryIndex_;
|
||||
const size_t typeIndexEnd_; // STL style end, so one past the last element
|
||||
};
|
||||
|
||||
iterator begin() const {
|
||||
return iterator(this, 0, 0);
|
||||
}
|
||||
|
||||
iterator end() const {
|
||||
return iterator(this, resource_ids_.size() + 1, 0);
|
||||
}
|
||||
|
||||
static std::unique_ptr<const LoadedPackage> Load(const Chunk& chunk,
|
||||
const LoadedIdmap* loaded_idmap, bool system,
|
||||
bool load_as_shared_library);
|
||||
@@ -182,6 +231,7 @@ class LoadedPackage {
|
||||
bool overlay_ = false;
|
||||
|
||||
ByteBucketArray<TypeSpecPtr> type_specs_;
|
||||
ByteBucketArray<uint32_t> resource_ids_;
|
||||
std::vector<DynamicPackageEntry> dynamic_package_map_;
|
||||
};
|
||||
|
||||
|
||||
@@ -278,4 +278,52 @@ TEST(LoadedArscTest, LoadOverlay) {
|
||||
// sizeof(Res_value) might not be backwards compatible.
|
||||
TEST(LoadedArscTest, LoadingShouldBeForwardsAndBackwardsCompatible) { ASSERT_TRUE(false); }
|
||||
|
||||
TEST(LoadedArscTest, ResourceIdentifierIterator) {
|
||||
std::string contents;
|
||||
ASSERT_TRUE(
|
||||
ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk", "resources.arsc", &contents));
|
||||
|
||||
std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
|
||||
ASSERT_NE(nullptr, loaded_arsc);
|
||||
|
||||
const std::vector<std::unique_ptr<const LoadedPackage>>& packages = loaded_arsc->GetPackages();
|
||||
ASSERT_EQ(1u, packages.size());
|
||||
EXPECT_EQ(std::string("com.android.basic"), packages[0]->GetPackageName());
|
||||
|
||||
const auto& loaded_package = packages[0];
|
||||
auto iter = loaded_package->begin();
|
||||
auto end = loaded_package->end();
|
||||
|
||||
ASSERT_NE(end, iter);
|
||||
ASSERT_EQ(0x7f010000u, *iter++);
|
||||
ASSERT_EQ(0x7f010001u, *iter++);
|
||||
ASSERT_EQ(0x7f020000u, *iter++);
|
||||
ASSERT_EQ(0x7f020001u, *iter++);
|
||||
ASSERT_EQ(0x7f030000u, *iter++);
|
||||
ASSERT_EQ(0x7f030001u, *iter++);
|
||||
ASSERT_EQ(0x7f030002u, *iter++); // note: string without default, excluded by aapt2 dump
|
||||
ASSERT_EQ(0x7f040000u, *iter++);
|
||||
ASSERT_EQ(0x7f040001u, *iter++);
|
||||
ASSERT_EQ(0x7f040002u, *iter++);
|
||||
ASSERT_EQ(0x7f040003u, *iter++);
|
||||
ASSERT_EQ(0x7f040004u, *iter++);
|
||||
ASSERT_EQ(0x7f040005u, *iter++);
|
||||
ASSERT_EQ(0x7f040006u, *iter++);
|
||||
ASSERT_EQ(0x7f040007u, *iter++);
|
||||
ASSERT_EQ(0x7f040008u, *iter++);
|
||||
ASSERT_EQ(0x7f040009u, *iter++);
|
||||
ASSERT_EQ(0x7f04000au, *iter++);
|
||||
ASSERT_EQ(0x7f04000bu, *iter++);
|
||||
ASSERT_EQ(0x7f04000cu, *iter++);
|
||||
ASSERT_EQ(0x7f04000du, *iter++);
|
||||
ASSERT_EQ(0x7f050000u, *iter++);
|
||||
ASSERT_EQ(0x7f050001u, *iter++);
|
||||
ASSERT_EQ(0x7f060000u, *iter++);
|
||||
ASSERT_EQ(0x7f070000u, *iter++);
|
||||
ASSERT_EQ(0x7f070001u, *iter++);
|
||||
ASSERT_EQ(0x7f070002u, *iter++);
|
||||
ASSERT_EQ(0x7f070003u, *iter++);
|
||||
ASSERT_EQ(end, iter);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
|
||||
@@ -105,6 +105,7 @@ struct LinkOptions {
|
||||
bool no_version_vectors = false;
|
||||
bool no_version_transitions = false;
|
||||
bool no_resource_deduping = false;
|
||||
bool no_resource_removal = false;
|
||||
bool no_xml_namespaces = false;
|
||||
bool do_not_compress_anything = false;
|
||||
std::unordered_set<std::string> extensions_to_not_compress;
|
||||
@@ -1806,10 +1807,12 @@ class LinkCommand {
|
||||
|
||||
// Before we process anything, remove the resources whose default values don't exist.
|
||||
// We want to force any references to these to fail the build.
|
||||
if (!NoDefaultResourceRemover{}.Consume(context_, &final_table_)) {
|
||||
context_->GetDiagnostics()->Error(DiagMessage()
|
||||
<< "failed removing resources with no defaults");
|
||||
return 1;
|
||||
if (!options_.no_resource_removal) {
|
||||
if (!NoDefaultResourceRemover{}.Consume(context_, &final_table_)) {
|
||||
context_->GetDiagnostics()->Error(DiagMessage()
|
||||
<< "failed removing resources with no defaults");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
ReferenceLinker linker;
|
||||
@@ -2084,6 +2087,10 @@ int Link(const std::vector<StringPiece>& args, IDiagnostics* diagnostics) {
|
||||
"Disables automatic deduping of resources with\n"
|
||||
"identical values across compatible configurations.",
|
||||
&options.no_resource_deduping)
|
||||
.OptionalSwitch("--no-resource-removal",
|
||||
"Disables automatic removal of resources without defaults. Use this only\n"
|
||||
"when building runtime resource overlay packages.",
|
||||
&options.no_resource_removal)
|
||||
.OptionalSwitch("--enable-sparse-encoding",
|
||||
"Enables encoding sparse entries using a binary search tree.\n"
|
||||
"This decreases APK size at the cost of resource retrieval performance.",
|
||||
|
||||
Reference in New Issue
Block a user