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