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 "Util.h"
18 
19 #include "android-base/stringprintf.h"
20 
21 #include "AppInfo.h"
22 #include "split/TableSplitter.h"
23 #include "test/Builders.h"
24 #include "test/Test.h"
25 #include "util/Files.h"
26 
27 using ::android::ConfigDescription;
28 using testing::UnorderedElementsAre;
29 
30 namespace aapt {
31 
32 #ifdef _WIN32
33 #define CREATE_PATH(path) android::base::StringPrintf(";%s", path)
34 #else
35 #define CREATE_PATH(path) android::base::StringPrintf(":%s", path)
36 #endif
37 
38 #define EXPECT_CONFIG_EQ(constraints, config) \
39     EXPECT_EQ(constraints.configs.size(), 1); \
40     EXPECT_EQ(*constraints.configs.begin(), config); \
41     constraints.configs.clear();
42 
TEST(UtilTest,SplitNamesAreSanitized)43 TEST(UtilTest, SplitNamesAreSanitized) {
44     AppInfo app_info{"com.pkg"};
45     SplitConstraints split_constraints{
46         {test::ParseConfigOrDie("en-rUS-land"), test::ParseConfigOrDie("b+sr+Latn")}};
47 
48     const auto doc = GenerateSplitManifest(app_info, split_constraints);
49     const auto &root = doc->root;
50     EXPECT_EQ(root->name, "manifest");
51     // split names cannot contain hyphens or plus signs.
52     EXPECT_EQ(root->FindAttribute("", "split")->value, "config.b_sr_Latn_en_rUS_land");
53     // but we should use resource qualifiers verbatim in 'targetConfig'.
54     EXPECT_EQ(root->FindAttribute("", "targetConfig")->value, "b+sr+Latn,en-rUS-land");
55 }
56 
TEST(UtilTest,LongVersionCodeDefined)57 TEST (UtilTest, LongVersionCodeDefined) {
58   auto doc = test::BuildXmlDom(R"(
59       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
60         package="com.android.aapt.test" android:versionCode="0x1" android:versionCodeMajor="0x1">
61       </manifest>)");
62   SetLongVersionCode(doc->root.get(), 42);
63 
64   auto version_code = doc->root->FindAttribute(xml::kSchemaAndroid, "versionCode");
65   ASSERT_NE(version_code, nullptr);
66   EXPECT_EQ(version_code->value, "0x0000002a");
67 
68   ASSERT_NE(version_code->compiled_value, nullptr);
69   auto compiled_version_code = ValueCast<BinaryPrimitive>(version_code->compiled_value.get());
70   ASSERT_NE(compiled_version_code, nullptr);
71   EXPECT_EQ(compiled_version_code->value.data, 42U);
72 
73   auto version_code_major = doc->root->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
74   EXPECT_EQ(version_code_major, nullptr);
75 }
76 
77 TEST (UtilTest, LongVersionCodeUndefined) {
78   auto doc = test::BuildXmlDom(R"(
79         <manifest xmlns:android="http://schemas.android.com/apk/res/android"
80           package="com.android.aapt.test">
81         </manifest>)");
82   SetLongVersionCode(doc->root.get(), 420000000000);
83 
84   auto version_code = doc->root->FindAttribute(xml::kSchemaAndroid, "versionCode");
85   ASSERT_NE(version_code, nullptr);
86   EXPECT_EQ(version_code->value, "0xc9f36800");
87 
88   ASSERT_NE(version_code->compiled_value, nullptr);
89   auto compiled_version_code = ValueCast<BinaryPrimitive>(version_code->compiled_value.get());
90   ASSERT_NE(compiled_version_code, nullptr);
91   EXPECT_EQ(compiled_version_code->value.data, 0xc9f36800);
92 
93   auto version_code_major = doc->root->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
94   ASSERT_NE(version_code_major, nullptr);
95   EXPECT_EQ(version_code_major->value, "0x00000061");
96 
97   ASSERT_NE(version_code_major->compiled_value, nullptr);
98   auto compiled_version_code_major = ValueCast<BinaryPrimitive>(
99       version_code_major->compiled_value.get());
100   ASSERT_NE(compiled_version_code_major, nullptr);
101   EXPECT_EQ(compiled_version_code_major->value.data, 0x61);
102 }
103 
104 
105 TEST (UtilTest, ParseSplitParameters) {
106   android::IDiagnostics* diagnostics = test::ContextBuilder().Build().get()->GetDiagnostics();
107   std::string path;
108   SplitConstraints constraints;
109   ConfigDescription expected_configuration;
110 
111   // ========== Test IMSI ==========
112   // mcc: 'mcc[0-9]{3}'
113   // mnc: 'mnc[0-9]{1,3}'
114   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("mcc310"),
115                                   diagnostics, &path, &constraints));
116   expected_configuration = test::ConfigDescriptionBuilder()
117       .setMcc(0x0136)
118       .Build();
119   EXPECT_CONFIG_EQ(constraints, expected_configuration);
120 
121   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("mcc310-mnc004"),
122                                   diagnostics, &path, &constraints));
123   expected_configuration = test::ConfigDescriptionBuilder()
124       .setMcc(0x0136)
125       .setMnc(0x0004)
126       .Build();
127   EXPECT_CONFIG_EQ(constraints, expected_configuration);
128 
129   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("mcc310-mnc000"),
130                                   diagnostics, &path, &constraints));
131   expected_configuration = test::ConfigDescriptionBuilder()
132       .setMcc(0x0136)
133       .setMnc(0xFFFF)
134       .Build();
135   EXPECT_CONFIG_EQ(constraints, expected_configuration);
136 
137   // ========== Test LOCALE ==========
138   // locale: '[a-z]{2,3}(-r[a-z]{2})?'
139   // locale: 'b+[a-z]{2,3}(+[a-z[0-9]]{2})?'
140   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("es"),
141                                   diagnostics, &path, &constraints));
142   expected_configuration = test::ConfigDescriptionBuilder()
143       .setLanguage(0x6573)
144       .Build();
145   EXPECT_CONFIG_EQ(constraints, expected_configuration);
146 
147   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("fr-rCA"),
148                                   diagnostics, &path, &constraints));
149   expected_configuration = test::ConfigDescriptionBuilder()
150       .setLanguage(0x6672)
151       .setCountry(0x4341)
152       .Build();
153   EXPECT_CONFIG_EQ(constraints, expected_configuration);
154 
155   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("b+es+419"),
156                                   diagnostics, &path, &constraints));
157   expected_configuration = test::ConfigDescriptionBuilder()
158       .setLanguage(0x6573)
159       .setCountry(0xA424)
160       .Build();
161   EXPECT_CONFIG_EQ(constraints, expected_configuration);
162 
163   // ========== Test SCREEN_TYPE ==========
164   // orientation: '(port|land|square)'
165   // touchscreen: '(notouch|stylus|finger)'
166   // density" '(anydpi|nodpi|ldpi|mdpi|tvdpi|hdpi|xhdpi|xxhdpi|xxxhdpi|[0-9]*dpi)'
167   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("square"),
168                                   diagnostics, &path, &constraints));
169   expected_configuration = test::ConfigDescriptionBuilder()
170       .setOrientation(0x03)
171       .Build();
172   EXPECT_CONFIG_EQ(constraints, expected_configuration);
173 
174   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("stylus"),
175                                   diagnostics, &path, &constraints));
176   expected_configuration = test::ConfigDescriptionBuilder()
177       .setTouchscreen(0x02)
178       .Build();
179   EXPECT_CONFIG_EQ(constraints, expected_configuration);
180 
181   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("xxxhdpi"),
182                                   diagnostics, &path, &constraints));
183   expected_configuration = test::ConfigDescriptionBuilder()
184       .setDensity(0x0280)
185       .setSdkVersion(0x0004) // version [any density requires donut]
186       .Build();
187   EXPECT_CONFIG_EQ(constraints, expected_configuration);
188 
189   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("land-xhdpi-finger"),
190                                   diagnostics, &path, &constraints));
191   expected_configuration = test::ConfigDescriptionBuilder()
192       .setOrientation(0x02)
193       .setTouchscreen(0x03)
194       .setDensity(0x0140)
195       .setSdkVersion(0x0004) // version [any density requires donut]
196       .Build();
197   EXPECT_CONFIG_EQ(constraints, expected_configuration);
198 
199   // ========== Test INPUT ==========
200   // keyboard: '(nokeys|qwerty|12key)'
201   // navigation: '(nonav|dpad|trackball|wheel)'
202   // inputFlags: '(keysexposed|keyshidden|keyssoft)'
203   // inputFlags: '(navexposed|navhidden)'
204   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("qwerty"),
205                                   diagnostics, &path, &constraints));
206   expected_configuration = test::ConfigDescriptionBuilder()
207       .setKeyboard(0x02)
208       .Build();
209   EXPECT_CONFIG_EQ(constraints, expected_configuration);
210 
211   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("dpad"),
212                                   diagnostics, &path, &constraints));
213   expected_configuration = test::ConfigDescriptionBuilder()
214       .setNavigation(0x02)
215       .Build();
216   EXPECT_CONFIG_EQ(constraints, expected_configuration);
217 
218   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("keyssoft-navhidden"),
219                                   diagnostics, &path, &constraints));
220   expected_configuration = test::ConfigDescriptionBuilder()
221       .setInputFlags(0x0B)
222       .Build();
223   EXPECT_CONFIG_EQ(constraints, expected_configuration);
224 
225   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("keyshidden-nokeys-navexposed-trackball"),
226                                   diagnostics, &path, &constraints));
227   expected_configuration = test::ConfigDescriptionBuilder()
228       .setKeyboard(0x01)
229       .setNavigation(0x03)
230       .setInputFlags(0x06)
231       .Build();
232   EXPECT_CONFIG_EQ(constraints, expected_configuration);
233 
234   // ========== Test SCREEN_SIZE ==========
235   // screenWidth/screenHeight: '[0-9]+x[0-9]+'
236   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("1920x1080"),
237                                   diagnostics, &path, &constraints));
238   expected_configuration = test::ConfigDescriptionBuilder()
239       .setScreenWidth(0x0780)
240       .setScreenHeight(0x0438)
241       .Build();
242   EXPECT_CONFIG_EQ(constraints, expected_configuration);
243 
244   // ========== Test VERSION ==========
245   // version 'v[0-9]+'
246 
247   // ========== Test SCREEN_CONFIG ==========
248   // screenLayout [direction]: '(ldltr|ldrtl)'
249   // screenLayout [size]: '(small|normal|large|xlarge)'
250   // screenLayout [long]: '(long|notlong)'
251   // uiMode [type]: '(desk|car|television|appliance|watch|vrheadset)'
252   // uiMode [night]: '(night|notnight)'
253   // smallestScreenWidthDp: 'sw[0-9]dp'
254   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("ldrtl"),
255                                   diagnostics, &path, &constraints));
256   expected_configuration = test::ConfigDescriptionBuilder()
257       .setScreenLayout(0x80)
258       .Build();
259   EXPECT_CONFIG_EQ(constraints, expected_configuration);
260 
261   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("small"),
262                                   diagnostics, &path, &constraints));
263   expected_configuration = test::ConfigDescriptionBuilder()
264       .setScreenLayout(0x01)
265       .setSdkVersion(0x0004) // screenLayout (size) requires donut
266       .Build();
267   EXPECT_CONFIG_EQ(constraints, expected_configuration);
268 
269   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("notlong"),
270                                   diagnostics, &path, &constraints));
271   expected_configuration = test::ConfigDescriptionBuilder()
272       .setScreenLayout(0x10)
273       .setSdkVersion(0x0004) // screenLayout (long) requires donut
274       .Build();
275   EXPECT_CONFIG_EQ(constraints, expected_configuration);
276 
277   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("ldltr-normal-long"),
278                                       diagnostics, &path, &constraints));
279   expected_configuration = test::ConfigDescriptionBuilder()
280       .setScreenLayout(0x62)
281       .setSdkVersion(0x0004) // screenLayout (size|long) requires donut
282       .Build();
283   EXPECT_CONFIG_EQ(constraints, expected_configuration);
284 
285   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("car"),
286                                   diagnostics, &path, &constraints));
287   expected_configuration = test::ConfigDescriptionBuilder()
288       .setUiMode(0x03)
289       .setSdkVersion(0x0008) // uiMode requires froyo
290       .Build();
291   EXPECT_CONFIG_EQ(constraints, expected_configuration);
292 
293   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("vrheadset"),
294                                   diagnostics, &path, &constraints));
295   expected_configuration = test::ConfigDescriptionBuilder()
296       .setUiMode(0x07)
297       .setSdkVersion(0x001A) // uiMode 'vrheadset' requires oreo
298       .Build();
299   EXPECT_CONFIG_EQ(constraints, expected_configuration);
300 
301   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("television-night"),
302                                   diagnostics, &path, &constraints));
303   expected_configuration = test::ConfigDescriptionBuilder()
304       .setUiMode(0x24)
305       .setSdkVersion(0x0008) // uiMode requires froyo
306       .Build();
307   EXPECT_CONFIG_EQ(constraints, expected_configuration);
308 
309   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("sw1920dp"),
310                                   diagnostics, &path, &constraints));
311   expected_configuration = test::ConfigDescriptionBuilder()
312       .setSmallestScreenWidthDp(0x0780)
313       .setSdkVersion(0x000D) // smallestScreenWidthDp requires honeycomb mr2
314       .Build();
315   EXPECT_CONFIG_EQ(constraints, expected_configuration);
316 
317   // ========== Test SCREEN_SIZE_DP ==========
318   // screenWidthDp: 'w[0-9]dp'
319   // screenHeightDp: 'h[0-9]dp'
320   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("w1920dp"),
321                                   diagnostics, &path, &constraints));
322   expected_configuration = test::ConfigDescriptionBuilder()
323       .setScreenWidthDp(0x0780)
324       .setSdkVersion(0x000D) // screenWidthDp requires honeycomb mr2
325       .Build();
326   EXPECT_CONFIG_EQ(constraints, expected_configuration);
327 
328   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("h1080dp"),
329                                   diagnostics, &path, &constraints));
330   expected_configuration = test::ConfigDescriptionBuilder()
331       .setScreenHeightDp(0x0438)
332       .setSdkVersion(0x000D) // screenHeightDp requires honeycomb mr2
333       .Build();
334   EXPECT_CONFIG_EQ(constraints, expected_configuration);
335 
336   // ========== Test SCREEN_CONFIG_2 ==========
337   // screenLayout2: '(round|notround)'
338   // colorMode: '(widecg|nowidecg)'
339   // colorMode: '(highhdr|lowdr)'
340   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("round"),
341                                   diagnostics, &path, &constraints));
342   expected_configuration = test::ConfigDescriptionBuilder()
343       .setScreenLayout2(0x02)
344       .setSdkVersion(0x0017) // screenLayout2 (round) requires marshmallow
345       .Build();
346   EXPECT_CONFIG_EQ(constraints, expected_configuration);
347 
348   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("widecg-highdr"),
349                                   diagnostics, &path, &constraints));
350   expected_configuration = test::ConfigDescriptionBuilder()
351       .setColorMode(0x0A)
352       .setSdkVersion(0x001A) // colorMode (hdr|colour gamut) requires oreo
353       .Build();
354   EXPECT_CONFIG_EQ(constraints, expected_configuration);
355 }
356 
TEST(UtilTest,AdjustSplitConstraintsForMinSdk)357 TEST (UtilTest, AdjustSplitConstraintsForMinSdk) {
358   std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
359 
360   android::IDiagnostics* diagnostics = context.get()->GetDiagnostics();
361   std::vector<SplitConstraints> test_constraints;
362   std::string path;
363 
364   test_constraints.push_back({});
365   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("v7"),
366                                   diagnostics, &path, &test_constraints.back()));
367   test_constraints.push_back({});
368   ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("xhdpi"),
369                                   diagnostics, &path, &test_constraints.back()));
370   EXPECT_EQ(test_constraints.size(), 2);
371   EXPECT_EQ(test_constraints[0].name, "v7");
372   EXPECT_EQ(test_constraints[0].configs.size(), 1);
373   EXPECT_NE(*test_constraints[0].configs.begin(), ConfigDescription::DefaultConfig());
374   EXPECT_EQ(test_constraints[1].name, "xhdpi");
375   EXPECT_EQ(test_constraints[1].configs.size(), 1);
376   EXPECT_NE(*test_constraints[0].configs.begin(), ConfigDescription::DefaultConfig());
377 
378   auto adjusted_contraints = AdjustSplitConstraintsForMinSdk(26, test_constraints);
379   EXPECT_EQ(adjusted_contraints.size(), 2);
380   EXPECT_EQ(adjusted_contraints[0].name, "v7");
381   EXPECT_EQ(adjusted_contraints[0].configs.size(), 0);
382   EXPECT_EQ(adjusted_contraints[1].name, "xhdpi");
383   EXPECT_EQ(adjusted_contraints[1].configs.size(), 1);
384   EXPECT_NE(*adjusted_contraints[1].configs.begin(), ConfigDescription::DefaultConfig());
385 }
386 
TEST(UtilTest,RegularExperssionsSimple)387 TEST (UtilTest, RegularExperssionsSimple) {
388   std::string valid(".bc$");
389   std::regex expression = GetRegularExpression(valid);
390   EXPECT_TRUE(std::regex_search("file.abc", expression));
391   EXPECT_TRUE(std::regex_search("file.123bc", expression));
392   EXPECT_FALSE(std::regex_search("abc.zip", expression));
393 }
394 
TEST(UtilTest,RegularExpressionComplex)395 TEST (UtilTest, RegularExpressionComplex) {
396   std::string valid("\\.(d|D)(e|E)(x|X)$");
397   std::regex expression = GetRegularExpression(valid);
398   EXPECT_TRUE(std::regex_search("file.dex", expression));
399   EXPECT_TRUE(std::regex_search("file.DEX", expression));
400   EXPECT_TRUE(std::regex_search("file.dEx", expression));
401   EXPECT_FALSE(std::regex_search("file.dexx", expression));
402   EXPECT_FALSE(std::regex_search("dex.file", expression));
403   EXPECT_FALSE(std::regex_search("file.adex", expression));
404 }
405 
TEST(UtilTest,RegularExpressionNonEnglish)406 TEST (UtilTest, RegularExpressionNonEnglish) {
407   std::string valid("\\.(k|K)(o|O)(ń|Ń)(c|C)(ó|Ó)(w|W)(k|K)(a|A)$");
408   std::regex expression = GetRegularExpression(valid);
409   EXPECT_TRUE(std::regex_search("file.końcówka", expression));
410   EXPECT_TRUE(std::regex_search("file.KOŃCÓWKA", expression));
411   EXPECT_TRUE(std::regex_search("file.kOńcÓwkA", expression));
412   EXPECT_FALSE(std::regex_search("file.koncowka", expression));
413 }
414 
TEST(UtilTest,ParseConfigWithDirectives)415 TEST(UtilTest, ParseConfigWithDirectives) {
416   const std::string& content = R"(
417 bool/remove_me#remove
418 bool/keep_name#no_collapse
419 layout/keep_path#no_path_shorten
420 string/foo#no_obfuscate
421 dimen/bar#no_obfuscate
422 layout/keep_name_and_path#no_collapse,no_path_shorten
423 )";
424   aapt::test::Context context;
425   std::unordered_set<ResourceName> resource_exclusion;
426   std::set<ResourceName> name_collapse_exemptions;
427   std::set<ResourceName> path_shorten_exemptions;
428 
429   EXPECT_TRUE(ParseResourceConfig(content, &context, resource_exclusion, name_collapse_exemptions,
430                                   path_shorten_exemptions));
431 
432   EXPECT_THAT(name_collapse_exemptions,
433               UnorderedElementsAre(ResourceName({}, ResourceType::kString, "foo"),
434                                    ResourceName({}, ResourceType::kDimen, "bar"),
435                                    ResourceName({}, ResourceType::kBool, "keep_name"),
436                                    ResourceName({}, ResourceType::kLayout, "keep_name_and_path")));
437   EXPECT_THAT(path_shorten_exemptions,
438               UnorderedElementsAre(ResourceName({}, ResourceType::kLayout, "keep_path"),
439                                    ResourceName({}, ResourceType::kLayout, "keep_name_and_path")));
440   EXPECT_THAT(resource_exclusion,
441               UnorderedElementsAre(ResourceName({}, ResourceType::kBool, "remove_me")));
442 }
443 
TEST(UtilTest,ParseConfigResourceWithPackage)444 TEST(UtilTest, ParseConfigResourceWithPackage) {
445   const std::string& content = R"(
446 package:bool/remove_me#remove
447 )";
448   aapt::test::Context context;
449   std::unordered_set<ResourceName> resource_exclusion;
450   std::set<ResourceName> name_collapse_exemptions;
451   std::set<ResourceName> path_shorten_exemptions;
452 
453   EXPECT_FALSE(ParseResourceConfig(content, &context, resource_exclusion, name_collapse_exemptions,
454                                    path_shorten_exemptions));
455 }
456 
TEST(UtilTest,ParseConfigInvalidName)457 TEST(UtilTest, ParseConfigInvalidName) {
458   const std::string& content = R"(
459 package:bool/1231#remove
460 )";
461   aapt::test::Context context;
462   std::unordered_set<ResourceName> resource_exclusion;
463   std::set<ResourceName> name_collapse_exemptions;
464   std::set<ResourceName> path_shorten_exemptions;
465 
466   EXPECT_FALSE(ParseResourceConfig(content, &context, resource_exclusion, name_collapse_exemptions,
467                                    path_shorten_exemptions));
468 }
469 
TEST(UtilTest,ParseConfigNoHash)470 TEST(UtilTest, ParseConfigNoHash) {
471   const std::string& content = R"(
472 package:bool/my_bool
473 )";
474   aapt::test::Context context;
475   std::unordered_set<ResourceName> resource_exclusion;
476   std::set<ResourceName> name_collapse_exemptions;
477   std::set<ResourceName> path_shorten_exemptions;
478 
479   EXPECT_FALSE(ParseResourceConfig(content, &context, resource_exclusion, name_collapse_exemptions,
480                                    path_shorten_exemptions));
481 }
482 
483 }  // namespace aapt
484