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
SetComment(StringPiece comment)180 AttributeBuilder& AttributeBuilder::SetComment(StringPiece comment) {
181 attr_->SetComment(comment);
182 return *this;
183 }
184
AddItem(StringPiece name,uint32_t value)185 AttributeBuilder& AttributeBuilder::AddItem(StringPiece name, uint32_t value) {
186 attr_->symbols.push_back(
187 Attribute::Symbol{Reference(ResourceName({}, ResourceType::kId, name)), value});
188 return *this;
189 }
190
AddItemWithComment(StringPiece name,uint32_t value,StringPiece comment)191 AttributeBuilder& AttributeBuilder::AddItemWithComment(StringPiece name, uint32_t value,
192 StringPiece comment) {
193 Reference ref(ResourceName({}, ResourceType::kId, name));
194 ref.SetComment(comment);
195 attr_->symbols.push_back(Attribute::Symbol{ref, value});
196 return *this;
197 }
198
Build()199 std::unique_ptr<Attribute> AttributeBuilder::Build() {
200 return std::move(attr_);
201 }
202
SetParent(StringPiece str)203 StyleBuilder& StyleBuilder::SetParent(StringPiece str) {
204 style_->parent = Reference(ParseNameOrDie(str));
205 return *this;
206 }
207
AddItem(StringPiece str,std::unique_ptr<Item> value)208 StyleBuilder& StyleBuilder::AddItem(StringPiece str, std::unique_ptr<Item> value) {
209 style_->entries.push_back(Style::Entry{Reference(ParseNameOrDie(str)), std::move(value)});
210 return *this;
211 }
212
AddItem(StringPiece str,const ResourceId & id,std::unique_ptr<Item> value)213 StyleBuilder& StyleBuilder::AddItem(StringPiece str, const ResourceId& id,
214 std::unique_ptr<Item> value) {
215 AddItem(str, std::move(value));
216 style_->entries.back().key.id = id;
217 return *this;
218 }
219
Build()220 std::unique_ptr<Style> StyleBuilder::Build() {
221 return std::move(style_);
222 }
223
AddItem(StringPiece str,const std::optional<ResourceId> & id)224 StyleableBuilder& StyleableBuilder::AddItem(StringPiece str, const std::optional<ResourceId>& id) {
225 styleable_->entries.push_back(Reference(ParseNameOrDie(str)));
226 styleable_->entries.back().id = id;
227 return *this;
228 }
229
Build()230 std::unique_ptr<Styleable> StyleableBuilder::Build() {
231 return std::move(styleable_);
232 }
233
BuildXmlDom(StringPiece str)234 std::unique_ptr<xml::XmlResource> BuildXmlDom(StringPiece str) {
235 std::string input = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
236 input.append(str.data(), str.size());
237 StringInputStream in(input);
238 StdErrDiagnostics diag;
239 std::unique_ptr<xml::XmlResource> doc = xml::Inflate(&in, &diag, android::Source("test.xml"));
240 CHECK(doc != nullptr && doc->root != nullptr) << "failed to parse inline XML string";
241 return doc;
242 }
243
BuildXmlDomForPackageName(IAaptContext * context,StringPiece str)244 std::unique_ptr<xml::XmlResource> BuildXmlDomForPackageName(IAaptContext* context,
245 StringPiece str) {
246 std::unique_ptr<xml::XmlResource> doc = BuildXmlDom(str);
247 doc->file.name.package = context->GetCompilationPackage();
248 return doc;
249 }
250
SetName(const std::string & name)251 ArtifactBuilder& ArtifactBuilder::SetName(const std::string& name) {
252 artifact_.name = name;
253 return *this;
254 }
255
SetVersion(int version)256 ArtifactBuilder& ArtifactBuilder::SetVersion(int version) {
257 artifact_.version = version;
258 return *this;
259 }
260
AddAbi(configuration::Abi abi)261 ArtifactBuilder& ArtifactBuilder::AddAbi(configuration::Abi abi) {
262 artifact_.abis.push_back(abi);
263 return *this;
264 }
265
AddDensity(const ConfigDescription & density)266 ArtifactBuilder& ArtifactBuilder::AddDensity(const ConfigDescription& density) {
267 artifact_.screen_densities.push_back(density);
268 return *this;
269 }
270
AddLocale(const ConfigDescription & locale)271 ArtifactBuilder& ArtifactBuilder::AddLocale(const ConfigDescription& locale) {
272 artifact_.locales.push_back(locale);
273 return *this;
274 }
275
SetAndroidSdk(int min_sdk)276 ArtifactBuilder& ArtifactBuilder::SetAndroidSdk(int min_sdk) {
277 artifact_.android_sdk = {AndroidSdk::ForMinSdk(min_sdk)};
278 return *this;
279 }
280
Build()281 configuration::OutputArtifact ArtifactBuilder::Build() {
282 return artifact_;
283 }
284
AddAbiGroup(const std::string & label,std::vector<configuration::Abi> abis)285 PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::AddAbiGroup(
286 const std::string& label, std::vector<configuration::Abi> abis) {
287 return AddGroup(label, &config_.abi_groups, std::move(abis));
288 }
289
AddDensityGroup(const std::string & label,std::vector<std::string> densities)290 PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::AddDensityGroup(
291 const std::string& label, std::vector<std::string> densities) {
292 std::vector<ConfigDescription> configs;
293 for (const auto& density : densities) {
294 configs.push_back(test::ParseConfigOrDie(density));
295 }
296 return AddGroup(label, &config_.screen_density_groups, configs);
297 }
298
AddLocaleGroup(const std::string & label,std::vector<std::string> locales)299 PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::AddLocaleGroup(
300 const std::string& label, std::vector<std::string> locales) {
301 std::vector<ConfigDescription> configs;
302 for (const auto& locale : locales) {
303 configs.push_back(test::ParseConfigOrDie(locale));
304 }
305 return AddGroup(label, &config_.locale_groups, configs);
306 }
307
AddDeviceFeatureGroup(const std::string & label)308 PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::AddDeviceFeatureGroup(
309 const std::string& label) {
310 return AddGroup(label, &config_.device_feature_groups);
311 }
312
AddGlTextureGroup(const std::string & label)313 PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::AddGlTextureGroup(
314 const std::string& label) {
315 return AddGroup(label, &config_.gl_texture_groups);
316 }
317
AddAndroidSdk(std::string label,int min_sdk)318 PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::AddAndroidSdk(
319 std::string label, int min_sdk) {
320 config_.android_sdks[label] = AndroidSdk::ForMinSdk(min_sdk);
321 return *this;
322 }
323
AddArtifact(configuration::ConfiguredArtifact artifact)324 PostProcessingConfigurationBuilder& PostProcessingConfigurationBuilder::AddArtifact(
325 configuration::ConfiguredArtifact artifact) {
326 config_.artifacts.push_back(std::move(artifact));
327 return *this;
328 }
329
Build()330 configuration::PostProcessingConfiguration PostProcessingConfigurationBuilder::Build() {
331 return config_;
332 }
333
334 } // namespace test
335 } // namespace aapt
336