blob: 7aa0dbbafab3a20cfa68e070970492cfc0490ba2 [file] [log] [blame]
Adam Lesinskif90f2f8d2014-06-06 14:27:00 -07001/*
2 * Copyright (C) 2014 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
Ryan Mitchell8a891d82019-07-01 09:48:23 -070017#include "android-base/file.h"
18#include "androidfw/ApkAssets.h"
19#include "androidfw/AssetManager2.h"
Adam Lesinski4c67a472016-11-10 16:43:59 -080020#include "androidfw/ResourceTypes.h"
Adam Lesinskif90f2f8d2014-06-06 14:27:00 -070021
Adam Lesinski4c67a472016-11-10 16:43:59 -080022#include "utils/String16.h"
23#include "utils/String8.h"
24
Adam Lesinskif90f2f8d2014-06-06 14:27:00 -070025#include "TestHelpers.h"
Ryan Mitchell8a891d82019-07-01 09:48:23 -070026#include "data/overlay/R.h"
27#include "data/overlayable/R.h"
28#include "data/system/R.h"
Adam Lesinskif90f2f8d2014-06-06 14:27:00 -070029
Ryan Mitchell8a891d82019-07-01 09:48:23 -070030namespace overlay = com::android::overlay;
31namespace overlayable = com::android::overlayable;
Adam Lesinskif90f2f8d2014-06-06 14:27:00 -070032
Adam Lesinski4c67a472016-11-10 16:43:59 -080033namespace android {
Adam Lesinskif90f2f8d2014-06-06 14:27:00 -070034
Ryan Mitchell8a891d82019-07-01 09:48:23 -070035namespace {
36
Adam Lesinskif90f2f8d2014-06-06 14:27:00 -070037class IdmapTest : public ::testing::Test {
Adam Lesinski4c67a472016-11-10 16:43:59 -080038 protected:
39 void SetUp() override {
Ryan Mitchell8a891d82019-07-01 09:48:23 -070040 // Move to the test data directory so the idmap can locate the overlay APK.
Ryan Mitchella9093052020-03-26 17:15:01 -070041 original_path = base::GetExecutableDirectory();
Ryan Mitchell8a891d82019-07-01 09:48:23 -070042 chdir(GetTestDataPath().c_str());
Adam Lesinskif90f2f8d2014-06-06 14:27:00 -070043
Ryan Mitchell8a891d82019-07-01 09:48:23 -070044 system_assets_ = ApkAssets::Load("system/system.apk");
45 ASSERT_NE(nullptr, system_assets_);
Adam Lesinskif90f2f8d2014-06-06 14:27:00 -070046
Ryan Mitchell8a891d82019-07-01 09:48:23 -070047 overlay_assets_ = ApkAssets::LoadOverlay("overlay/overlay.idmap");
48 ASSERT_NE(nullptr, overlay_assets_);
49
50 overlayable_assets_ = ApkAssets::Load("overlayable/overlayable.apk");
51 ASSERT_NE(nullptr, overlayable_assets_);
Ryan Mitchella9093052020-03-26 17:15:01 -070052 }
53
54 void TearDown() override {
Ryan Mitchell8a891d82019-07-01 09:48:23 -070055 chdir(original_path.c_str());
Adam Lesinski4c67a472016-11-10 16:43:59 -080056 }
57
Ryan Mitchell8a891d82019-07-01 09:48:23 -070058 protected:
Ryan Mitchella9093052020-03-26 17:15:01 -070059 std::string original_path;
Ryan Mitchell8a891d82019-07-01 09:48:23 -070060 std::unique_ptr<const ApkAssets> system_assets_;
61 std::unique_ptr<const ApkAssets> overlay_assets_;
62 std::unique_ptr<const ApkAssets> overlayable_assets_;
Adam Lesinskif90f2f8d2014-06-06 14:27:00 -070063};
64
Ryan Mitchell55ef6162020-11-13 23:55:20 +000065std::string GetStringFromApkAssets(const AssetManager2& asset_manager, const Res_value& value,
66 ApkAssetsCookie cookie) {
Ryan Mitchell8a891d82019-07-01 09:48:23 -070067 auto assets = asset_manager.GetApkAssets();
Ryan Mitchell55ef6162020-11-13 23:55:20 +000068 const ResStringPool* string_pool = assets[cookie]->GetLoadedArsc()->GetStringPool();
Ryan Mitchell8a891d82019-07-01 09:48:23 -070069 return GetStringFromPool(string_pool, value.data);
70}
71
Adam Lesinskif90f2f8d2014-06-06 14:27:00 -070072}
73
Adam Lesinskied69ce82017-03-20 10:55:01 -070074TEST_F(IdmapTest, OverlayOverridesResourceValue) {
Ryan Mitchell8a891d82019-07-01 09:48:23 -070075 AssetManager2 asset_manager;
76 asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
77 overlay_assets_.get()});
Ryan Mitchell55ef6162020-11-13 23:55:20 +000078 Res_value val;
79 ResTable_config config;
80 uint32_t flags;
81 ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::string::overlayable5,
82 false /* may_be_bag */,
83 0 /* density_override */, &val, &config,
84 &flags);
85 ASSERT_EQ(cookie, 2U);
86 ASSERT_EQ(val.dataType, Res_value::TYPE_STRING);
87 ASSERT_EQ(GetStringFromApkAssets(asset_manager, val, cookie), "Overlay One");
Ryan Mitchell8a891d82019-07-01 09:48:23 -070088}
Adam Lesinskif90f2f8d2014-06-06 14:27:00 -070089
Ryan Mitchell8a891d82019-07-01 09:48:23 -070090TEST_F(IdmapTest, OverlayOverridesResourceValueUsingDifferentPackage) {
91 AssetManager2 asset_manager;
92 asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
93 overlay_assets_.get()});
Ryan Mitchell55ef6162020-11-13 23:55:20 +000094 Res_value val;
95 ResTable_config config;
96 uint32_t flags;
97 ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::string::overlayable10,
98 false /* may_be_bag */,
99 0 /* density_override */, &val, &config,
100 &flags);
101 ASSERT_EQ(cookie, 0U);
102 ASSERT_EQ(val.dataType, Res_value::TYPE_STRING);
103 ASSERT_EQ(GetStringFromApkAssets(asset_manager, val, cookie), "yes");
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700104}
Adam Lesinskif90f2f8d2014-06-06 14:27:00 -0700105
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700106TEST_F(IdmapTest, OverlayOverridesResourceValueUsingInternalResource) {
107 AssetManager2 asset_manager;
108 asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
109 overlay_assets_.get()});
Ryan Mitchell55ef6162020-11-13 23:55:20 +0000110 Res_value val;
111 ResTable_config config;
112 uint32_t flags;
113 ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::string::overlayable8,
114 false /* may_be_bag */,
115 0 /* density_override */, &val, &config,
116 &flags);
117 ASSERT_EQ(cookie, 2U);
118 ASSERT_EQ(val.dataType, Res_value::TYPE_REFERENCE);
119 ASSERT_EQ(val.data, (overlay::R::string::internal & 0x00ffffff) | (0x02 << 24));
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700120}
Adam Lesinskif90f2f8d2014-06-06 14:27:00 -0700121
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700122TEST_F(IdmapTest, OverlayOverridesResourceValueUsingInlineInteger) {
123 AssetManager2 asset_manager;
124 asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
125 overlay_assets_.get()});
Ryan Mitchell55ef6162020-11-13 23:55:20 +0000126 Res_value val;
127 ResTable_config config;
128 uint32_t flags;
129 ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::integer::config_integer,
130 false /* may_be_bag */,
131 0 /* density_override */, &val, &config,
132 &flags);
133 ASSERT_EQ(cookie, 2U);
134 ASSERT_EQ(val.dataType, Res_value::TYPE_INT_DEC);
135 ASSERT_EQ(val.data, 42);
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700136}
Adam Lesinskif90f2f8d2014-06-06 14:27:00 -0700137
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700138TEST_F(IdmapTest, OverlayOverridesResourceValueUsingInlineString) {
139 AssetManager2 asset_manager;
140 asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
141 overlay_assets_.get()});
Ryan Mitchell55ef6162020-11-13 23:55:20 +0000142 Res_value val;
143 ResTable_config config;
144 uint32_t flags;
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700145
Ryan Mitchell55ef6162020-11-13 23:55:20 +0000146 ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::string::overlayable11,
147 false /* may_be_bag */,
148 0 /* density_override */, &val, &config,
149 &flags);
150 ASSERT_EQ(cookie, 2U);
151 ASSERT_EQ(val.dataType, Res_value::TYPE_STRING);
152 ASSERT_EQ(GetStringFromApkAssets(asset_manager, val, cookie), "Hardcoded string");
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700153}
154
155TEST_F(IdmapTest, OverlayOverridesResourceValueUsingOverlayingResource) {
156 AssetManager2 asset_manager;
157 asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
158 overlay_assets_.get()});
Ryan Mitchell55ef6162020-11-13 23:55:20 +0000159 Res_value val;
160 ResTable_config config;
161 uint32_t flags;
162 ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::string::overlayable9,
163 false /* may_be_bag */,
164 0 /* density_override */, &val, &config,
165 &flags);
166 ASSERT_EQ(cookie, 2U);
167 ASSERT_EQ(val.dataType, Res_value::TYPE_REFERENCE);
168 ASSERT_EQ(val.data, overlayable::R::string::overlayable7);
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700169}
170
171TEST_F(IdmapTest, OverlayOverridesXmlParser) {
172 AssetManager2 asset_manager;
173 asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
174 overlay_assets_.get()});
Ryan Mitchell55ef6162020-11-13 23:55:20 +0000175 Res_value val;
176 ResTable_config config;
177 uint32_t flags;
178 ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::layout::hello_view,
179 false /* may_be_bag */,
180 0 /* density_override */, &val, &config,
181 &flags);
182 ASSERT_EQ(cookie, 2U);
183 ASSERT_EQ(val.dataType, Res_value::TYPE_STRING);
184 ASSERT_EQ(GetStringFromApkAssets(asset_manager, val, cookie), "res/layout/hello_view.xml");
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700185
Ryan Mitchell55ef6162020-11-13 23:55:20 +0000186 auto asset = asset_manager.OpenNonAsset("res/layout/hello_view.xml", cookie,
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700187 Asset::ACCESS_RANDOM);
Ryan Mitchell55ef6162020-11-13 23:55:20 +0000188 auto dynamic_ref_table = asset_manager.GetDynamicRefTableForCookie(cookie);
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700189 auto xml_tree = util::make_unique<ResXMLTree>(std::move(dynamic_ref_table));
190 status_t err = xml_tree->setTo(asset->getBuffer(true), asset->getLength(), false);
191 ASSERT_EQ(err, NO_ERROR);
192
193 while (xml_tree->next() != ResXMLParser::START_TAG) { }
194
195 // The resource id of @id/hello_view should be rewritten to the resource id/hello_view within the
196 // target.
197 ASSERT_EQ(xml_tree->getAttributeNameResID(0), 0x010100d0 /* android:attr/id */);
198 ASSERT_EQ(xml_tree->getAttributeDataType(0), Res_value::TYPE_REFERENCE);
199 ASSERT_EQ(xml_tree->getAttributeData(0), overlayable::R::id::hello_view);
200
201 // The resource id of @android:string/yes should not be rewritten even though it overlays
202 // string/overlayable10 in the target.
203 ASSERT_EQ(xml_tree->getAttributeNameResID(1), 0x0101014f /* android:attr/text */);
204 ASSERT_EQ(xml_tree->getAttributeDataType(1), Res_value::TYPE_REFERENCE);
205 ASSERT_EQ(xml_tree->getAttributeData(1), 0x01040013 /* android:string/yes */);
206
207 // The resource id of the attribute within the overlay should be rewritten to the resource id of
208 // the attribute in the target.
209 ASSERT_EQ(xml_tree->getAttributeNameResID(2), overlayable::R::attr::max_lines);
210 ASSERT_EQ(xml_tree->getAttributeDataType(2), Res_value::TYPE_INT_DEC);
211 ASSERT_EQ(xml_tree->getAttributeData(2), 4);
Adam Lesinskif90f2f8d2014-06-06 14:27:00 -0700212}
213
Adam Lesinskied69ce82017-03-20 10:55:01 -0700214TEST_F(IdmapTest, OverlaidResourceHasSameName) {
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700215 AssetManager2 asset_manager;
216 asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
217 overlay_assets_.get()});
Adam Lesinskif90f2f8d2014-06-06 14:27:00 -0700218
Ryan Mitchell55ef6162020-11-13 23:55:20 +0000219 AssetManager2::ResourceName name;
220 ASSERT_TRUE(asset_manager.GetResourceName(overlayable::R::string::overlayable9, &name));
221 ASSERT_EQ(std::string(name.package), "com.android.overlayable");
222 ASSERT_EQ(String16(name.type16), u"string");
223 ASSERT_EQ(std::string(name.entry), "overlayable9");
Adam Lesinskied69ce82017-03-20 10:55:01 -0700224}
225
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700226TEST_F(IdmapTest, OverlayLoaderInterop) {
Ryan Mitchell55ef6162020-11-13 23:55:20 +0000227 std::string contents;
Ryan Mitchella9093052020-03-26 17:15:01 -0700228 auto loader_assets = ApkAssets::LoadTable("loader/resources.arsc", PROPERTY_LOADER);
Ryan Mitchell55ef6162020-11-13 23:55:20 +0000229
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700230 AssetManager2 asset_manager;
231 asset_manager.SetApkAssets({overlayable_assets_.get(), loader_assets.get(),
232 overlay_assets_.get()});
Adam Lesinskied69ce82017-03-20 10:55:01 -0700233
Ryan Mitchell55ef6162020-11-13 23:55:20 +0000234 Res_value val;
235 ResTable_config config;
236 uint32_t flags;
237 ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::string::overlayable11,
238 false /* may_be_bag */,
239 0 /* density_override */, &val, &config,
240 &flags);
241 std::cout << asset_manager.GetLastResourceResolution();
242 ASSERT_EQ(cookie, 1U);
243 ASSERT_EQ(val.dataType, Res_value::TYPE_STRING);
244 ASSERT_EQ(GetStringFromApkAssets(asset_manager, val, cookie), "loader");
Adam Lesinskif90f2f8d2014-06-06 14:27:00 -0700245}
246
Ryan Mitchella9093052020-03-26 17:15:01 -0700247TEST_F(IdmapTest, OverlayAssetsIsUpToDate) {
248 std::string idmap_contents;
249 ASSERT_TRUE(base::ReadFileToString("overlay/overlay.idmap", &idmap_contents));
250
251 TemporaryFile temp_file;
252 ASSERT_TRUE(base::WriteStringToFile(idmap_contents, temp_file.path));
253
254 auto apk_assets = ApkAssets::LoadOverlay(temp_file.path);
255 ASSERT_NE(nullptr, apk_assets);
256 ASSERT_TRUE(apk_assets->IsUpToDate());
257
258 unlink(temp_file.path);
259 ASSERT_FALSE(apk_assets->IsUpToDate());
260 sleep(2);
261
262 base::WriteStringToFile("hello", temp_file.path);
263 sleep(2);
264
265 ASSERT_FALSE(apk_assets->IsUpToDate());
266}
267
Adam Lesinski4c67a472016-11-10 16:43:59 -0800268} // namespace