• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 "androidfw/AssetManager2.h"
18 
19 #include "android-base/logging.h"
20 
21 #include "TestHelpers.h"
22 #include "androidfw/ResourceUtils.h"
23 #include "data/lib_one/R.h"
24 #include "data/lib_two/R.h"
25 #include "data/libclient/R.h"
26 #include "data/styles/R.h"
27 #include "data/system/R.h"
28 
29 namespace app = com::android::app;
30 namespace lib_one = com::android::lib_one;
31 namespace lib_two = com::android::lib_two;
32 namespace libclient = com::android::libclient;
33 
34 namespace android {
35 
36 class ThemeTest : public ::testing::Test {
37  public:
SetUp()38   void SetUp() override {
39     system_assets_ = ApkAssets::Load(GetTestDataPath() + "/system/system.apk", PROPERTY_SYSTEM);
40     ASSERT_NE(nullptr, system_assets_);
41 
42     style_assets_ = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk");
43     ASSERT_NE(nullptr, style_assets_);
44 
45     libclient_assets_ = ApkAssets::Load(GetTestDataPath() + "/libclient/libclient.apk");
46     ASSERT_NE(nullptr, libclient_assets_);
47 
48     lib_one_assets_ = ApkAssets::Load(GetTestDataPath() + "/lib_one/lib_one.apk");
49     ASSERT_NE(nullptr, lib_one_assets_);
50 
51     lib_two_assets_ = ApkAssets::Load(GetTestDataPath() + "/lib_two/lib_two.apk");
52     ASSERT_NE(nullptr, lib_two_assets_);
53   }
54 
55  protected:
56   std::unique_ptr<const ApkAssets> system_assets_;
57   std::unique_ptr<const ApkAssets> style_assets_;
58   std::unique_ptr<const ApkAssets> libclient_assets_;
59   std::unique_ptr<const ApkAssets> lib_one_assets_;
60   std::unique_ptr<const ApkAssets> lib_two_assets_;
61 };
62 
TEST_F(ThemeTest,EmptyTheme)63 TEST_F(ThemeTest, EmptyTheme) {
64   AssetManager2 assetmanager;
65   assetmanager.SetApkAssets({style_assets_.get()});
66 
67   std::unique_ptr<Theme> theme = assetmanager.NewTheme();
68   EXPECT_EQ(0u, theme->GetChangingConfigurations());
69   EXPECT_EQ(&assetmanager, theme->GetAssetManager());
70 
71   Res_value value;
72   uint32_t flags;
73   EXPECT_EQ(kInvalidCookie, theme->GetAttribute(app::R::attr::attr_one, &value, &flags));
74 }
75 
TEST_F(ThemeTest,SingleThemeNoParent)76 TEST_F(ThemeTest, SingleThemeNoParent) {
77   AssetManager2 assetmanager;
78   assetmanager.SetApkAssets({style_assets_.get()});
79 
80   std::unique_ptr<Theme> theme = assetmanager.NewTheme();
81   ASSERT_TRUE(theme->ApplyStyle(app::R::style::StyleOne));
82 
83   Res_value value;
84   uint32_t flags;
85   ApkAssetsCookie cookie;
86 
87   cookie = theme->GetAttribute(app::R::attr::attr_one, &value, &flags);
88   ASSERT_NE(kInvalidCookie, cookie);
89   EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType);
90   EXPECT_EQ(1u, value.data);
91   EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags);
92 
93   cookie = theme->GetAttribute(app::R::attr::attr_two, &value, &flags);
94   ASSERT_NE(kInvalidCookie, cookie);
95   EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType);
96   EXPECT_EQ(2u, value.data);
97   EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags);
98 }
99 
TEST_F(ThemeTest,SingleThemeWithParent)100 TEST_F(ThemeTest, SingleThemeWithParent) {
101   AssetManager2 assetmanager;
102   assetmanager.SetApkAssets({style_assets_.get()});
103 
104   std::unique_ptr<Theme> theme = assetmanager.NewTheme();
105   ASSERT_TRUE(theme->ApplyStyle(app::R::style::StyleTwo));
106 
107   Res_value value;
108   uint32_t flags;
109   ApkAssetsCookie cookie;
110 
111   cookie = theme->GetAttribute(app::R::attr::attr_one, &value, &flags);
112   ASSERT_NE(kInvalidCookie, cookie);
113   EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType);
114   EXPECT_EQ(1u, value.data);
115   EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags);
116 
117   cookie = theme->GetAttribute(app::R::attr::attr_two, &value, &flags);
118   ASSERT_NE(kInvalidCookie, cookie);
119   EXPECT_EQ(Res_value::TYPE_STRING, value.dataType);
120   EXPECT_EQ(0, cookie);
121   EXPECT_EQ(std::string("string"),
122             GetStringFromPool(assetmanager.GetStringPoolForCookie(0), value.data));
123   EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags);
124 
125   // This attribute should point to an attr_indirect, so the result should be 3.
126   cookie = theme->GetAttribute(app::R::attr::attr_three, &value, &flags);
127   ASSERT_NE(kInvalidCookie, cookie);
128   EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType);
129   EXPECT_EQ(3u, value.data);
130   EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags);
131 }
132 
TEST_F(ThemeTest,TryToUseBadResourceId)133 TEST_F(ThemeTest, TryToUseBadResourceId) {
134   AssetManager2 assetmanager;
135   assetmanager.SetApkAssets({style_assets_.get()});
136 
137   std::unique_ptr<Theme> theme = assetmanager.NewTheme();
138   ASSERT_TRUE(theme->ApplyStyle(app::R::style::StyleTwo));
139 
140   Res_value value;
141   uint32_t flags;
142   ASSERT_EQ(kInvalidCookie, theme->GetAttribute(0x7f000001, &value, &flags));
143 }
144 
TEST_F(ThemeTest,MultipleThemesOverlaidNotForce)145 TEST_F(ThemeTest, MultipleThemesOverlaidNotForce) {
146   AssetManager2 assetmanager;
147   assetmanager.SetApkAssets({style_assets_.get()});
148 
149   std::unique_ptr<Theme> theme = assetmanager.NewTheme();
150   ASSERT_TRUE(theme->ApplyStyle(app::R::style::StyleTwo));
151   ASSERT_TRUE(theme->ApplyStyle(app::R::style::StyleThree));
152 
153   Res_value value;
154   uint32_t flags;
155   ApkAssetsCookie cookie;
156 
157   // attr_one is still here from the base.
158   cookie = theme->GetAttribute(app::R::attr::attr_one, &value, &flags);
159   ASSERT_NE(kInvalidCookie, cookie);
160   EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType);
161   EXPECT_EQ(1u, value.data);
162   EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags);
163 
164   // check for the new attr_six
165   cookie = theme->GetAttribute(app::R::attr::attr_six, &value, &flags);
166   ASSERT_NE(kInvalidCookie, cookie);
167   EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType);
168   EXPECT_EQ(6u, value.data);
169   EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags);
170 
171   // check for the old attr_five (force=true was not used).
172   cookie = theme->GetAttribute(app::R::attr::attr_five, &value, &flags);
173   ASSERT_NE(kInvalidCookie, cookie);
174   EXPECT_EQ(Res_value::TYPE_REFERENCE, value.dataType);
175   EXPECT_EQ(app::R::string::string_one, value.data);
176   EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags);
177 }
178 
TEST_F(ThemeTest,MultipleThemesOverlaidForced)179 TEST_F(ThemeTest, MultipleThemesOverlaidForced) {
180   AssetManager2 assetmanager;
181   assetmanager.SetApkAssets({style_assets_.get()});
182 
183   std::unique_ptr<Theme> theme = assetmanager.NewTheme();
184   ASSERT_TRUE(theme->ApplyStyle(app::R::style::StyleTwo));
185   ASSERT_TRUE(theme->ApplyStyle(app::R::style::StyleThree, true /* force */));
186 
187   Res_value value;
188   uint32_t flags;
189   ApkAssetsCookie cookie;
190 
191   // attr_one is still here from the base.
192   cookie = theme->GetAttribute(app::R::attr::attr_one, &value, &flags);
193   ASSERT_NE(kInvalidCookie, cookie);
194   EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType);
195   EXPECT_EQ(1u, value.data);
196   EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags);
197 
198   // check for the new attr_six
199   cookie = theme->GetAttribute(app::R::attr::attr_six, &value, &flags);
200   ASSERT_NE(kInvalidCookie, cookie);
201   EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType);
202   EXPECT_EQ(6u, value.data);
203   EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags);
204 
205   // check for the new attr_five (force=true was used).
206   cookie = theme->GetAttribute(app::R::attr::attr_five, &value, &flags);
207   ASSERT_NE(kInvalidCookie, cookie);
208   EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType);
209   EXPECT_EQ(5u, value.data);
210   EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags);
211 }
212 
TEST_F(ThemeTest,ResolveDynamicAttributesAndReferencesToSharedLibrary)213 TEST_F(ThemeTest, ResolveDynamicAttributesAndReferencesToSharedLibrary) {
214   AssetManager2 assetmanager;
215   assetmanager.SetApkAssets(
216       {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()});
217 
218   std::unique_ptr<Theme> theme = assetmanager.NewTheme();
219   ASSERT_TRUE(theme->ApplyStyle(libclient::R::style::Theme, false /*force*/));
220 
221   Res_value value;
222   uint32_t flags;
223   ApkAssetsCookie cookie;
224 
225   // The attribute should be resolved to the final value.
226   cookie = theme->GetAttribute(libclient::R::attr::foo, &value, &flags);
227   ASSERT_NE(kInvalidCookie, cookie);
228   EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType);
229   EXPECT_EQ(700u, value.data);
230   EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags);
231 
232   // The reference should be resolved to a TYPE_REFERENCE.
233   cookie = theme->GetAttribute(libclient::R::attr::bar, &value, &flags);
234   ASSERT_NE(kInvalidCookie, cookie);
235   EXPECT_EQ(Res_value::TYPE_REFERENCE, value.dataType);
236 
237   // lib_one is assigned package ID 0x03.
238   EXPECT_EQ(3u, get_package_id(value.data));
239   EXPECT_EQ(get_type_id(lib_one::R::string::foo), get_type_id(value.data));
240   EXPECT_EQ(get_entry_id(lib_one::R::string::foo), get_entry_id(value.data));
241 }
242 
TEST_F(ThemeTest,CopyThemeSameAssetManager)243 TEST_F(ThemeTest, CopyThemeSameAssetManager) {
244   AssetManager2 assetmanager;
245   assetmanager.SetApkAssets({style_assets_.get()});
246 
247   std::unique_ptr<Theme> theme_one = assetmanager.NewTheme();
248   ASSERT_TRUE(theme_one->ApplyStyle(app::R::style::StyleOne));
249 
250   Res_value value;
251   uint32_t flags;
252   ApkAssetsCookie cookie;
253 
254   // attr_one is still here from the base.
255   cookie = theme_one->GetAttribute(app::R::attr::attr_one, &value, &flags);
256   ASSERT_NE(kInvalidCookie, cookie);
257   EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType);
258   EXPECT_EQ(1u, value.data);
259   EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags);
260 
261   // attr_six is not here.
262   EXPECT_EQ(kInvalidCookie, theme_one->GetAttribute(app::R::attr::attr_six, &value, &flags));
263 
264   std::unique_ptr<Theme> theme_two = assetmanager.NewTheme();
265   ASSERT_TRUE(theme_two->ApplyStyle(app::R::style::StyleThree));
266 
267   // Copy the theme to theme_one.
268   theme_one->SetTo(*theme_two);
269 
270   // Clear theme_two to make sure we test that there WAS a copy.
271   theme_two->Clear();
272 
273   // attr_one is now not here.
274   EXPECT_EQ(kInvalidCookie, theme_one->GetAttribute(app::R::attr::attr_one, &value, &flags));
275 
276   // attr_six is now here because it was copied.
277   cookie = theme_one->GetAttribute(app::R::attr::attr_six, &value, &flags);
278   ASSERT_NE(kInvalidCookie, cookie);
279   EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType);
280   EXPECT_EQ(6u, value.data);
281   EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags);
282 }
283 
TEST_F(ThemeTest,OnlyCopySameAssetsThemeWhenAssetManagersDiffer)284 TEST_F(ThemeTest, OnlyCopySameAssetsThemeWhenAssetManagersDiffer) {
285   AssetManager2 assetmanager_dst;
286   assetmanager_dst.SetApkAssets({system_assets_.get(), lib_one_assets_.get(), style_assets_.get(),
287                                  libclient_assets_.get()});
288 
289   AssetManager2 assetmanager_src;
290   assetmanager_src.SetApkAssets({system_assets_.get(), lib_two_assets_.get(), lib_one_assets_.get(),
291                                  style_assets_.get()});
292 
293   auto theme_dst = assetmanager_dst.NewTheme();
294   ASSERT_TRUE(theme_dst->ApplyStyle(app::R::style::StyleOne));
295 
296   auto theme_src = assetmanager_src.NewTheme();
297   ASSERT_TRUE(theme_src->ApplyStyle(R::style::Theme_One));
298   ASSERT_TRUE(theme_src->ApplyStyle(app::R::style::StyleTwo));
299   ASSERT_TRUE(theme_src->ApplyStyle(fix_package_id(lib_one::R::style::Theme, 0x03),
300                                     false /*force*/));
301   ASSERT_TRUE(theme_src->ApplyStyle(fix_package_id(lib_two::R::style::Theme, 0x02),
302                                     false /*force*/));
303 
304   theme_dst->SetTo(*theme_src);
305 
306   Res_value value;
307   uint32_t flags;
308 
309   // System resources (present in destination asset manager).
310   EXPECT_EQ(0, theme_dst->GetAttribute(R::attr::foreground, &value, &flags));
311 
312   // The cookie of the style asset is 3 in the source and 2 in the destination.
313   // Check that the cookie has been rewritten to the destination values.
314   EXPECT_EQ(2, theme_dst->GetAttribute(app::R::attr::attr_one, &value, &flags));
315 
316   // The cookie of the lib_one asset is 2 in the source and 1 in the destination.
317   // The package id of the lib_one package is 0x03 in the source and 0x02 in the destination
318   // Check that the cookie and packages have been rewritten to the destination values.
319   EXPECT_EQ(1, theme_dst->GetAttribute(fix_package_id(lib_one::R::attr::attr1, 0x02), &value,
320                                        &flags));
321   EXPECT_EQ(1, theme_dst->GetAttribute(fix_package_id(lib_one::R::attr::attr2, 0x02), &value,
322                                        &flags));
323 
324   // attr2 references an attribute in lib_one. Check that the resolution of the attribute value is
325   // correct after the value of attr2 had its package id rewritten to the destination package id.
326   EXPECT_EQ(700, value.data);
327 }
328 
TEST_F(ThemeTest,CopyNonReferencesWhenPackagesDiffer)329 TEST_F(ThemeTest, CopyNonReferencesWhenPackagesDiffer) {
330   AssetManager2 assetmanager_dst;
331   assetmanager_dst.SetApkAssets({system_assets_.get()});
332 
333   AssetManager2 assetmanager_src;
334   assetmanager_src.SetApkAssets({system_assets_.get(), style_assets_.get()});
335 
336   auto theme_dst = assetmanager_dst.NewTheme();
337   auto theme_src = assetmanager_src.NewTheme();
338   ASSERT_TRUE(theme_src->ApplyStyle(app::R::style::StyleSeven));
339   theme_dst->SetTo(*theme_src);
340 
341   Res_value value;
342   uint32_t flags;
343 
344   // Allow inline resource values to be copied even if the source apk asset is not present in the
345   // destination.
346   EXPECT_EQ(0, theme_dst->GetAttribute(0x0101021b /* android:versionCode */, &value, &flags));
347 
348   // Do not copy strings since the data is an index into the values string pool of the source apk
349   // asset.
350   EXPECT_EQ(-1, theme_dst->GetAttribute(0x01010001 /* android:label */, &value, &flags));
351 
352   // Do not copy values that reference another resource if the resource is not present in the
353   // destination.
354   EXPECT_EQ(-1, theme_dst->GetAttribute(0x01010002 /* android:icon */, &value, &flags));
355   EXPECT_EQ(-1, theme_dst->GetAttribute(0x010100d1 /* android:tag */, &value, &flags));
356 
357   // Allow @empty to and @null to be copied.
358   EXPECT_EQ(0, theme_dst->GetAttribute(0x010100d0 /* android:id */, &value, &flags));
359   EXPECT_EQ(0, theme_dst->GetAttribute(0x01010000 /* android:theme */, &value, &flags));
360 }
361 
362 }  // namespace android
363