Home | History | Annotate | Download | only in tests
      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:
     38   void SetUp() override {
     39     system_assets_ = ApkAssets::Load(GetTestDataPath() + "/system/system.apk", true /*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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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