| /* |
| * Copyright (C) 2017 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "test/Builders.h" |
| |
| #include "Diagnostics.h" |
| #include "android-base/logging.h" |
| #include "androidfw/StringPiece.h" |
| #include "io/StringStream.h" |
| #include "test/Common.h" |
| #include "util/Util.h" |
| |
| using ::aapt::configuration::Abi; |
| using ::aapt::configuration::AndroidSdk; |
| using ::aapt::configuration::ConfiguredArtifact; |
| using ::aapt::configuration::GetOrCreateGroup; |
| using ::aapt::io::StringInputStream; |
| using ::android::ConfigDescription; |
| using ::android::StringPiece; |
| |
| namespace aapt { |
| namespace test { |
| |
| ResourceTableBuilder& ResourceTableBuilder::AddSimple(StringPiece name, const ResourceId& id) { |
| return AddValue(name, id, util::make_unique<Id>()); |
| } |
| |
| ResourceTableBuilder& ResourceTableBuilder::AddSimple(StringPiece name, |
| const ConfigDescription& config, |
| const ResourceId& id) { |
| return AddValue(name, config, id, util::make_unique<Id>()); |
| } |
| |
| ResourceTableBuilder& ResourceTableBuilder::AddReference(StringPiece name, StringPiece ref) { |
| return AddReference(name, {}, ref); |
| } |
| |
| ResourceTableBuilder& ResourceTableBuilder::AddReference(StringPiece name, const ResourceId& id, |
| StringPiece ref) { |
| return AddValue(name, id, util::make_unique<Reference>(ParseNameOrDie(ref))); |
| } |
| |
| ResourceTableBuilder& ResourceTableBuilder::AddString(StringPiece name, StringPiece str) { |
| return AddString(name, {}, str); |
| } |
| |
| ResourceTableBuilder& ResourceTableBuilder::AddString(StringPiece name, const ResourceId& id, |
| StringPiece str) { |
| return AddValue(name, id, util::make_unique<String>(table_->string_pool.MakeRef(str))); |
| } |
| |
| ResourceTableBuilder& ResourceTableBuilder::AddString(StringPiece name, const ResourceId& id, |
| const ConfigDescription& config, |
| StringPiece str) { |
| return AddValue(name, config, id, util::make_unique<String>(table_->string_pool.MakeRef(str))); |
| } |
| |
| ResourceTableBuilder& ResourceTableBuilder::AddFileReference(StringPiece name, StringPiece path, |
| io::IFile* file) { |
| return AddFileReference(name, {}, path, file); |
| } |
| |
| ResourceTableBuilder& ResourceTableBuilder::AddFileReference(StringPiece name, const ResourceId& id, |
| StringPiece path, io::IFile* file) { |
| auto file_ref = util::make_unique<FileReference>(table_->string_pool.MakeRef(path)); |
| file_ref->file = file; |
| return AddValue(name, id, std::move(file_ref)); |
| } |
| |
| ResourceTableBuilder& ResourceTableBuilder::AddFileReference(StringPiece name, StringPiece path, |
| const ConfigDescription& config, |
| io::IFile* file) { |
| auto file_ref = util::make_unique<FileReference>(table_->string_pool.MakeRef(path)); |
| file_ref->file = file; |
| return AddValue(name, config, {}, std::move(file_ref)); |
| } |
| |
| ResourceTableBuilder& ResourceTableBuilder::AddValue(StringPiece name, |
| std::unique_ptr<Value> value) { |
| return AddValue(name, {}, std::move(value)); |
| } |
| |
| ResourceTableBuilder& ResourceTableBuilder::AddValue(StringPiece name, const ResourceId& id, |
| std::unique_ptr<Value> value) { |
| return AddValue(name, {}, id, std::move(value)); |
| } |
| |
| ResourceTableBuilder& ResourceTableBuilder::AddValue(StringPiece name, |
| const ConfigDescription& config, |
| const ResourceId& id, |
| std::unique_ptr<Value> value) { |
| ResourceName res_name = ParseNameOrDie(name); |
| NewResourceBuilder builder(res_name); |
| builder.SetValue(std::move(value), config).SetAllowMangled(true); |
| if (id.id != 0U) { |
| builder.SetId(id); |
| } |
| |
| CHECK(table_->AddResource(builder.Build(), GetDiagnostics())); |
| return *this; |
| } |
| |
| ResourceTableBuilder& ResourceTableBuilder::SetSymbolState(StringPiece name, const ResourceId& id, |
| Visibility::Level level, |
| bool allow_new) { |
| ResourceName res_name = ParseNameOrDie(name); |
| NewResourceBuilder builder(res_name); |
| builder.SetVisibility({level}).SetAllowNew({}).SetAllowMangled(true); |
| if (id.id != 0U) { |
| builder.SetId(id); |
| } |
| |
| CHECK(table_->AddResource(builder.Build(), GetDiagnostics())); |
| return *this; |
| } |
| |
| ResourceTableBuilder& ResourceTableBuilder::SetOverlayable(StringPiece name, |
| const OverlayableItem& overlayable) { |
| ResourceName res_name = ParseNameOrDie(name); |
| CHECK(table_->AddResource( |
| NewResourceBuilder(res_name).SetOverlayable(overlayable).SetAllowMangled(true).Build(), |
| GetDiagnostics())); |
| return *this; |
| } |
| |
| ResourceTableBuilder& ResourceTableBuilder::Add(NewResource&& res) { |
| CHECK(table_->AddResource(std::move(res), GetDiagnostics())); |
| return *this; |
| } |
| |
| android::StringPool* ResourceTableBuilder::string_pool() { |
| return &table_->string_pool; |
| } |
| |
| std::unique_ptr<ResourceTable> ResourceTableBuilder::Build() { |
| return std::move(table_); |
| } |
| |
| std::unique_ptr<Reference> BuildReference(StringPiece ref, const std::optional<ResourceId>& id) { |
| std::unique_ptr<Reference> reference = util::make_unique<Reference>(ParseNameOrDie(ref)); |
| reference->id = id; |
| return reference; |
| } |
| |
| std::unique_ptr<BinaryPrimitive> BuildPrimitive(uint8_t type, uint32_t data) { |
| android::Res_value value = {}; |
| value.size = sizeof(value); |
| value.dataType = type; |
| value.data = data; |
| return util::make_unique<BinaryPrimitive>(value); |
| } |
| |
| AttributeBuilder::AttributeBuilder() |
| : attr_(util::make_unique<Attribute>(android::ResTable_map::TYPE_ANY)) { |
| } |
| |
| AttributeBuilder& AttributeBuilder::SetTypeMask(uint32_t typeMask) { |
| attr_->type_mask = typeMask; |
| return *this; |
| } |
| |
| AttributeBuilder& AttributeBuilder::SetWeak(bool weak) { |
| attr_->SetWeak(weak); |
| return *this; |
| } |
| |
| AttributeBuilder& AttributeBuilder::AddItem(StringPiece name, uint32_t value) { |
| attr_->symbols.push_back( |
| Attribute::Symbol{Reference(ResourceName({}, ResourceType::kId, name)), value}); |
| return *this; |
| } |
| |
| std::unique_ptr<Attribute> AttributeBuilder::Build() { |
| return std::move(attr_); |
| } |
| |
| StyleBuilder& StyleBuilder::SetParent(StringPiece str) { |
| style_->parent = Reference(ParseNameOrDie(str)); |
| return *this; |
| } |
| |
| StyleBuilder& StyleBuilder::AddItem(StringPiece str, std::unique_ptr<Item> value) { |
| style_->entries.push_back(Style::Entry{Reference(ParseNameOrDie(str)), std::move(value)}); |
| return *this; |
| } |
| |
| StyleBuilder& StyleBuilder::AddItem(StringPiece str, const ResourceId& id, |
| std::unique_ptr<Item> value) { |
| AddItem(str, std::move(value)); |
| style_->entries.back().key.id = id; |
| return *this; |
| } |
| |
| std::unique_ptr<Style> StyleBuilder::Build() { |
| return std::move(style_); |
| } |
| |
| StyleableBuilder& StyleableBuilder::AddItem(StringPiece str, const std::optional<ResourceId>& id) { |
| styleable_->entries.push_back(Reference(ParseNameOrDie(str))); |
| styleable_->entries.back().id = id; |
| return *this; |
| } |
| |
| std::unique_ptr<Styleable> StyleableBuilder::Build() { |
| return std::move(styleable_); |
| } |
| |
| std::unique_ptr<xml::XmlResource> BuildXmlDom(StringPiece str) { |
| std::string input = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"; |
| input.append(str.data(), str.size()); |
| StringInputStream in(input); |
| StdErrDiagnostics diag; |
| std::unique_ptr<xml::XmlResource> doc = xml::Inflate(&in, &diag, android::Source("test.xml")); |
| CHECK(doc != nullptr && doc->root != nullptr) << "failed to parse inline XML string"; |
| return doc; |
| } |
| |
| std::unique_ptr<xml::XmlResource> BuildXmlDomForPackageName(IAaptContext* context, |
| StringPiece str) { |
| std::unique_ptr<xml::XmlResource> doc = BuildXmlDom(str); |
| doc->file.name.package = context->GetCompilationPackage(); |
| return doc; |
| } |
| |
| ArtifactBuilder& ArtifactBuilder::SetName(const std::string& name) { |
| artifact_.name = name; |
| return *this; |
| } |
| |
| ArtifactBuilder& ArtifactBuilder::SetVersion(int version) { |
| artifact_.version = version; |
| return *this; |
| } |
| |
| ArtifactBuilder& ArtifactBuilder::AddAbi(configuration::Abi abi) { |
| artifact_.abis.push_back(abi); |
| return *this; |
| } |
| |
| ArtifactBuilder& ArtifactBuilder::AddDensity(const ConfigDescription& density) { |
| artifact_.screen_densities.push_back(density); |
| return *this; |
| } |
| |
| ArtifactBuilder& ArtifactBuilder::AddLocale(const ConfigDescription& locale) { |
| artifact_.locales.push_back(locale); |
| return *this; |
| } |
| |
| ArtifactBuilder& ArtifactBuilder::SetAndroidSdk(int min_sdk) { |
| artifact_.android_sdk = {AndroidSdk::ForMinSdk(min_sdk)}; |
| return *this; |
| } |
| |
| configuration::OutputArtifact ArtifactBuilder::Build() { |
| return artifact_; |
| } |
| |
| PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::AddAbiGroup( |
| const std::string& label, std::vector<configuration::Abi> abis) { |
| return AddGroup(label, &config_.abi_groups, std::move(abis)); |
| } |
| |
| PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::AddDensityGroup( |
| const std::string& label, std::vector<std::string> densities) { |
| std::vector<ConfigDescription> configs; |
| for (const auto& density : densities) { |
| configs.push_back(test::ParseConfigOrDie(density)); |
| } |
| return AddGroup(label, &config_.screen_density_groups, configs); |
| } |
| |
| PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::AddLocaleGroup( |
| const std::string& label, std::vector<std::string> locales) { |
| std::vector<ConfigDescription> configs; |
| for (const auto& locale : locales) { |
| configs.push_back(test::ParseConfigOrDie(locale)); |
| } |
| return AddGroup(label, &config_.locale_groups, configs); |
| } |
| |
| PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::AddDeviceFeatureGroup( |
| const std::string& label) { |
| return AddGroup(label, &config_.device_feature_groups); |
| } |
| |
| PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::AddGlTextureGroup( |
| const std::string& label) { |
| return AddGroup(label, &config_.gl_texture_groups); |
| } |
| |
| PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::AddAndroidSdk( |
| std::string label, int min_sdk) { |
| config_.android_sdks[label] = AndroidSdk::ForMinSdk(min_sdk); |
| return *this; |
| } |
| |
| PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::AddArtifact( |
| configuration::ConfiguredArtifact artifact) { |
| config_.artifacts.push_back(std::move(artifact)); |
| return *this; |
| } |
| |
| configuration::PostProcessingConfiguration PostProcessingConfigurationBuilder::Build() { |
| return config_; |
| } |
| |
| } // namespace test |
| } // namespace aapt |