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