xref: /aosp_15_r20/frameworks/base/tools/aapt2/link/ManifestFixer_test.cpp (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1 /*
2  * Copyright (C) 2015 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 "link/ManifestFixer.h"
18 
19 #include "test/Test.h"
20 
21 using ::android::StringPiece;
22 using ::testing::Eq;
23 using ::testing::Gt;
24 using ::testing::IsNull;
25 using ::testing::Ne;
26 using ::testing::NotNull;
27 using ::testing::StrEq;
28 
29 namespace aapt {
30 
31 struct ManifestFixerTest : public ::testing::Test {
32   std::unique_ptr<IAaptContext> mContext;
33 
SetUpaapt::ManifestFixerTest34   void SetUp() override {
35     mContext =
36         test::ContextBuilder()
37             .SetCompilationPackage("android")
38             .SetPackageId(0x01)
39             .SetNameManglerPolicy(NameManglerPolicy{"android"})
40             .AddSymbolSource(test::StaticSymbolSourceBuilder()
41                                  .AddSymbol("android:attr/package", ResourceId(0x01010000),
42                                             test::AttributeBuilder()
43                                                 .SetTypeMask(android::ResTable_map::TYPE_STRING)
44                                                 .Build())
45                                  .AddSymbol("android:attr/minSdkVersion", ResourceId(0x01010001),
46                                             test::AttributeBuilder()
47                                                 .SetTypeMask(android::ResTable_map::TYPE_STRING |
48                                                              android::ResTable_map::TYPE_INTEGER)
49                                                 .Build())
50                                  .AddSymbol("android:attr/targetSdkVersion", ResourceId(0x01010002),
51                                             test::AttributeBuilder()
52                                                 .SetTypeMask(android::ResTable_map::TYPE_STRING |
53                                                              android::ResTable_map::TYPE_INTEGER)
54                                                 .Build())
55                                  .AddSymbol("android:string/str", ResourceId(0x01060000))
56                                  .AddSymbol("android:attr/configChanges", ResourceId(0x01010003),
57                                             test::AttributeBuilder()
58                                                 .AddItem("testConfigChange1", 1)
59                                                 .AddItem("testConfigChange2", 2)
60                                                 .AddItem("resourcesUnused", 4)
61                                                 .SetTypeMask(android::ResTable_map::TYPE_STRING)
62                                                 .Build())
63                                  .Build())
64             .Build();
65   }
66 
Verifyaapt::ManifestFixerTest67   std::unique_ptr<xml::XmlResource> Verify(StringPiece str) {
68     return VerifyWithOptions(str, {});
69   }
70 
VerifyWithOptionsaapt::ManifestFixerTest71   std::unique_ptr<xml::XmlResource> VerifyWithOptions(StringPiece str,
72                                                       const ManifestFixerOptions& options) {
73     std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(str);
74     ManifestFixer fixer(options);
75     if (fixer.Consume(mContext.get(), doc.get())) {
76       return doc;
77     }
78     return {};
79   }
80 };
81 
TEST_F(ManifestFixerTest,EnsureManifestIsRootTag)82 TEST_F(ManifestFixerTest, EnsureManifestIsRootTag) {
83   EXPECT_THAT(Verify("<other-tag />"), IsNull());
84   EXPECT_THAT(Verify("<ns:manifest xmlns:ns=\"com\" />"), IsNull());
85   EXPECT_THAT(Verify("<manifest package=\"android\"></manifest>"), NotNull());
86 }
87 
TEST_F(ManifestFixerTest,EnsureManifestHasPackage)88 TEST_F(ManifestFixerTest, EnsureManifestHasPackage) {
89   EXPECT_THAT(Verify("<manifest package=\"android\" />"), NotNull());
90   EXPECT_THAT(Verify("<manifest package=\"com.android\" />"), NotNull());
91   EXPECT_THAT(Verify("<manifest package=\"com.android.google\" />"), NotNull());
92   EXPECT_THAT(Verify("<manifest package=\"com.android.google.Class$1\" />"), IsNull());
93   EXPECT_THAT(Verify("<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\" "
94                      "android:package=\"com.android\" />"),
95               IsNull());
96   EXPECT_THAT(Verify("<manifest package=\"@string/str\" />"), IsNull());
97 }
98 
TEST_F(ManifestFixerTest,AllowMetaData)99 TEST_F(ManifestFixerTest, AllowMetaData) {
100   auto doc = Verify(R"EOF(
101         <manifest xmlns:android="http://schemas.android.com/apk/res/android"
102                   package="android">
103           <meta-data />
104           <application>
105             <meta-data />
106             <activity android:name=".Hi"><meta-data /></activity>
107             <activity-alias android:name=".Ho"><meta-data /></activity-alias>
108             <receiver android:name=".OffTo"><meta-data /></receiver>
109             <provider android:name=".Work"><meta-data /></provider>
110             <service android:name=".We"><meta-data /></service>
111           </application>
112           <instrumentation android:name=".Go"><meta-data /></instrumentation>
113         </manifest>)EOF");
114   ASSERT_THAT(doc, NotNull());
115 }
116 
117 TEST_F(ManifestFixerTest, UseDefaultSdkVersionsIfNonePresent) {
118   ManifestFixerOptions options;
119   options.min_sdk_version_default = std::string("8");
120   options.target_sdk_version_default = std::string("22");
121 
122   std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
123       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
124                 package="android">
125         <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="21" />
126       </manifest>)EOF",
127                                                             options);
128   ASSERT_THAT(doc, NotNull());
129 
130   xml::Element* el;
131   xml::Attribute* attr;
132 
133   el = doc->root.get();
134   ASSERT_THAT(el, NotNull());
135   el = el->FindChild({}, "uses-sdk");
136   ASSERT_THAT(el, NotNull());
137   attr = el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion");
138   ASSERT_THAT(attr, NotNull());
139   EXPECT_THAT(attr->value, StrEq("7"));
140   attr = el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion");
141   ASSERT_THAT(attr, NotNull());
142   EXPECT_THAT(attr->value, StrEq("21"));
143 
144   doc = VerifyWithOptions(R"EOF(
145       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
146                 package="android">
147         <uses-sdk android:targetSdkVersion="21" />
148       </manifest>)EOF",
149                           options);
150   ASSERT_THAT(doc, NotNull());
151 
152   el = doc->root.get();
153   ASSERT_THAT(el, NotNull());
154   el = el->FindChild({}, "uses-sdk");
155   ASSERT_THAT(el, NotNull());
156   attr = el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion");
157   ASSERT_THAT(attr, NotNull());
158   EXPECT_THAT(attr->value, StrEq("8"));
159   attr = el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion");
160   ASSERT_THAT(attr, NotNull());
161   EXPECT_THAT(attr->value, StrEq("21"));
162 
163   doc = VerifyWithOptions(R"EOF(
164       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
165                 package="android">
166         <uses-sdk />
167       </manifest>)EOF",
168                           options);
169   ASSERT_THAT(doc, NotNull());
170 
171   el = doc->root.get();
172   ASSERT_THAT(el, NotNull());
173   el = el->FindChild({}, "uses-sdk");
174   ASSERT_THAT(el, NotNull());
175   attr = el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion");
176   ASSERT_THAT(attr, NotNull());
177   EXPECT_THAT(attr->value, StrEq("8"));
178   attr = el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion");
179   ASSERT_THAT(attr, NotNull());
180   EXPECT_THAT(attr->value, StrEq("22"));
181 
182   doc = VerifyWithOptions(R"EOF(
183       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
184                 package="android" />)EOF",
185                           options);
186   ASSERT_THAT(doc, NotNull());
187 
188   el = doc->root.get();
189   ASSERT_THAT(el, NotNull());
190   el = el->FindChild({}, "uses-sdk");
191   ASSERT_THAT(el, NotNull());
192   attr = el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion");
193   ASSERT_THAT(attr, NotNull());
194   EXPECT_THAT(attr->value, StrEq("8"));
195   attr = el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion");
196   ASSERT_THAT(attr, NotNull());
197   EXPECT_THAT(attr->value, StrEq("22"));
198 }
199 
200 TEST_F(ManifestFixerTest, UsesSdkMustComeBeforeApplication) {
201   ManifestFixerOptions options;
202   options.min_sdk_version_default = std::string("8");
203   options.target_sdk_version_default = std::string("22");
204   std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
205           <manifest xmlns:android="http://schemas.android.com/apk/res/android"
206                     package="android">
207             <application android:name=".MainApplication" />
208           </manifest>)EOF",
209                                                             options);
210   ASSERT_THAT(doc, NotNull());
211 
212   xml::Element* manifest_el = doc->root.get();
213   ASSERT_THAT(manifest_el, NotNull());
214   ASSERT_EQ("manifest", manifest_el->name);
215 
216   xml::Element* application_el = manifest_el->FindChild("", "application");
217   ASSERT_THAT(application_el, NotNull());
218 
219   xml::Element* uses_sdk_el = manifest_el->FindChild("", "uses-sdk");
220   ASSERT_THAT(uses_sdk_el, NotNull());
221 
222   // Check that the uses_sdk_el comes before application_el in the children
223   // vector.
224   // Since there are no namespaces here, these children are direct descendants
225   // of manifest.
226   auto uses_sdk_iter =
227       std::find_if(manifest_el->children.begin(), manifest_el->children.end(),
228                    [&](const std::unique_ptr<xml::Node>& child) {
229                      return child.get() == uses_sdk_el;
230                    });
231 
232   auto application_iter =
233       std::find_if(manifest_el->children.begin(), manifest_el->children.end(),
234                    [&](const std::unique_ptr<xml::Node>& child) {
235                      return child.get() == application_el;
236                    });
237 
238   ASSERT_THAT(uses_sdk_iter, Ne(manifest_el->children.end()));
239   ASSERT_THAT(application_iter, Ne(manifest_el->children.end()));
240 
241   // The distance should be positive, meaning uses_sdk_iter comes before
242   // application_iter.
243   EXPECT_THAT(std::distance(uses_sdk_iter, application_iter), Gt(0));
244 }
245 
246 TEST_F(ManifestFixerTest, RenameManifestPackageAndFullyQualifyClasses) {
247   ManifestFixerOptions options;
248   options.rename_manifest_package = std::string("com.android");
249 
250   std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
251       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
252                 package="android">
253         <uses-split android:name="feature_a" />
254         <application android:name=".MainApplication" text="hello">
255           <activity android:name=".activity.Start" />
256           <receiver android:name="com.google.android.Receiver" />
257         </application>
258       </manifest>)EOF",
259                                                             options);
260   ASSERT_THAT(doc, NotNull());
261 
262   xml::Element* manifest_el = doc->root.get();
263   ASSERT_THAT(manifest_el, NotNull());
264 
265   xml::Attribute* attr = nullptr;
266 
267   attr = manifest_el->FindAttribute({}, "package");
268   ASSERT_THAT(attr, NotNull());
269   EXPECT_THAT(attr->value, StrEq("com.android"));
270 
271   xml::Element* uses_split_el = manifest_el->FindChild({}, "uses-split");
272   ASSERT_THAT(uses_split_el, NotNull());
273   attr = uses_split_el->FindAttribute(xml::kSchemaAndroid, "name");
274   ASSERT_THAT(attr, NotNull());
275   // This should NOT have been affected.
276   EXPECT_THAT(attr->value, StrEq("feature_a"));
277 
278   xml::Element* application_el = manifest_el->FindChild({}, "application");
279   ASSERT_THAT(application_el, NotNull());
280 
281   attr = application_el->FindAttribute(xml::kSchemaAndroid, "name");
282   ASSERT_THAT(attr, NotNull());
283   EXPECT_THAT(attr->value, StrEq("android.MainApplication"));
284 
285   attr = application_el->FindAttribute({}, "text");
286   ASSERT_THAT(attr, NotNull());
287   EXPECT_THAT(attr->value, StrEq("hello"));
288 
289   xml::Element* el;
290   el = application_el->FindChild({}, "activity");
291   ASSERT_THAT(el, NotNull());
292 
293   attr = el->FindAttribute(xml::kSchemaAndroid, "name");
294   ASSERT_THAT(el, NotNull());
295   EXPECT_THAT(attr->value, StrEq("android.activity.Start"));
296 
297   el = application_el->FindChild({}, "receiver");
298   ASSERT_THAT(el, NotNull());
299 
300   attr = el->FindAttribute(xml::kSchemaAndroid, "name");
301   ASSERT_THAT(el, NotNull());
302   EXPECT_THAT(attr->value, StrEq("com.google.android.Receiver"));
303 }
304 
305 TEST_F(ManifestFixerTest,
306        RenameManifestInstrumentationPackageAndFullyQualifyTarget) {
307   ManifestFixerOptions options;
308   options.rename_instrumentation_target_package = std::string("com.android");
309 
310   std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
311       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
312                 package="android">
313         <instrumentation android:name=".TestRunner" android:targetPackage="android" />
314       </manifest>)EOF",
315                                                             options);
316   ASSERT_THAT(doc, NotNull());
317 
318   xml::Element* manifest_el = doc->root.get();
319   ASSERT_THAT(manifest_el, NotNull());
320 
321   xml::Element* instrumentation_el =
322       manifest_el->FindChild({}, "instrumentation");
323   ASSERT_THAT(instrumentation_el, NotNull());
324 
325   xml::Attribute* attr =
326       instrumentation_el->FindAttribute(xml::kSchemaAndroid, "targetPackage");
327   ASSERT_THAT(attr, NotNull());
328   EXPECT_THAT(attr->value, StrEq("com.android"));
329 }
330 
331 TEST_F(ManifestFixerTest,
332        RenameManifestOverlayPackageAndFullyQualifyTarget) {
333   ManifestFixerOptions options;
334   options.rename_overlay_target_package = std::string("com.android");
335 
336   std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
337       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
338                 package="android">
339         <overlay android:targetName="Customization" android:targetPackage="android" />
340       </manifest>)EOF",
341                                                             options);
342   ASSERT_THAT(doc, NotNull());
343 
344   xml::Element* manifest_el = doc->root.get();
345   ASSERT_THAT(manifest_el, NotNull());
346 
347   xml::Element* overlay_el =
348       manifest_el->FindChild({}, "overlay");
349   ASSERT_THAT(overlay_el, NotNull());
350 
351   xml::Attribute* attr =
352       overlay_el->FindAttribute(xml::kSchemaAndroid, "targetPackage");
353   ASSERT_THAT(attr, NotNull());
354   EXPECT_THAT(attr->value, StrEq("com.android"));
355 }
356 
357 TEST_F(ManifestFixerTest, AddOverlayCategory) {
358   ManifestFixerOptions options;
359   options.rename_overlay_category = std::string("category");
360 
361   std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
362       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
363                 package="android">
364         <overlay android:targetName="Customization" android:targetPackage="android" />
365       </manifest>)EOF",
366                                                             options);
367   ASSERT_THAT(doc, NotNull());
368 
369   xml::Element* manifest_el = doc->root.get();
370   ASSERT_THAT(manifest_el, NotNull());
371 
372   xml::Element* overlay_el = manifest_el->FindChild({}, "overlay");
373   ASSERT_THAT(overlay_el, NotNull());
374 
375   xml::Attribute* attr = overlay_el->FindAttribute(xml::kSchemaAndroid, "category");
376   ASSERT_THAT(attr, NotNull());
377   EXPECT_THAT(attr->value, StrEq("category"));
378 }
379 
380 TEST_F(ManifestFixerTest, OverrideOverlayCategory) {
381   ManifestFixerOptions options;
382   options.rename_overlay_category = std::string("category");
383 
384   std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
385       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
386                 package="android">
387         <overlay android:targetName="Customization"
388                  android:targetPackage="android"
389                  android:category="yrogetac"/>
390       </manifest>)EOF",
391                                                             options);
392   ASSERT_THAT(doc, NotNull());
393 
394   xml::Element* manifest_el = doc->root.get();
395   ASSERT_THAT(manifest_el, NotNull());
396 
397   xml::Element* overlay_el = manifest_el->FindChild({}, "overlay");
398   ASSERT_THAT(overlay_el, NotNull());
399 
400   xml::Attribute* attr = overlay_el->FindAttribute(xml::kSchemaAndroid, "category");
401   ASSERT_THAT(attr, NotNull());
402   EXPECT_THAT(attr->value, StrEq("category"));
403 }
404 
405 TEST_F(ManifestFixerTest, UseDefaultVersionNameAndCode) {
406   ManifestFixerOptions options;
407   options.version_name_default = std::string("Beta");
408   options.version_code_default = std::string("0x10000000");
409   options.version_code_major_default = std::string("0x20000000");
410 
411   std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
412       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
413                 package="android" />)EOF",
414                                                             options);
415   ASSERT_THAT(doc, NotNull());
416 
417   xml::Element* manifest_el = doc->root.get();
418   ASSERT_THAT(manifest_el, NotNull());
419 
420   xml::Attribute* attr =
421       manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
422   ASSERT_THAT(attr, NotNull());
423   EXPECT_THAT(attr->value, StrEq("Beta"));
424 
425   attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
426   ASSERT_THAT(attr, NotNull());
427   EXPECT_THAT(attr->value, StrEq("0x10000000"));
428 
429   attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
430   ASSERT_THAT(attr, NotNull());
431   EXPECT_THAT(attr->value, StrEq("0x20000000"));
432 }
433 
434 TEST_F(ManifestFixerTest, DontUseDefaultVersionNameAndCode) {
435   ManifestFixerOptions options;
436   options.version_name_default = std::string("Beta");
437   options.version_code_default = std::string("0x10000000");
438   options.version_code_major_default = std::string("0x20000000");
439 
440   std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
441         <manifest xmlns:android="http://schemas.android.com/apk/res/android"
442                   package="android"
443                   android:versionCode="0x00000001"
444                   android:versionCodeMajor="0x00000002"
445                   android:versionName="Alpha" />)EOF",
446                                                             options);
447   ASSERT_THAT(doc, NotNull());
448 
449   xml::Element* manifest_el = doc->root.get();
450   ASSERT_THAT(manifest_el, NotNull());
451 
452   xml::Attribute* attr =
453       manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
454   ASSERT_THAT(attr, NotNull());
455   EXPECT_THAT(attr->value, StrEq("Alpha"));
456 
457   attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
458   ASSERT_THAT(attr, NotNull());
459   EXPECT_THAT(attr->value, StrEq("0x00000001"));
460 
461   attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
462   ASSERT_THAT(attr, NotNull());
463   EXPECT_THAT(attr->value, StrEq("0x00000002"));
464 }
465 
466 TEST_F(ManifestFixerTest, ReplaceVersionNameAndCode) {
467   ManifestFixerOptions options;
468   options.replace_version = true;
469   options.version_name_default = std::string("Beta");
470   options.version_code_default = std::string("0x10000000");
471   options.version_code_major_default = std::string("0x20000000");
472 
473   std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
474       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
475                 package="android"
476                 android:versionCode="0x00000001"
477                 android:versionCodeMajor="0x00000002"
478                 android:versionName="Alpha" />)EOF",
479                                                             options);
480   ASSERT_THAT(doc, NotNull());
481 
482   xml::Element* manifest_el = doc->root.get();
483   ASSERT_THAT(manifest_el, NotNull());
484 
485   xml::Attribute* attr =
486       manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
487   ASSERT_THAT(attr, NotNull());
488   EXPECT_THAT(attr->value, StrEq("Beta"));
489 
490   attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
491   ASSERT_THAT(attr, NotNull());
492   EXPECT_THAT(attr->value, StrEq("0x10000000"));
493 
494   attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
495   ASSERT_THAT(attr, NotNull());
496   EXPECT_THAT(attr->value, StrEq("0x20000000"));
497 }
498 
499 TEST_F(ManifestFixerTest, UseDefaultRevisionCode) {
500   ManifestFixerOptions options;
501   options.revision_code_default = std::string("0x10000000");
502 
503   std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
504       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
505                 package="android"
506                 android:versionCode="0x00000001" />)EOF",
507                                                             options);
508   ASSERT_THAT(doc, NotNull());
509 
510   xml::Element* manifest_el = doc->root.get();
511   ASSERT_THAT(manifest_el, NotNull());
512 
513   xml::Attribute* attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "revisionCode");
514   ASSERT_THAT(attr, NotNull());
515   EXPECT_THAT(attr->value, StrEq("0x10000000"));
516 }
517 
518 TEST_F(ManifestFixerTest, DontUseDefaultRevisionCode) {
519   ManifestFixerOptions options;
520   options.revision_code_default = std::string("0x10000000");
521 
522   std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
523         <manifest xmlns:android="http://schemas.android.com/apk/res/android"
524                   package="android"
525                   android:versionCode="0x00000001"
526                   android:revisionCode="0x00000002" />)EOF",
527                                                             options);
528   ASSERT_THAT(doc, NotNull());
529 
530   xml::Element* manifest_el = doc->root.get();
531   ASSERT_THAT(manifest_el, NotNull());
532 
533   xml::Attribute* attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "revisionCode");
534   ASSERT_THAT(attr, NotNull());
535   EXPECT_THAT(attr->value, StrEq("0x00000002"));
536 }
537 
538 TEST_F(ManifestFixerTest, ReplaceRevisionCode) {
539   ManifestFixerOptions options;
540   options.replace_version = true;
541   options.revision_code_default = std::string("0x10000000");
542 
543   std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
544         <manifest xmlns:android="http://schemas.android.com/apk/res/android"
545                   package="android"
546                   android:versionCode="0x00000001"
547                   android:revisionCode="0x00000002" />)EOF",
548                                                             options);
549   ASSERT_THAT(doc, NotNull());
550 
551   xml::Element* manifest_el = doc->root.get();
552   ASSERT_THAT(manifest_el, NotNull());
553 
554   xml::Attribute* attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "revisionCode");
555   ASSERT_THAT(attr, NotNull());
556   EXPECT_THAT(attr->value, StrEq("0x10000000"));
557 }
558 
559 TEST_F(ManifestFixerTest, ReplaceVersionName) {
560   ManifestFixerOptions options;
561   options.replace_version = true;
562   options.version_name_default = std::string("Beta");
563 
564 
565   std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
566     <manifest xmlns:android="http://schemas.android.com/apk/res/android"
567               package="android"
568               android:versionCode="0x00000001"
569               android:versionCodeMajor="0x00000002"
570               android:versionName="Alpha" />)EOF",
571                                                             options);
572   ASSERT_THAT(doc, NotNull());
573 
574   xml::Element* manifest_el = doc->root.get();
575   ASSERT_THAT(manifest_el, NotNull());
576 
577   xml::Attribute* attr =
578       manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
579   ASSERT_THAT(attr, NotNull());
580   EXPECT_THAT(attr->value, StrEq("Beta"));
581 
582   attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
583   ASSERT_THAT(attr, NotNull());
584   EXPECT_THAT(attr->value, StrEq("0x00000001"));
585 
586   attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
587   ASSERT_THAT(attr, NotNull());
588   EXPECT_THAT(attr->value, StrEq("0x00000002"));
589 }
590 
591 TEST_F(ManifestFixerTest, ReplaceVersionCode) {
592   ManifestFixerOptions options;
593   options.replace_version = true;
594   options.version_code_default = std::string("0x10000000");
595 
596   std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
597     <manifest xmlns:android="http://schemas.android.com/apk/res/android"
598               package="android"
599               android:versionCode="0x00000001"
600               android:versionCodeMajor="0x00000002"
601               android:versionName="Alpha" />)EOF",
602                                                             options);
603   ASSERT_THAT(doc, NotNull());
604 
605   xml::Element* manifest_el = doc->root.get();
606   ASSERT_THAT(manifest_el, NotNull());
607 
608   xml::Attribute* attr =
609       manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
610   ASSERT_THAT(attr, NotNull());
611   EXPECT_THAT(attr->value, StrEq("Alpha"));
612 
613   attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
614   ASSERT_THAT(attr, NotNull());
615   EXPECT_THAT(attr->value, StrEq("0x10000000"));
616 
617   attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
618   ASSERT_THAT(attr, NotNull());
619   EXPECT_THAT(attr->value, StrEq("0x00000002"));
620 }
621 
622 TEST_F(ManifestFixerTest, ReplaceVersionCodeMajor) {
623   ManifestFixerOptions options;
624   options.replace_version = true;
625   options.version_code_major_default = std::string("0x20000000");
626 
627   std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
628   <manifest xmlns:android="http://schemas.android.com/apk/res/android"
629           package="android"
630           android:versionCode="0x00000001"
631           android:versionCodeMajor="0x00000002"
632           android:versionName="Alpha" />)EOF",
633                                                             options);
634   ASSERT_THAT(doc, NotNull());
635 
636   xml::Element* manifest_el = doc->root.get();
637   ASSERT_THAT(manifest_el, NotNull());
638 
639   xml::Attribute* attr =
640       manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
641   ASSERT_THAT(attr, NotNull());
642   EXPECT_THAT(attr->value, StrEq("Alpha"));
643 
644   attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
645   ASSERT_THAT(attr, NotNull());
646   EXPECT_THAT(attr->value, StrEq("0x00000001"));
647 
648   attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
649   ASSERT_THAT(attr, NotNull());
650   EXPECT_THAT(attr->value, StrEq("0x20000000"));
651 }
652 
653 TEST_F(ManifestFixerTest, DontReplaceVersionNameOrCode) {
654   ManifestFixerOptions options;
655   options.replace_version = true;
656 
657   std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
658   <manifest xmlns:android="http://schemas.android.com/apk/res/android"
659             package="android"
660             android:versionCode="0x00000001"
661             android:versionCodeMajor="0x00000002"
662             android:versionName="Alpha" />)EOF",
663                                                             options);
664   ASSERT_THAT(doc, NotNull());
665 
666   xml::Element* manifest_el = doc->root.get();
667   ASSERT_THAT(manifest_el, NotNull());
668 
669   xml::Attribute* attr =
670       manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
671   ASSERT_THAT(attr, NotNull());
672   EXPECT_THAT(attr->value, StrEq("Alpha"));
673 
674   attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
675   ASSERT_THAT(attr, NotNull());
676   EXPECT_THAT(attr->value, StrEq("0x00000001"));
677 
678   attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
679   ASSERT_THAT(attr, NotNull());
680   EXPECT_THAT(attr->value, StrEq("0x00000002"));
681 }
682 
683 TEST_F(ManifestFixerTest, MarkNonUpdatableSystem) {
684   ManifestFixerOptions options;
685   options.non_updatable_system = true;
686 
687   std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
688       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
689                 package="android" />)EOF",
690                                                             options);
691   ASSERT_THAT(doc, NotNull());
692 
693   xml::Element* manifest_el = doc->root.get();
694   ASSERT_THAT(manifest_el, NotNull());
695 
696   xml::Attribute* attr = manifest_el->FindAttribute("", "updatableSystem");
697   ASSERT_THAT(attr, NotNull());
698   EXPECT_THAT(attr->value, StrEq("false"));
699 }
700 
701 TEST_F(ManifestFixerTest, MarkNonUpdatableSystemOverwritingValue) {
702   ManifestFixerOptions options;
703   options.non_updatable_system = true;
704 
705   std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
706       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
707                 package="android"
708                 updatableSystem="true" />)EOF",
709                                                             options);
710   ASSERT_THAT(doc, NotNull());
711 
712   xml::Element* manifest_el = doc->root.get();
713   ASSERT_THAT(manifest_el, NotNull());
714 
715   xml::Attribute* attr = manifest_el->FindAttribute("", "updatableSystem");
716   ASSERT_THAT(attr, NotNull());
717   EXPECT_THAT(attr->value, StrEq("false"));
718 }
719 
720 TEST_F(ManifestFixerTest, DontMarkNonUpdatableSystemWhenExplicitVersion) {
721   ManifestFixerOptions options;
722   options.non_updatable_system = true;
723 
724   std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
725       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
726                 package="android"
727                 android:versionCode="0x00000001" />)EOF",
728                                                             options);
729   ASSERT_THAT(doc, NotNull());
730 
731   xml::Element* manifest_el = doc->root.get();
732   ASSERT_THAT(manifest_el, NotNull());
733 
734   xml::Attribute* attr = manifest_el->FindAttribute("", "updatableSystem");
735   ASSERT_THAT(attr, IsNull());
736 }
737 
738 TEST_F(ManifestFixerTest, DontMarkNonUpdatableSystemWhenAddedVersion) {
739   ManifestFixerOptions options;
740   options.non_updatable_system = true;
741   options.version_code_default = std::string("0x10000000");
742 
743   std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
744       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
745                 package="android" />)EOF",
746                                                             options);
747   ASSERT_THAT(doc, NotNull());
748 
749   xml::Element* manifest_el = doc->root.get();
750   ASSERT_THAT(manifest_el, NotNull());
751 
752   xml::Attribute* attr = manifest_el->FindAttribute("", "updatableSystem");
753   ASSERT_THAT(attr, IsNull());
754 
755   attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
756   ASSERT_THAT(attr, NotNull());
757   EXPECT_THAT(attr->value, StrEq("0x10000000"));
758 }
759 
760 TEST_F(ManifestFixerTest, EnsureManifestAttributesAreTyped) {
761   EXPECT_THAT(Verify("<manifest package=\"android\" coreApp=\"hello\" />"), IsNull());
762   EXPECT_THAT(Verify("<manifest package=\"android\" coreApp=\"1dp\" />"), IsNull());
763 
764   std::unique_ptr<xml::XmlResource> doc =
765       Verify("<manifest package=\"android\" coreApp=\"true\" />");
766   ASSERT_THAT(doc, NotNull());
767 
768   xml::Element* el = doc->root.get();
769   ASSERT_THAT(el, NotNull());
770 
771   EXPECT_THAT(el->name, StrEq("manifest"));
772 
773   xml::Attribute* attr = el->FindAttribute("", "coreApp");
774   ASSERT_THAT(attr, NotNull());
775 
776   EXPECT_THAT(attr->compiled_value, NotNull());
777   EXPECT_THAT(ValueCast<BinaryPrimitive>(attr->compiled_value.get()), NotNull());
778 }
779 
TEST_F(ManifestFixerTest,UsesFeatureMustHaveNameOrGlEsVersion)780 TEST_F(ManifestFixerTest, UsesFeatureMustHaveNameOrGlEsVersion) {
781   std::string input = R"EOF(
782         <manifest xmlns:android="http://schemas.android.com/apk/res/android"
783                   package="android">
784           <uses-feature android:name="feature" />
785           <uses-feature android:glEsVersion="1" />
786           <feature-group />
787           <feature-group>
788             <uses-feature android:name="feature_in_group" />
789             <uses-feature android:glEsVersion="2" />
790           </feature-group>
791         </manifest>)EOF";
792   EXPECT_THAT(Verify(input), NotNull());
793 
794   input = R"EOF(
795         <manifest xmlns:android="http://schemas.android.com/apk/res/android"
796                   package="android">
797           <uses-feature android:name="feature" android:glEsVersion="1" />
798         </manifest>)EOF";
799   EXPECT_THAT(Verify(input), IsNull());
800 
801   input = R"EOF(
802         <manifest xmlns:android="http://schemas.android.com/apk/res/android"
803                   package="android">
804           <uses-feature />
805         </manifest>)EOF";
806   EXPECT_THAT(Verify(input), IsNull());
807 
808   input = R"EOF(
809         <manifest xmlns:android="http://schemas.android.com/apk/res/android"
810                   package="android">
811           <feature-group>
812             <uses-feature android:name="feature" android:glEsVersion="1" />
813           </feature-group>
814         </manifest>)EOF";
815   EXPECT_THAT(Verify(input), IsNull());
816 
817   input = R"EOF(
818         <manifest xmlns:android="http://schemas.android.com/apk/res/android"
819                   package="android">
820           <feature-group>
821             <uses-feature />
822           </feature-group>
823         </manifest>)EOF";
824   EXPECT_THAT(Verify(input), IsNull());
825 }
826 
827 TEST_F(ManifestFixerTest, ApplicationInjectDebuggable) {
828   ManifestFixerOptions options;
829   options.debug_mode = true;
830 
831   std::string no_d = R"(
832       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
833           package="android">
834         <application>
835         </application>
836       </manifest>)";
837 
838   std::string false_d = R"(
839       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
840           package="android">
841         <application android:debuggable="false">
842         </application>
843       </manifest>)";
844 
845   std::string true_d = R"(
846       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
847           package="android">
848         <application android:debuggable="true">
849         </application>
850       </manifest>)";
851 
852   // Inject the debuggable attribute when the attribute is not present and the
853   // flag is present
854   std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(no_d, options);
855   EXPECT_THAT(manifest->root.get()->FindChildWithAttribute(
856       {}, "application", xml::kSchemaAndroid, "debuggable", "true"), NotNull());
857 
858   // Set the debuggable flag to true if the attribute is false and the flag is
859   // present
860   manifest = VerifyWithOptions(false_d, options);
861   EXPECT_THAT(manifest->root.get()->FindChildWithAttribute(
862       {}, "application", xml::kSchemaAndroid, "debuggable", "true"), NotNull());
863 
864   // Keep debuggable flag true if the attribute is true and the flag is present
865   manifest = VerifyWithOptions(true_d, options);
866   EXPECT_THAT(manifest->root.get()->FindChildWithAttribute(
867       {}, "application", xml::kSchemaAndroid, "debuggable", "true"), NotNull());
868 
869   // Do not inject the debuggable attribute when the attribute is not present
870   // and the flag is not present
871   manifest = Verify(no_d);
872   EXPECT_THAT(manifest->root.get()->FindChildWithAttribute(
873       {}, "application", xml::kSchemaAndroid, "debuggable", "true"), IsNull());
874 
875   // Do not set the debuggable flag to true if the attribute is false and the
876   // flag is not present
877   manifest = Verify(false_d);
878   EXPECT_THAT(manifest->root.get()->FindChildWithAttribute(
879       {}, "application", xml::kSchemaAndroid, "debuggable", "true"), IsNull());
880 
881   // Keep debuggable flag true if the attribute is true and the flag is not
882   // present
883   manifest = Verify(true_d);
884   EXPECT_THAT(manifest->root.get()->FindChildWithAttribute(
885       {}, "application", xml::kSchemaAndroid, "debuggable", "true"), NotNull());
886 }
887 
888 TEST_F(ManifestFixerTest, ApplicationProfileable) {
889   std::string shell = R"(
890       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
891           package="android">
892         <application>
893           <profileable android:shell="true"/>
894         </application>
895       </manifest>)";
896   EXPECT_THAT(Verify(shell), NotNull());
897   std::string noshell = R"(
898       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
899           package="android">
900         <application>
901           <profileable/>
902         </application>
903       </manifest>)";
904   EXPECT_THAT(Verify(noshell), NotNull());
905 }
906 
907 TEST_F(ManifestFixerTest, IgnoreNamespacedElements) {
908   std::string input = R"EOF(
909       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
910                 package="android">
911         <special:tag whoo="true" xmlns:special="http://google.com" />
912       </manifest>)EOF";
913   EXPECT_THAT(Verify(input), NotNull());
914 }
915 
916 TEST_F(ManifestFixerTest, DoNotIgnoreNonNamespacedElements) {
917   std::string input = R"EOF(
918       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
919                 package="android">
920         <tag whoo="true" />
921       </manifest>)EOF";
922   EXPECT_THAT(Verify(input), IsNull());
923 }
924 
925 TEST_F(ManifestFixerTest, SupportKeySets) {
926   std::string input = R"(
927       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
928           package="android">
929         <key-sets>
930           <key-set android:name="old-set">
931             <public-key android:name="old-key" android:value="some+old+key" />
932           </key-set>
933           <key-set android:name="new-set">
934             <public-key android:name="new-key" android:value="some+new+key" />
935           </key-set>
936           <upgrade-key-set android:name="old-set" />
937           <upgrade-key-set android:name="new-set" />
938         </key-sets>
939       </manifest>)";
940   EXPECT_THAT(Verify(input), NotNull());
941 }
942 
943 TEST_F(ManifestFixerTest, InsertCompileSdkVersions) {
944   std::string input = R"(<manifest package="com.pkg" />)";
945   ManifestFixerOptions options;
946   options.compile_sdk_version = {"28"};
947   options.compile_sdk_version_codename = {"P"};
948 
949   std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options);
950   ASSERT_THAT(manifest, NotNull());
951 
952   // There should be a declaration of kSchemaAndroid, even when the input
953   // didn't have one.
954   EXPECT_EQ(manifest->root->namespace_decls.size(), 1);
955   EXPECT_EQ(manifest->root->namespace_decls[0].prefix, "android");
956   EXPECT_EQ(manifest->root->namespace_decls[0].uri, xml::kSchemaAndroid);
957 
958   xml::Attribute* attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersion");
959   ASSERT_THAT(attr, NotNull());
960   EXPECT_THAT(attr->value, StrEq("28"));
961 
962   attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersionCodename");
963   ASSERT_THAT(attr, NotNull());
964   EXPECT_THAT(attr->value, StrEq("P"));
965 
966   attr = manifest->root->FindAttribute("", "platformBuildVersionCode");
967   ASSERT_THAT(attr, NotNull());
968   EXPECT_THAT(attr->value, StrEq("28"));
969 
970   attr = manifest->root->FindAttribute("", "platformBuildVersionName");
971   ASSERT_THAT(attr, NotNull());
972   EXPECT_THAT(attr->value, StrEq("P"));
973 }
974 
975 TEST_F(ManifestFixerTest, DoNotInsertCompileSdkVersions) {
976   std::string input = R"(<manifest package="com.pkg" />)";
977   ManifestFixerOptions options;
978   options.no_compile_sdk_metadata = true;
979   options.compile_sdk_version = {"28"};
980   options.compile_sdk_version_codename = {"P"};
981 
982   std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options);
983   ASSERT_THAT(manifest, NotNull());
984 
985   // There should be a declaration of kSchemaAndroid, even when the input
986   // didn't have one.
987   EXPECT_EQ(manifest->root->namespace_decls.size(), 1);
988   EXPECT_EQ(manifest->root->namespace_decls[0].prefix, "android");
989   EXPECT_EQ(manifest->root->namespace_decls[0].uri, xml::kSchemaAndroid);
990 
991   xml::Attribute* attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersion");
992   ASSERT_THAT(attr, IsNull());
993 
994   attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersionCodename");
995   ASSERT_THAT(attr, IsNull());
996 
997   attr = manifest->root->FindAttribute("", "platformBuildVersionCode");
998   ASSERT_THAT(attr, IsNull());
999 
1000   attr = manifest->root->FindAttribute("", "platformBuildVersionName");
1001   ASSERT_THAT(attr, IsNull());
1002 }
1003 
1004 TEST_F(ManifestFixerTest, OverrideCompileSdkVersions) {
1005   std::string input = R"(
1006       <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"
1007           compileSdkVersion="27" compileSdkVersionCodename="O"
1008           platformBuildVersionCode="27" platformBuildVersionName="O"/>)";
1009   ManifestFixerOptions options;
1010   options.compile_sdk_version = {"28"};
1011   options.compile_sdk_version_codename = {"P"};
1012 
1013   std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options);
1014   ASSERT_THAT(manifest, NotNull());
1015 
1016   xml::Attribute* attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersion");
1017   ASSERT_THAT(attr, NotNull());
1018   EXPECT_THAT(attr->value, StrEq("28"));
1019 
1020   attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersionCodename");
1021   ASSERT_THAT(attr, NotNull());
1022   EXPECT_THAT(attr->value, StrEq("P"));
1023 
1024   attr = manifest->root->FindAttribute("", "platformBuildVersionCode");
1025   ASSERT_THAT(attr, NotNull());
1026   EXPECT_THAT(attr->value, StrEq("28"));
1027 
1028   attr = manifest->root->FindAttribute("", "platformBuildVersionName");
1029   ASSERT_THAT(attr, NotNull());
1030   EXPECT_THAT(attr->value, StrEq("P"));
1031 }
1032 
1033 TEST_F(ManifestFixerTest, AndroidPrefixAlreadyUsed) {
1034   std::string input =
1035       R"(<manifest package="com.pkg"
1036          xmlns:android="http://schemas.android.com/apk/prv/res/android"
1037          android:private_attr="foo" />)";
1038   ManifestFixerOptions options;
1039   options.compile_sdk_version = {"28"};
1040   options.compile_sdk_version_codename = {"P"};
1041 
1042   std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options);
1043   ASSERT_THAT(manifest, NotNull());
1044 
1045   // Make sure that we don't redefine "android".
1046   EXPECT_EQ(manifest->root->namespace_decls.size(), 2);
1047   EXPECT_EQ(manifest->root->namespace_decls[0].prefix, "android");
1048   EXPECT_EQ(manifest->root->namespace_decls[0].uri,
1049             "http://schemas.android.com/apk/prv/res/android");
1050   EXPECT_EQ(manifest->root->namespace_decls[1].prefix, "android0");
1051   EXPECT_EQ(manifest->root->namespace_decls[1].uri, xml::kSchemaAndroid);
1052 }
1053 
TEST_F(ManifestFixerTest,UnexpectedElementsInManifest)1054 TEST_F(ManifestFixerTest, UnexpectedElementsInManifest) {
1055   std::string input = R"(
1056       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1057           package="android">
1058         <beep/>
1059       </manifest>)";
1060   ManifestFixerOptions options;
1061   options.warn_validation = true;
1062 
1063   // Unexpected element should result in a warning if the flag is set to 'true'.
1064   std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options);
1065   ASSERT_THAT(manifest, NotNull());
1066 
1067   // Unexpected element should result in an error if the flag is set to 'false'.
1068   options.warn_validation = false;
1069   manifest = VerifyWithOptions(input, options);
1070   ASSERT_THAT(manifest, IsNull());
1071 
1072   // By default the flag should be set to 'false'.
1073   manifest = Verify(input);
1074   ASSERT_THAT(manifest, IsNull());
1075 }
1076 
1077 TEST_F(ManifestFixerTest, InsertFingerprintPrefixIfNotExist) {
1078   std::string input = R"(
1079       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1080           package="android">
1081       </manifest>)";
1082   ManifestFixerOptions options;
1083   options.fingerprint_prefixes = {"foo", "bar"};
1084 
1085   std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options);
1086   ASSERT_THAT(manifest, NotNull());
1087   xml::Element* install_constraints = manifest->root.get()->FindChild({}, "install-constraints");
1088   ASSERT_THAT(install_constraints, NotNull());
1089   std::vector<xml::Element*> fingerprint_prefixes = install_constraints->GetChildElements();
1090   EXPECT_EQ(fingerprint_prefixes.size(), 2);
1091   xml::Attribute* attr;
1092   EXPECT_THAT(fingerprint_prefixes[0]->name, StrEq("fingerprint-prefix"));
1093   attr = fingerprint_prefixes[0]->FindAttribute(xml::kSchemaAndroid, "value");
1094   ASSERT_THAT(attr, NotNull());
1095   EXPECT_THAT(attr->value, StrEq("foo"));
1096   EXPECT_THAT(fingerprint_prefixes[1]->name, StrEq("fingerprint-prefix"));
1097   attr = fingerprint_prefixes[1]->FindAttribute(xml::kSchemaAndroid, "value");
1098   ASSERT_THAT(attr, NotNull());
1099   EXPECT_THAT(attr->value, StrEq("bar"));
1100 }
1101 
1102 TEST_F(ManifestFixerTest, AppendFingerprintPrefixIfExists) {
1103   std::string input = R"(
1104       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1105           package="android">
1106           <install-constraints>
1107             <fingerprint-prefix android:value="foo" />
1108           </install-constraints>
1109       </manifest>)";
1110   ManifestFixerOptions options;
1111   options.fingerprint_prefixes = {"bar", "baz"};
1112 
1113   std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options);
1114   ASSERT_THAT(manifest, NotNull());
1115   xml::Element* install_constraints = manifest->root.get()->FindChild({}, "install-constraints");
1116   ASSERT_THAT(install_constraints, NotNull());
1117   std::vector<xml::Element*> fingerprint_prefixes = install_constraints->GetChildElements();
1118   EXPECT_EQ(fingerprint_prefixes.size(), 3);
1119   xml::Attribute* attr;
1120   EXPECT_THAT(fingerprint_prefixes[0]->name, StrEq("fingerprint-prefix"));
1121   attr = fingerprint_prefixes[0]->FindAttribute(xml::kSchemaAndroid, "value");
1122   ASSERT_THAT(attr, NotNull());
1123   EXPECT_THAT(attr->value, StrEq("foo"));
1124   EXPECT_THAT(fingerprint_prefixes[1]->name, StrEq("fingerprint-prefix"));
1125   attr = fingerprint_prefixes[1]->FindAttribute(xml::kSchemaAndroid, "value");
1126   ASSERT_THAT(attr, NotNull());
1127   EXPECT_THAT(attr->value, StrEq("bar"));
1128   EXPECT_THAT(fingerprint_prefixes[2]->name, StrEq("fingerprint-prefix"));
1129   attr = fingerprint_prefixes[2]->FindAttribute(xml::kSchemaAndroid, "value");
1130   ASSERT_THAT(attr, NotNull());
1131   EXPECT_THAT(attr->value, StrEq("baz"));
1132 }
1133 
1134 TEST_F(ManifestFixerTest, UsesLibraryMustHaveNonEmptyName) {
1135   std::string input = R"(
1136       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1137           package="android">
1138         <application>
1139           <uses-library android:name="" />
1140         </application>
1141       </manifest>)";
1142   EXPECT_THAT(Verify(input), IsNull());
1143 
1144   input = R"(
1145       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1146           package="android">
1147         <application>
1148           <uses-library />
1149         </application>
1150       </manifest>)";
1151   EXPECT_THAT(Verify(input), IsNull());
1152 
1153   input = R"(
1154        <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1155            package="android">
1156          <application>
1157            <uses-library android:name="blahhh" />
1158          </application>
1159        </manifest>)";
1160   EXPECT_THAT(Verify(input), NotNull());
1161 }
1162 
1163 TEST_F(ManifestFixerTest, ApplicationPropertyAttributeRequired) {
1164   std::string input = R"(
1165       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1166           package="android">
1167         <application>
1168           <property android:name="" />
1169         </application>
1170       </manifest>)";
1171   EXPECT_THAT(Verify(input), IsNull());
1172 }
1173 
1174 TEST_F(ManifestFixerTest, ApplicationPropertyOnlyOneAttributeDefined) {
1175   std::string input = R"(
1176       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1177           package="android">
1178         <application>
1179           <property android:name="" android:value="" android:resource="" />
1180         </application>
1181       </manifest>)";
1182   EXPECT_THAT(Verify(input), IsNull());
1183 
1184   input = R"(
1185       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1186           package="android">
1187         <application>
1188           <property android:name="" android:resource="" />
1189         </application>
1190       </manifest>)";
1191   EXPECT_THAT(Verify(input), NotNull());
1192 
1193   input = R"(
1194       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1195           package="android">
1196         <application>
1197           <property android:name="" android:value="" />
1198         </application>
1199       </manifest>)";
1200   EXPECT_THAT(Verify(input), NotNull());
1201 }
1202 
1203 TEST_F(ManifestFixerTest, ComponentPropertyOnlyOneAttributeDefined) {
1204   std::string input = R"(
1205       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1206           package="android">
1207         <application>
1208           <activity android:name=".MyActivity">
1209             <property android:name="" android:value="" android:resource="" />
1210           </activity>
1211         </application>
1212       </manifest>)";
1213   EXPECT_THAT(Verify(input), IsNull());
1214 
1215   input = R"(
1216       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1217           package="android">
1218         <application>
1219           <activity android:name=".MyActivity">
1220             <property android:name="" android:value="" />
1221           </activity>
1222         </application>
1223       </manifest>)";
1224   EXPECT_THAT(Verify(input), NotNull());
1225 
1226   input = R"(
1227       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1228           package="android">
1229         <application>
1230           <activity android:name=".MyActivity">
1231             <property android:name="" android:resource="" />
1232           </activity>
1233         </application>
1234       </manifest>)";
1235   EXPECT_THAT(Verify(input), NotNull());
1236 }
1237 
1238 TEST_F(ManifestFixerTest, IntentFilterActionMustHaveNonEmptyName) {
1239   std::string input = R"(
1240     <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1241         package="android">
1242       <application>
1243         <activity android:name=".MainActivity">
1244           <intent-filter>
1245             <action android:name="" />
1246           </intent-filter>
1247         </activity>
1248       </application>
1249     </manifest>)";
1250   EXPECT_THAT(Verify(input), IsNull());
1251 
1252   input = R"(
1253     <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1254              package="android">
1255       <application>
1256         <activity android:name=".MainActivity">
1257           <intent-filter>
1258             <action />
1259           </intent-filter>
1260         </activity>
1261       </application>
1262     </manifest>)";
1263   EXPECT_THAT(Verify(input), IsNull());
1264 
1265   input = R"(
1266     <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1267         package="android">
1268       <application>
1269         <activity android:name=".MainActivity">
1270           <intent-filter>
1271             <action android:name="android.intent.action.MAIN" />
1272           </intent-filter>
1273         </activity>
1274       </application>
1275     </manifest>)";
1276   EXPECT_THAT(Verify(input), NotNull());
1277 }
1278 
1279 TEST_F(ManifestFixerTest, IntentFilterCategoryMustHaveNonEmptyName) {
1280   std::string input = R"(
1281     <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1282         package="android">
1283       <application>
1284         <activity android:name=".MainActivity">
1285           <intent-filter>
1286             <category android:name="" />
1287           </intent-filter>
1288         </activity>
1289       </application>
1290     </manifest>)";
1291   EXPECT_THAT(Verify(input), IsNull());
1292 
1293   input = R"(
1294     <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1295              package="android">
1296       <application>
1297         <activity android:name=".MainActivity">
1298           <intent-filter>
1299             <category />
1300           </intent-filter>
1301         </activity>
1302       </application>
1303     </manifest>)";
1304   EXPECT_THAT(Verify(input), IsNull());
1305 
1306   input = R"(
1307     <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1308         package="android">
1309       <application>
1310         <activity android:name=".MainActivity">
1311           <intent-filter>
1312             <category android:name="android.intent.category.LAUNCHER" />
1313           </intent-filter>
1314         </activity>
1315       </application>
1316     </manifest>)";
1317   EXPECT_THAT(Verify(input), NotNull());
1318 }
1319 
1320 TEST_F(ManifestFixerTest, IntentFilterPathMustStartWithLeadingSlashOnDeepLinks) {
1321   // No DeepLink.
1322   std::string input = R"(
1323     <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1324              package="android">
1325       <application>
1326         <activity android:name=".MainActivity">
1327           <intent-filter>
1328             <data />
1329           </intent-filter>
1330         </activity>
1331       </application>
1332     </manifest>)";
1333   EXPECT_THAT(Verify(input), NotNull());
1334 
1335   // No DeepLink, missing ACTION_VIEW.
1336   input = R"(
1337     <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1338         package="android">
1339       <application>
1340         <activity android:name=".MainActivity">
1341           <intent-filter>
1342             <category android:name="android.intent.category.DEFAULT" />
1343             <category android:name="android.intent.category.BROWSABLE" />
1344             <data android:scheme="http"
1345                           android:host="www.example.com"
1346                           android:pathPrefix="pathPattern" />
1347           </intent-filter>
1348         </activity>
1349       </application>
1350     </manifest>)";
1351   EXPECT_THAT(Verify(input), NotNull());
1352 
1353   // DeepLink, missing DEFAULT category while DEFAULT is recommended but not required.
1354   input = R"(
1355     <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1356         package="android">
1357       <application>
1358         <activity android:name=".MainActivity">
1359           <intent-filter>
1360             <action android:name="android.intent.action.VIEW" />
1361             <category android:name="android.intent.category.BROWSABLE" />
1362             <data android:scheme="http"
1363                           android:host="www.example.com"
1364                           android:pathPrefix="pathPattern" />
1365           </intent-filter>
1366         </activity>
1367       </application>
1368     </manifest>)";
1369   EXPECT_THAT(Verify(input), IsNull());
1370 
1371   // No DeepLink, missing BROWSABLE category.
1372   input = R"(
1373     <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1374         package="android">
1375       <application>
1376         <activity android:name=".MainActivity">
1377           <intent-filter>
1378             <action android:name="android.intent.action.VIEW" />
1379             <category android:name="android.intent.category.DEFAULT" />
1380             <data android:scheme="http"
1381                           android:host="www.example.com"
1382                           android:pathPrefix="pathPattern" />
1383           </intent-filter>
1384         </activity>
1385       </application>
1386     </manifest>)";
1387   EXPECT_THAT(Verify(input), NotNull());
1388 
1389   // No DeepLink, missing 'android:scheme' in <data> tag.
1390   input = R"(
1391     <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1392         package="android">
1393       <application>
1394         <activity android:name=".MainActivity">
1395           <intent-filter>
1396             <action android:name="android.intent.action.VIEW" />
1397             <category android:name="android.intent.category.DEFAULT" />
1398             <category android:name="android.intent.category.BROWSABLE" />
1399             <data android:host="www.example.com"
1400                           android:pathPrefix="pathPattern" />
1401           </intent-filter>
1402         </activity>
1403       </application>
1404     </manifest>)";
1405   EXPECT_THAT(Verify(input), NotNull());
1406 
1407   // No DeepLink, <action> is ACTION_MAIN not ACTION_VIEW.
1408   input = R"(
1409     <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1410         package="android">
1411       <application>
1412         <activity android:name=".MainActivity">
1413           <intent-filter>
1414             <action android:name="android.intent.action.MAIN" />
1415             <category android:name="android.intent.category.DEFAULT" />
1416             <category android:name="android.intent.category.BROWSABLE" />
1417             <data android:scheme="http"
1418                           android:host="www.example.com"
1419                           android:pathPrefix="pathPattern" />
1420           </intent-filter>
1421         </activity>
1422       </application>
1423     </manifest>)";
1424   EXPECT_THAT(Verify(input), NotNull());
1425 
1426   // DeepLink with no leading slash in android:path.
1427   input = R"(
1428     <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1429         package="android">
1430       <application>
1431         <activity android:name=".MainActivity">
1432           <intent-filter>
1433             <action android:name="android.intent.action.VIEW" />
1434             <category android:name="android.intent.category.DEFAULT" />
1435             <category android:name="android.intent.category.BROWSABLE" />
1436             <data android:scheme="http"
1437                           android:host="www.example.com"
1438                           android:path="path" />
1439           </intent-filter>
1440         </activity>
1441       </application>
1442     </manifest>)";
1443   EXPECT_THAT(Verify(input), IsNull());
1444 
1445   // DeepLink with leading slash in android:path.
1446   input = R"(
1447     <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1448         package="android">
1449       <application>
1450         <activity android:name=".MainActivity">
1451           <intent-filter>
1452             <action android:name="android.intent.action.VIEW" />
1453             <category android:name="android.intent.category.DEFAULT" />
1454             <category android:name="android.intent.category.BROWSABLE" />
1455             <data android:scheme="http"
1456                           android:host="www.example.com"
1457                           android:path="/path" />
1458           </intent-filter>
1459         </activity>
1460       </application>
1461     </manifest>)";
1462   EXPECT_THAT(Verify(input), NotNull());
1463 
1464   // DeepLink with no leading slash in android:pathPrefix.
1465   input = R"(
1466     <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1467         package="android">
1468       <application>
1469         <activity android:name=".MainActivity">
1470           <intent-filter>
1471             <action android:name="android.intent.action.VIEW" />
1472             <category android:name="android.intent.category.DEFAULT" />
1473             <category android:name="android.intent.category.BROWSABLE" />
1474             <data android:scheme="http"
1475                           android:host="www.example.com"
1476                           android:pathPrefix="pathPrefix" />
1477           </intent-filter>
1478         </activity>
1479       </application>
1480     </manifest>)";
1481   EXPECT_THAT(Verify(input), IsNull());
1482 
1483   // DeepLink with leading slash in android:pathPrefix.
1484   input = R"(
1485     <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1486         package="android">
1487       <application>
1488         <activity android:name=".MainActivity">
1489           <intent-filter>
1490             <action android:name="android.intent.action.VIEW" />
1491             <category android:name="android.intent.category.DEFAULT" />
1492             <category android:name="android.intent.category.BROWSABLE" />
1493             <data android:scheme="http"
1494                           android:host="www.example.com"
1495                           android:pathPrefix="/pathPrefix" />
1496           </intent-filter>
1497         </activity>
1498       </application>
1499     </manifest>)";
1500   EXPECT_THAT(Verify(input), NotNull());
1501 
1502   // DeepLink with no leading slash in android:pathPattern.
1503   input = R"(
1504     <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1505         package="android">
1506       <application>
1507         <activity android:name=".MainActivity">
1508           <intent-filter>
1509             <action android:name="android.intent.action.VIEW" />
1510             <category android:name="android.intent.category.DEFAULT" />
1511             <category android:name="android.intent.category.BROWSABLE" />
1512             <data android:scheme="http"
1513                           android:host="www.example.com"
1514                           android:pathPattern="pathPattern" />
1515           </intent-filter>
1516         </activity>
1517       </application>
1518     </manifest>)";
1519   EXPECT_THAT(Verify(input), IsNull());
1520 
1521   // DeepLink with leading slash in android:pathPattern.
1522   input = R"(
1523     <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1524         package="android">
1525       <application>
1526         <activity android:name=".MainActivity">
1527           <intent-filter>
1528             <action android:name="android.intent.action.VIEW" />
1529             <category android:name="android.intent.category.DEFAULT" />
1530             <category android:name="android.intent.category.BROWSABLE" />
1531             <data android:scheme="http"
1532                           android:host="www.example.com"
1533                           android:pathPattern="/pathPattern" />
1534           </intent-filter>
1535         </activity>
1536       </application>
1537     </manifest>)";
1538   EXPECT_THAT(Verify(input), NotNull());
1539 
1540   // DeepLink with '.' start in pathPattern.
1541   input = R"(
1542     <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1543         package="android">
1544       <application>
1545         <activity android:name=".MainActivity">
1546           <intent-filter>
1547             <action android:name="android.intent.action.VIEW" />
1548             <category android:name="android.intent.category.DEFAULT" />
1549             <category android:name="android.intent.category.BROWSABLE" />
1550             <data android:scheme="http"
1551                           android:host="www.example.com"
1552                           android:pathPattern=".*\\.pathPattern" />
1553           </intent-filter>
1554         </activity>
1555       </application>
1556     </manifest>)";
1557   EXPECT_THAT(Verify(input), NotNull());
1558 
1559   // DeepLink with '*' start in pathPattern.
1560   input = R"(
1561     <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1562         package="android">
1563       <application>
1564         <activity android:name=".MainActivity">
1565           <intent-filter>
1566             <action android:name="android.intent.action.VIEW" />
1567             <category android:name="android.intent.category.DEFAULT" />
1568             <category android:name="android.intent.category.BROWSABLE" />
1569             <data android:scheme="http"
1570                           android:host="www.example.com"
1571                           android:pathPattern="*" />
1572           </intent-filter>
1573         </activity>
1574       </application>
1575     </manifest>)";
1576   EXPECT_THAT(Verify(input), NotNull());
1577 
1578   // DeepLink with string reference as a path.
1579   input = R"(
1580     <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1581         package="android">
1582       <application>
1583         <activity android:name=".MainActivity">
1584           <intent-filter>
1585             <action android:name="android.intent.action.VIEW" />
1586             <category android:name="android.intent.category.DEFAULT" />
1587             <category android:name="android.intent.category.BROWSABLE" />
1588             <data android:scheme="http"
1589                           android:host="www.example.com"
1590                           android:path="@string/startup_uri" />
1591           </intent-filter>
1592         </activity>
1593       </application>
1594     </manifest>)";
1595   EXPECT_THAT(Verify(input), NotNull());
1596 }
1597 
1598 TEST_F(ManifestFixerTest, AllKnownNotDeclaredProperly) {
1599   std::string input = R"(
1600     <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1601         package="android">
1602       <application>
1603         <activity android:name=".MainActivity"
1604                   android:configChanges="allKnown|testConfigChange1">
1605         </activity>
1606       </application>
1607     </manifest>)";
1608   auto doc = Verify(input);
1609   EXPECT_THAT(doc, IsNull());
1610 }
1611 
1612 TEST_F(ManifestFixerTest, ModifyAttributeValueForAllKnown) {
1613   std::string input = R"(
1614     <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1615         package="android">
1616       <application>
1617         <activity android:name=".MainActivity"
1618                   android:configChanges="allKnown">
1619         </activity>
1620       </application>
1621     </manifest>)";
1622   auto doc = Verify(input);
1623   EXPECT_THAT(doc, NotNull());
1624 
1625   xml::Element* el;
1626   xml::Attribute* attr;
1627 
1628   el = doc->root.get();
1629   ASSERT_THAT(el, NotNull());
1630   el = el->FindChild({}, "application");
1631   ASSERT_THAT(el, NotNull());
1632   el = el->FindChild({}, "activity");
1633   ASSERT_THAT(el, NotNull());
1634 
1635   attr = el->FindAttribute(xml::kSchemaAndroid, "configChanges");
1636   ASSERT_THAT(attr->value, "testConfigChange1|testConfigChange2");
1637 }
1638 
1639 TEST_F(ManifestFixerTest, DoNothingForOtherConfigChanges) {
1640   std::string input = R"(
1641     <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1642         package="android">
1643       <application>
1644         <activity android:name=".MainActivity"
1645                   android:configChanges="testConfigChange2">
1646         </activity>
1647       </application>
1648     </manifest>)";
1649   auto doc = Verify(input);
1650   EXPECT_THAT(doc, NotNull());
1651 
1652   xml::Element* el;
1653   xml::Attribute* attr;
1654 
1655   el = doc->root.get();
1656   ASSERT_THAT(el, NotNull());
1657   el = el->FindChild({}, "application");
1658   ASSERT_THAT(el, NotNull());
1659   el = el->FindChild({}, "activity");
1660   ASSERT_THAT(el, NotNull());
1661 
1662   attr = el->FindAttribute(xml::kSchemaAndroid, "configChanges");
1663   ASSERT_THAT(attr->value, "testConfigChange2");
1664 }
1665 }  // namespace aapt
1666