1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "test/Builders.h"
18
19 #include "Diagnostics.h"
20 #include "android-base/logging.h"
21 #include "androidfw/StringPiece.h"
22 #include "io/StringStream.h"
23 #include "test/Common.h"
24 #include "util/Util.h"
25
26 using ::aapt::configuration::Abi;
27 using ::aapt::configuration::AndroidSdk;
28 using ::aapt::configuration::ConfiguredArtifact;
29 using ::aapt::configuration::GetOrCreateGroup;
30 using ::aapt::io::StringInputStream;
31 using ::android::ConfigDescription;
32 using ::android::StringPiece;
33
34 namespace aapt {
35 namespace test {
36
AddSimple(StringPiece name,const ResourceId & id)37 ResourceTableBuilder& ResourceTableBuilder::AddSimple(StringPiece name, const ResourceId& id) {
38 return AddValue(name, id, util::make_unique<Id>());
39 }
40
AddSimple(StringPiece name,const ConfigDescription & config,const ResourceId & id)41 ResourceTableBuilder& ResourceTableBuilder::AddSimple(StringPiece name,
42 const ConfigDescription& config,
43 const ResourceId& id) {
44 return AddValue(name, config, id, util::make_unique<Id>());
45 }
46
AddReference(StringPiece name,StringPiece ref)47 ResourceTableBuilder& ResourceTableBuilder::AddReference(StringPiece name, StringPiece ref) {
48 return AddReference(name, {}, ref);
49 }
50
AddReference(StringPiece name,const ResourceId & id,StringPiece ref)51 ResourceTableBuilder& ResourceTableBuilder::AddReference(StringPiece name, const ResourceId& id,
52 StringPiece ref) {
53 return AddValue(name, id, util::make_unique<Reference>(ParseNameOrDie(ref)));
54 }
55
AddString(StringPiece name,StringPiece str)56 ResourceTableBuilder& ResourceTableBuilder::AddString(StringPiece name, StringPiece str) {
57 return AddString(name, {}, str);
58 }
59
AddString(StringPiece name,const ResourceId & id,StringPiece str)60 ResourceTableBuilder& ResourceTableBuilder::AddString(StringPiece name, const ResourceId& id,
61 StringPiece str) {
62 return AddValue(name, id, util::make_unique<String>(table_->string_pool.MakeRef(str)));
63 }
64
AddString(StringPiece name,const ResourceId & id,const ConfigDescription & config,StringPiece str)65 ResourceTableBuilder& ResourceTableBuilder::AddString(StringPiece name, const ResourceId& id,
66 const ConfigDescription& config,
67 StringPiece str) {
68 return AddValue(name, config, id, util::make_unique<String>(table_->string_pool.MakeRef(str)));
69 }
70
AddFileReference(StringPiece name,StringPiece path,io::IFile * file)71 ResourceTableBuilder& ResourceTableBuilder::AddFileReference(StringPiece name, StringPiece path,
72 io::IFile* file) {
73 return AddFileReference(name, {}, path, file);
74 }
75
AddFileReference(StringPiece name,const ResourceId & id,StringPiece path,io::IFile * file)76 ResourceTableBuilder& ResourceTableBuilder::AddFileReference(StringPiece name, const ResourceId& id,
77 StringPiece path, io::IFile* file) {
78 auto file_ref = util::make_unique<FileReference>(table_->string_pool.MakeRef(path));
79 file_ref->file = file;
80 return AddValue(name, id, std::move(file_ref));
81 }
82
AddFileReference(StringPiece name,StringPiece path,const ConfigDescription & config,io::IFile * file)83 ResourceTableBuilder& ResourceTableBuilder::AddFileReference(StringPiece name, StringPiece path,
84 const ConfigDescription& config,
85 io::IFile* file) {
86 auto file_ref = util::make_unique<FileReference>(table_->string_pool.MakeRef(path));
87 file_ref->file = file;
88 return AddValue(name, config, {}, std::move(file_ref));
89 }
90
AddValue(StringPiece name,std::unique_ptr<Value> value)91 ResourceTableBuilder& ResourceTableBuilder::AddValue(StringPiece name,
92 std::unique_ptr<Value> value) {
93 return AddValue(name, {}, std::move(value));
94 }
95
AddValue(StringPiece name,const ResourceId & id,std::unique_ptr<Value> value)96 ResourceTableBuilder& ResourceTableBuilder::AddValue(StringPiece name, const ResourceId& id,
97 std::unique_ptr<Value> value) {
98 return AddValue(name, {}, id, std::move(value));
99 }
100
AddValue(StringPiece name,const ConfigDescription & config,const ResourceId & id,std::unique_ptr<Value> value)101 ResourceTableBuilder& ResourceTableBuilder::AddValue(StringPiece name,
102 const ConfigDescription& config,
103 const ResourceId& id,
104 std::unique_ptr<Value> value) {
105 ResourceName res_name = ParseNameOrDie(name);
106 NewResourceBuilder builder(res_name);
107 builder.SetValue(std::move(value), config).SetAllowMangled(true);
108 if (id.id != 0U) {
109 builder.SetId(id);
110 }
111
112 CHECK(table_->AddResource(builder.Build(), GetDiagnostics()));
113 return *this;
114 }
115
SetSymbolState(StringPiece name,const ResourceId & id,Visibility::Level level,bool allow_new)116 ResourceTableBuilder& ResourceTableBuilder::SetSymbolState(StringPiece name, const ResourceId& id,
117 Visibility::Level level,
118 bool allow_new) {
119 ResourceName res_name = ParseNameOrDie(name);
120 NewResourceBuilder builder(res_name);
121 builder.SetVisibility({level}).SetAllowNew({}).SetAllowMangled(true);
122 if (id.id != 0U) {
123 builder.SetId(id);
124 }
125
126 CHECK(table_->AddResource(builder.Build(), GetDiagnostics()));
127 return *this;
128 }
129
SetOverlayable(StringPiece name,const OverlayableItem & overlayable)130 ResourceTableBuilder& ResourceTableBuilder::SetOverlayable(StringPiece name,
131 const OverlayableItem& overlayable) {
132 ResourceName res_name = ParseNameOrDie(name);
133 CHECK(table_->AddResource(
134 NewResourceBuilder(res_name).SetOverlayable(overlayable).SetAllowMangled(true).Build(),
135 GetDiagnostics()));
136 return *this;
137 }
138
Add(NewResource && res)139 ResourceTableBuilder& ResourceTableBuilder::Add(NewResource&& res) {
140 CHECK(table_->AddResource(std::move(res), GetDiagnostics()));
141 return *this;
142 }
143
string_pool()144 android::StringPool* ResourceTableBuilder::string_pool() {
145 return &table_->string_pool;
146 }
147
Build()148 std::unique_ptr<ResourceTable> ResourceTableBuilder::Build() {
149 return std::move(table_);
150 }
151
BuildReference(StringPiece ref,const std::optional<ResourceId> & id)152 std::unique_ptr<Reference> BuildReference(StringPiece ref, const std::optional<ResourceId>& id) {
153 std::unique_ptr<Reference> reference = util::make_unique<Reference>(ParseNameOrDie(ref));
154 reference->id = id;
155 return reference;
156 }
157
BuildPrimitive(uint8_t type,uint32_t data)158 std::unique_ptr<BinaryPrimitive> BuildPrimitive(uint8_t type, uint32_t data) {
159 android::Res_value value = {};
160 value.size = sizeof(value);
161 value.dataType = type;
162 value.data = data;
163 return util::make_unique<BinaryPrimitive>(value);
164 }
165
AttributeBuilder()166 AttributeBuilder::AttributeBuilder()
167 : attr_(util::make_unique<Attribute>(android::ResTable_map::TYPE_ANY)) {
168 }
169
SetTypeMask(uint32_t typeMask)170 AttributeBuilder& AttributeBuilder::SetTypeMask(uint32_t typeMask) {
171 attr_->type_mask = typeMask;
172 return *this;
173 }
174
SetWeak(bool weak)175 AttributeBuilder& AttributeBuilder::SetWeak(bool weak) {
176 attr_->SetWeak(weak);
177 return *this;
178 }
179
AddItem(StringPiece name,uint32_t value)180 AttributeBuilder& AttributeBuilder::AddItem(StringPiece name, uint32_t value) {
181 attr_->symbols.push_back(
182 Attribute::Symbol{Reference(ResourceName({}, ResourceType::kId, name)), value});
183 return *this;
184 }
185
Build()186 std::unique_ptr<Attribute> AttributeBuilder::Build() {
187 return std::move(attr_);
188 }
189
SetParent(StringPiece str)190 StyleBuilder& StyleBuilder::SetParent(StringPiece str) {
191 style_->parent = Reference(ParseNameOrDie(str));
192 return *this;
193 }
194
AddItem(StringPiece str,std::unique_ptr<Item> value)195 StyleBuilder& StyleBuilder::AddItem(StringPiece str, std::unique_ptr<Item> value) {
196 style_->entries.push_back(Style::Entry{Reference(ParseNameOrDie(str)), std::move(value)});
197 return *this;
198 }
199
AddItem(StringPiece str,const ResourceId & id,std::unique_ptr<Item> value)200 StyleBuilder& StyleBuilder::AddItem(StringPiece str, const ResourceId& id,
201 std::unique_ptr<Item> value) {
202 AddItem(str, std::move(value));
203 style_->entries.back().key.id = id;
204 return *this;
205 }
206
Build()207 std::unique_ptr<Style> StyleBuilder::Build() {
208 return std::move(style_);
209 }
210
AddItem(StringPiece str,const std::optional<ResourceId> & id)211 StyleableBuilder& StyleableBuilder::AddItem(StringPiece str, const std::optional<ResourceId>& id) {
212 styleable_->entries.push_back(Reference(ParseNameOrDie(str)));
213 styleable_->entries.back().id = id;
214 return *this;
215 }
216
Build()217 std::unique_ptr<Styleable> StyleableBuilder::Build() {
218 return std::move(styleable_);
219 }
220
BuildXmlDom(StringPiece str)221 std::unique_ptr<xml::XmlResource> BuildXmlDom(StringPiece str) {
222 std::string input = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
223 input.append(str.data(), str.size());
224 StringInputStream in(input);
225 StdErrDiagnostics diag;
226 std::unique_ptr<xml::XmlResource> doc = xml::Inflate(&in, &diag, android::Source("test.xml"));
227 CHECK(doc != nullptr && doc->root != nullptr) << "failed to parse inline XML string";
228 return doc;
229 }
230
BuildXmlDomForPackageName(IAaptContext * context,StringPiece str)231 std::unique_ptr<xml::XmlResource> BuildXmlDomForPackageName(IAaptContext* context,
232 StringPiece str) {
233 std::unique_ptr<xml::XmlResource> doc = BuildXmlDom(str);
234 doc->file.name.package = context->GetCompilationPackage();
235 return doc;
236 }
237
SetName(const std::string & name)238 ArtifactBuilder& ArtifactBuilder::SetName(const std::string& name) {
239 artifact_.name = name;
240 return *this;
241 }
242
SetVersion(int version)243 ArtifactBuilder& ArtifactBuilder::SetVersion(int version) {
244 artifact_.version = version;
245 return *this;
246 }
247
AddAbi(configuration::Abi abi)248 ArtifactBuilder& ArtifactBuilder::AddAbi(configuration::Abi abi) {
249 artifact_.abis.push_back(abi);
250 return *this;
251 }
252
AddDensity(const ConfigDescription & density)253 ArtifactBuilder& ArtifactBuilder::AddDensity(const ConfigDescription& density) {
254 artifact_.screen_densities.push_back(density);
255 return *this;
256 }
257
AddLocale(const ConfigDescription & locale)258 ArtifactBuilder& ArtifactBuilder::AddLocale(const ConfigDescription& locale) {
259 artifact_.locales.push_back(locale);
260 return *this;
261 }
262
SetAndroidSdk(int min_sdk)263 ArtifactBuilder& ArtifactBuilder::SetAndroidSdk(int min_sdk) {
264 artifact_.android_sdk = {AndroidSdk::ForMinSdk(min_sdk)};
265 return *this;
266 }
267
Build()268 configuration::OutputArtifact ArtifactBuilder::Build() {
269 return artifact_;
270 }
271
AddAbiGroup(const std::string & label,std::vector<configuration::Abi> abis)272 PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::AddAbiGroup(
273 const std::string& label, std::vector<configuration::Abi> abis) {
274 return AddGroup(label, &config_.abi_groups, std::move(abis));
275 }
276
AddDensityGroup(const std::string & label,std::vector<std::string> densities)277 PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::AddDensityGroup(
278 const std::string& label, std::vector<std::string> densities) {
279 std::vector<ConfigDescription> configs;
280 for (const auto& density : densities) {
281 configs.push_back(test::ParseConfigOrDie(density));
282 }
283 return AddGroup(label, &config_.screen_density_groups, configs);
284 }
285
AddLocaleGroup(const std::string & label,std::vector<std::string> locales)286 PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::AddLocaleGroup(
287 const std::string& label, std::vector<std::string> locales) {
288 std::vector<ConfigDescription> configs;
289 for (const auto& locale : locales) {
290 configs.push_back(test::ParseConfigOrDie(locale));
291 }
292 return AddGroup(label, &config_.locale_groups, configs);
293 }
294
AddDeviceFeatureGroup(const std::string & label)295 PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::AddDeviceFeatureGroup(
296 const std::string& label) {
297 return AddGroup(label, &config_.device_feature_groups);
298 }
299
AddGlTextureGroup(const std::string & label)300 PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::AddGlTextureGroup(
301 const std::string& label) {
302 return AddGroup(label, &config_.gl_texture_groups);
303 }
304
AddAndroidSdk(std::string label,int min_sdk)305 PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::AddAndroidSdk(
306 std::string label, int min_sdk) {
307 config_.android_sdks[label] = AndroidSdk::ForMinSdk(min_sdk);
308 return *this;
309 }
310
AddArtifact(configuration::ConfiguredArtifact artifact)311 PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::AddArtifact(
312 configuration::ConfiguredArtifact artifact) {
313 config_.artifacts.push_back(std::move(artifact));
314 return *this;
315 }
316
Build()317 configuration::PostProcessingConfiguration PostProcessingConfigurationBuilder::Build() {
318 return config_;
319 }
320
321 } // namespace test
322 } // namespace aapt
323