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