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