• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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::NotNull;
23 
24 namespace aapt {
25 
26 struct ManifestFixerTest : public ::testing::Test {
27   std::unique_ptr<IAaptContext> mContext;
28 
SetUpaapt::ManifestFixerTest29   void SetUp() override {
30     mContext =
31         test::ContextBuilder()
32             .SetCompilationPackage("android")
33             .SetPackageId(0x01)
34             .SetNameManglerPolicy(NameManglerPolicy{"android"})
35             .AddSymbolSource(
36                 test::StaticSymbolSourceBuilder()
37                     .AddSymbol(
38                         "android:attr/package", ResourceId(0x01010000),
39                         test::AttributeBuilder()
40                             .SetTypeMask(android::ResTable_map::TYPE_STRING)
41                             .Build())
42                     .AddSymbol(
43                         "android:attr/minSdkVersion", ResourceId(0x01010001),
44                         test::AttributeBuilder()
45                             .SetTypeMask(android::ResTable_map::TYPE_STRING |
46                                          android::ResTable_map::TYPE_INTEGER)
47                             .Build())
48                     .AddSymbol(
49                         "android:attr/targetSdkVersion", ResourceId(0x01010002),
50                         test::AttributeBuilder()
51                             .SetTypeMask(android::ResTable_map::TYPE_STRING |
52                                          android::ResTable_map::TYPE_INTEGER)
53                             .Build())
54                     .AddSymbol("android:string/str", ResourceId(0x01060000))
55                     .Build())
56             .Build();
57   }
58 
Verifyaapt::ManifestFixerTest59   std::unique_ptr<xml::XmlResource> Verify(const StringPiece& str) {
60     return VerifyWithOptions(str, {});
61   }
62 
VerifyWithOptionsaapt::ManifestFixerTest63   std::unique_ptr<xml::XmlResource> VerifyWithOptions(
64       const StringPiece& str, const ManifestFixerOptions& options) {
65     std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(str);
66     ManifestFixer fixer(options);
67     if (fixer.Consume(mContext.get(), doc.get())) {
68       return doc;
69     }
70     return {};
71   }
72 };
73 
TEST_F(ManifestFixerTest,EnsureManifestIsRootTag)74 TEST_F(ManifestFixerTest, EnsureManifestIsRootTag) {
75   EXPECT_EQ(nullptr, Verify("<other-tag />"));
76   EXPECT_EQ(nullptr, Verify("<ns:manifest xmlns:ns=\"com\" />"));
77   EXPECT_NE(nullptr, Verify("<manifest package=\"android\"></manifest>"));
78 }
79 
TEST_F(ManifestFixerTest,EnsureManifestHasPackage)80 TEST_F(ManifestFixerTest, EnsureManifestHasPackage) {
81   EXPECT_NE(nullptr, Verify("<manifest package=\"android\" />"));
82   EXPECT_NE(nullptr, Verify("<manifest package=\"com.android\" />"));
83   EXPECT_NE(nullptr, Verify("<manifest package=\"com.android.google\" />"));
84   EXPECT_EQ(nullptr,
85             Verify("<manifest package=\"com.android.google.Class$1\" />"));
86   EXPECT_EQ(nullptr, Verify("<manifest "
87                             "xmlns:android=\"http://schemas.android.com/apk/"
88                             "res/android\" "
89                             "android:package=\"com.android\" />"));
90   EXPECT_EQ(nullptr, Verify("<manifest package=\"@string/str\" />"));
91 }
92 
TEST_F(ManifestFixerTest,AllowMetaData)93 TEST_F(ManifestFixerTest, AllowMetaData) {
94   auto doc = Verify(R"EOF(
95         <manifest xmlns:android="http://schemas.android.com/apk/res/android"
96                   package="android">
97           <meta-data />
98           <application>
99             <meta-data />
100             <activity android:name=".Hi"><meta-data /></activity>
101             <activity-alias android:name=".Ho"><meta-data /></activity-alias>
102             <receiver android:name=".OffTo"><meta-data /></receiver>
103             <provider android:name=".Work"><meta-data /></provider>
104             <service android:name=".We"><meta-data /></service>
105           </application>
106           <instrumentation android:name=".Go"><meta-data /></instrumentation>
107         </manifest>)EOF");
108   ASSERT_NE(nullptr, doc);
109 }
110 
111 TEST_F(ManifestFixerTest, UseDefaultSdkVersionsIfNonePresent) {
112   ManifestFixerOptions options = {std::string("8"), std::string("22")};
113 
114   std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
115       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
116                 package="android">
117         <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="21" />
118       </manifest>)EOF",
119                                                             options);
120   ASSERT_NE(nullptr, doc);
121 
122   xml::Element* el;
123   xml::Attribute* attr;
124 
125   el = doc->root.get();
126   ASSERT_NE(nullptr, el);
127   el = el->FindChild({}, "uses-sdk");
128   ASSERT_NE(nullptr, el);
129   attr = el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion");
130   ASSERT_NE(nullptr, attr);
131   EXPECT_EQ("7", attr->value);
132   attr = el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion");
133   ASSERT_NE(nullptr, attr);
134   EXPECT_EQ("21", attr->value);
135 
136   doc = VerifyWithOptions(R"EOF(
137       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
138                 package="android">
139         <uses-sdk android:targetSdkVersion="21" />
140       </manifest>)EOF",
141                           options);
142   ASSERT_NE(nullptr, doc);
143 
144   el = doc->root.get();
145   ASSERT_NE(nullptr, el);
146   el = el->FindChild({}, "uses-sdk");
147   ASSERT_NE(nullptr, el);
148   attr = el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion");
149   ASSERT_NE(nullptr, attr);
150   EXPECT_EQ("8", attr->value);
151   attr = el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion");
152   ASSERT_NE(nullptr, attr);
153   EXPECT_EQ("21", attr->value);
154 
155   doc = VerifyWithOptions(R"EOF(
156       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
157                 package="android">
158         <uses-sdk />
159       </manifest>)EOF",
160                           options);
161   ASSERT_NE(nullptr, doc);
162 
163   el = doc->root.get();
164   ASSERT_NE(nullptr, el);
165   el = el->FindChild({}, "uses-sdk");
166   ASSERT_NE(nullptr, el);
167   attr = el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion");
168   ASSERT_NE(nullptr, attr);
169   EXPECT_EQ("8", attr->value);
170   attr = el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion");
171   ASSERT_NE(nullptr, attr);
172   EXPECT_EQ("22", attr->value);
173 
174   doc = VerifyWithOptions(R"EOF(
175       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
176                 package="android" />)EOF",
177                           options);
178   ASSERT_NE(nullptr, doc);
179 
180   el = doc->root.get();
181   ASSERT_NE(nullptr, el);
182   el = el->FindChild({}, "uses-sdk");
183   ASSERT_NE(nullptr, el);
184   attr = el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion");
185   ASSERT_NE(nullptr, attr);
186   EXPECT_EQ("8", attr->value);
187   attr = el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion");
188   ASSERT_NE(nullptr, attr);
189   EXPECT_EQ("22", attr->value);
190 }
191 
192 TEST_F(ManifestFixerTest, UsesSdkMustComeBeforeApplication) {
193   ManifestFixerOptions options = {std::string("8"), std::string("22")};
194   std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
195           <manifest xmlns:android="http://schemas.android.com/apk/res/android"
196                     package="android">
197             <application android:name=".MainApplication" />
198           </manifest>)EOF",
199                                                             options);
200   ASSERT_NE(nullptr, doc);
201 
202   xml::Element* manifest_el = doc->root.get();
203   ASSERT_NE(nullptr, manifest_el);
204   ASSERT_EQ("manifest", manifest_el->name);
205 
206   xml::Element* application_el = manifest_el->FindChild("", "application");
207   ASSERT_NE(nullptr, application_el);
208 
209   xml::Element* uses_sdk_el = manifest_el->FindChild("", "uses-sdk");
210   ASSERT_NE(nullptr, uses_sdk_el);
211 
212   // Check that the uses_sdk_el comes before application_el in the children
213   // vector.
214   // Since there are no namespaces here, these children are direct descendants
215   // of manifest.
216   auto uses_sdk_iter =
217       std::find_if(manifest_el->children.begin(), manifest_el->children.end(),
218                    [&](const std::unique_ptr<xml::Node>& child) {
219                      return child.get() == uses_sdk_el;
220                    });
221 
222   auto application_iter =
223       std::find_if(manifest_el->children.begin(), manifest_el->children.end(),
224                    [&](const std::unique_ptr<xml::Node>& child) {
225                      return child.get() == application_el;
226                    });
227 
228   ASSERT_NE(manifest_el->children.end(), uses_sdk_iter);
229   ASSERT_NE(manifest_el->children.end(), application_iter);
230 
231   // The distance should be positive, meaning uses_sdk_iter comes before
232   // application_iter.
233   EXPECT_GT(std::distance(uses_sdk_iter, application_iter), 0);
234 }
235 
236 TEST_F(ManifestFixerTest, RenameManifestPackageAndFullyQualifyClasses) {
237   ManifestFixerOptions options;
238   options.rename_manifest_package = std::string("com.android");
239 
240   std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
241       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
242                 package="android">
243         <application android:name=".MainApplication" text="hello">
244           <activity android:name=".activity.Start" />
245           <receiver android:name="com.google.android.Receiver" />
246         </application>
247       </manifest>)EOF",
248                                                             options);
249   ASSERT_NE(nullptr, doc);
250 
251   xml::Element* manifestEl = doc->root.get();
252   ASSERT_NE(nullptr, manifestEl);
253 
254   xml::Attribute* attr = nullptr;
255 
256   attr = manifestEl->FindAttribute({}, "package");
257   ASSERT_NE(nullptr, attr);
258   EXPECT_EQ(std::string("com.android"), attr->value);
259 
260   xml::Element* applicationEl = manifestEl->FindChild({}, "application");
261   ASSERT_NE(nullptr, applicationEl);
262 
263   attr = applicationEl->FindAttribute(xml::kSchemaAndroid, "name");
264   ASSERT_NE(nullptr, attr);
265   EXPECT_EQ(std::string("android.MainApplication"), attr->value);
266 
267   attr = applicationEl->FindAttribute({}, "text");
268   ASSERT_NE(nullptr, attr);
269   EXPECT_EQ(std::string("hello"), attr->value);
270 
271   xml::Element* el;
272   el = applicationEl->FindChild({}, "activity");
273   ASSERT_NE(nullptr, el);
274 
275   attr = el->FindAttribute(xml::kSchemaAndroid, "name");
276   ASSERT_NE(nullptr, el);
277   EXPECT_EQ(std::string("android.activity.Start"), attr->value);
278 
279   el = applicationEl->FindChild({}, "receiver");
280   ASSERT_NE(nullptr, el);
281 
282   attr = el->FindAttribute(xml::kSchemaAndroid, "name");
283   ASSERT_NE(nullptr, el);
284   EXPECT_EQ(std::string("com.google.android.Receiver"), attr->value);
285 }
286 
287 TEST_F(ManifestFixerTest,
288        RenameManifestInstrumentationPackageAndFullyQualifyTarget) {
289   ManifestFixerOptions options;
290   options.rename_instrumentation_target_package = std::string("com.android");
291 
292   std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
293       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
294                 package="android">
295         <instrumentation android:name=".TestRunner" android:targetPackage="android" />
296       </manifest>)EOF",
297                                                             options);
298   ASSERT_NE(nullptr, doc);
299 
300   xml::Element* manifest_el = doc->root.get();
301   ASSERT_NE(nullptr, manifest_el);
302 
303   xml::Element* instrumentation_el =
304       manifest_el->FindChild({}, "instrumentation");
305   ASSERT_NE(nullptr, instrumentation_el);
306 
307   xml::Attribute* attr =
308       instrumentation_el->FindAttribute(xml::kSchemaAndroid, "targetPackage");
309   ASSERT_NE(nullptr, attr);
310   EXPECT_EQ(std::string("com.android"), attr->value);
311 }
312 
313 TEST_F(ManifestFixerTest, UseDefaultVersionNameAndCode) {
314   ManifestFixerOptions options;
315   options.version_name_default = std::string("Beta");
316   options.version_code_default = std::string("0x10000000");
317 
318   std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
319       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
320                 package="android" />)EOF",
321                                                             options);
322   ASSERT_NE(nullptr, doc);
323 
324   xml::Element* manifest_el = doc->root.get();
325   ASSERT_NE(nullptr, manifest_el);
326 
327   xml::Attribute* attr =
328       manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
329   ASSERT_NE(nullptr, attr);
330   EXPECT_EQ(std::string("Beta"), attr->value);
331 
332   attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
333   ASSERT_NE(nullptr, attr);
334   EXPECT_EQ(std::string("0x10000000"), attr->value);
335 }
336 
337 TEST_F(ManifestFixerTest, EnsureManifestAttributesAreTyped) {
338   EXPECT_EQ(nullptr,
339             Verify("<manifest package=\"android\" coreApp=\"hello\" />"));
340   EXPECT_EQ(nullptr,
341             Verify("<manifest package=\"android\" coreApp=\"1dp\" />"));
342 
343   std::unique_ptr<xml::XmlResource> doc =
344       Verify("<manifest package=\"android\" coreApp=\"true\" />");
345   ASSERT_NE(nullptr, doc);
346 
347   xml::Element* el = doc->root.get();
348   ASSERT_NE(nullptr, el);
349 
350   EXPECT_EQ("manifest", el->name);
351 
352   xml::Attribute* attr = el->FindAttribute("", "coreApp");
353   ASSERT_NE(nullptr, attr);
354 
355   EXPECT_NE(nullptr, attr->compiled_value);
356   EXPECT_NE(nullptr, ValueCast<BinaryPrimitive>(attr->compiled_value.get()));
357 }
358 
TEST_F(ManifestFixerTest,UsesFeatureMustHaveNameOrGlEsVersion)359 TEST_F(ManifestFixerTest, UsesFeatureMustHaveNameOrGlEsVersion) {
360   std::string input = R"EOF(
361         <manifest xmlns:android="http://schemas.android.com/apk/res/android"
362                   package="android">
363           <uses-feature android:name="feature" />
364           <uses-feature android:glEsVersion="1" />
365           <feature-group />
366           <feature-group>
367             <uses-feature android:name="feature_in_group" />
368             <uses-feature android:glEsVersion="2" />
369           </feature-group>
370         </manifest>)EOF";
371   EXPECT_NE(nullptr, Verify(input));
372 
373   input = R"EOF(
374         <manifest xmlns:android="http://schemas.android.com/apk/res/android"
375                   package="android">
376           <uses-feature android:name="feature" android:glEsVersion="1" />
377         </manifest>)EOF";
378   EXPECT_EQ(nullptr, Verify(input));
379 
380   input = R"EOF(
381         <manifest xmlns:android="http://schemas.android.com/apk/res/android"
382                   package="android">
383           <uses-feature />
384         </manifest>)EOF";
385   EXPECT_EQ(nullptr, Verify(input));
386 
387   input = R"EOF(
388         <manifest xmlns:android="http://schemas.android.com/apk/res/android"
389                   package="android">
390           <feature-group>
391             <uses-feature android:name="feature" android:glEsVersion="1" />
392           </feature-group>
393         </manifest>)EOF";
394   EXPECT_EQ(nullptr, Verify(input));
395 
396   input = R"EOF(
397         <manifest xmlns:android="http://schemas.android.com/apk/res/android"
398                   package="android">
399           <feature-group>
400             <uses-feature />
401           </feature-group>
402         </manifest>)EOF";
403   EXPECT_EQ(nullptr, Verify(input));
404 }
405 
406 TEST_F(ManifestFixerTest, IgnoreNamespacedElements) {
407   std::string input = R"EOF(
408       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
409                 package="android">
410         <special:tag whoo="true" xmlns:special="http://google.com" />
411       </manifest>)EOF";
412   EXPECT_NE(nullptr, Verify(input));
413 }
414 
415 TEST_F(ManifestFixerTest, DoNotIgnoreNonNamespacedElements) {
416   std::string input = R"EOF(
417       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
418                 package="android">
419         <tag whoo="true" />
420       </manifest>)EOF";
421   EXPECT_EQ(nullptr, Verify(input));
422 }
423 
424 TEST_F(ManifestFixerTest, SupportKeySets) {
425   std::string input = R"(
426       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
427           package="android">
428         <key-sets>
429           <key-set android:name="old-set">
430             <public-key android:name="old-key" android:value="some+old+key" />
431           </key-set>
432           <key-set android:name="new-set">
433             <public-key android:name="new-key" android:value="some+new+key" />
434           </key-set>
435           <upgrade-key-set android:name="old-set" />
436           <upgrade-key-set android:name="new-set" />
437         </key-sets>
438       </manifest>)";
439   EXPECT_THAT(Verify(input), NotNull());
440 }
441 
442 }  // namespace aapt
443