blob: b679672ab34e299a28800d5dff315c795f8745fa [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.
41 std::string original_path = base::GetExecutableDirectory();
42 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_);
52 chdir(original_path.c_str());
Adam Lesinski4c67a472016-11-10 16:43:59 -080053 }
54
Ryan Mitchell8a891d82019-07-01 09:48:23 -070055 protected:
56 std::unique_ptr<const ApkAssets> system_assets_;
57 std::unique_ptr<const ApkAssets> overlay_assets_;
58 std::unique_ptr<const ApkAssets> overlayable_assets_;
Adam Lesinskif90f2f8d2014-06-06 14:27:00 -070059};
60
Ryan Mitchell8a891d82019-07-01 09:48:23 -070061std::string GetStringFromApkAssets(const AssetManager2& asset_manager, const Res_value& value,
62 ApkAssetsCookie cookie) {
63 auto assets = asset_manager.GetApkAssets();
64 const ResStringPool* string_pool = assets[cookie]->GetLoadedArsc()->GetStringPool();
65 return GetStringFromPool(string_pool, value.data);
66}
67
Adam Lesinskif90f2f8d2014-06-06 14:27:00 -070068}
69
Adam Lesinskied69ce82017-03-20 10:55:01 -070070TEST_F(IdmapTest, OverlayOverridesResourceValue) {
Ryan Mitchell8a891d82019-07-01 09:48:23 -070071 AssetManager2 asset_manager;
72 asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
73 overlay_assets_.get()});
Adam Lesinski4c67a472016-11-10 16:43:59 -080074 Res_value val;
Ryan Mitchell8a891d82019-07-01 09:48:23 -070075 ResTable_config config;
76 uint32_t flags;
77 ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::string::overlayable5,
78 false /* may_be_bag */,
79 0 /* density_override */, &val, &config,
80 &flags);
81 ASSERT_EQ(cookie, 2U);
82 ASSERT_EQ(val.dataType, Res_value::TYPE_STRING);
83 ASSERT_EQ(GetStringFromApkAssets(asset_manager, val, cookie), "Overlay One");
84}
Adam Lesinskif90f2f8d2014-06-06 14:27:00 -070085
Ryan Mitchell8a891d82019-07-01 09:48:23 -070086TEST_F(IdmapTest, OverlayOverridesResourceValueUsingDifferentPackage) {
87 AssetManager2 asset_manager;
88 asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
89 overlay_assets_.get()});
90 Res_value val;
91 ResTable_config config;
92 uint32_t flags;
93 ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::string::overlayable10,
94 false /* may_be_bag */,
95 0 /* density_override */, &val, &config,
96 &flags);
97 ASSERT_EQ(cookie, 0U);
98 ASSERT_EQ(val.dataType, Res_value::TYPE_STRING);
99 ASSERT_EQ(GetStringFromApkAssets(asset_manager, val, cookie), "yes");
100}
Adam Lesinskif90f2f8d2014-06-06 14:27:00 -0700101
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700102TEST_F(IdmapTest, OverlayOverridesResourceValueUsingInternalResource) {
103 AssetManager2 asset_manager;
104 asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
105 overlay_assets_.get()});
106 Res_value val;
107 ResTable_config config;
108 uint32_t flags;
109 ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::string::overlayable8,
110 false /* may_be_bag */,
111 0 /* density_override */, &val, &config,
112 &flags);
113 ASSERT_EQ(cookie, 2U);
114 ASSERT_EQ(val.dataType, Res_value::TYPE_REFERENCE);
115 ASSERT_EQ(val.data, (overlay::R::string::internal & 0x00ffffff) | (0x02 << 24));
116}
Adam Lesinskif90f2f8d2014-06-06 14:27:00 -0700117
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700118TEST_F(IdmapTest, OverlayOverridesResourceValueUsingInlineInteger) {
119 AssetManager2 asset_manager;
120 asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
121 overlay_assets_.get()});
122 Res_value val;
123 ResTable_config config;
124 uint32_t flags;
125 ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::integer::config_integer,
126 false /* may_be_bag */,
127 0 /* density_override */, &val, &config,
128 &flags);
129 ASSERT_EQ(cookie, 2U);
130 ASSERT_EQ(val.dataType, Res_value::TYPE_INT_DEC);
131 ASSERT_EQ(val.data, 42);
132}
Adam Lesinskif90f2f8d2014-06-06 14:27:00 -0700133
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700134TEST_F(IdmapTest, OverlayOverridesResourceValueUsingInlineString) {
135 AssetManager2 asset_manager;
136 asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
137 overlay_assets_.get()});
138 Res_value val;
139 ResTable_config config;
140 uint32_t flags;
141
142 ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::string::overlayable11,
143 false /* may_be_bag */,
144 0 /* density_override */, &val, &config,
145 &flags);
146 ASSERT_EQ(cookie, 2U);
147 ASSERT_EQ(val.dataType, Res_value::TYPE_STRING);
148 ASSERT_EQ(GetStringFromApkAssets(asset_manager, val, cookie), "Hardcoded string");
149}
150
151TEST_F(IdmapTest, OverlayOverridesResourceValueUsingOverlayingResource) {
152 AssetManager2 asset_manager;
153 asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
154 overlay_assets_.get()});
155 Res_value val;
156 ResTable_config config;
157 uint32_t flags;
158 ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::string::overlayable9,
159 false /* may_be_bag */,
160 0 /* density_override */, &val, &config,
161 &flags);
162 ASSERT_EQ(cookie, 2U);
163 ASSERT_EQ(val.dataType, Res_value::TYPE_REFERENCE);
164 ASSERT_EQ(val.data, overlayable::R::string::overlayable7);
165}
166
167TEST_F(IdmapTest, OverlayOverridesXmlParser) {
168 AssetManager2 asset_manager;
169 asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
170 overlay_assets_.get()});
171 Res_value val;
172 ResTable_config config;
173 uint32_t flags;
174 ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::layout::hello_view,
175 false /* may_be_bag */,
176 0 /* density_override */, &val, &config,
177 &flags);
178 ASSERT_EQ(cookie, 2U);
179 ASSERT_EQ(val.dataType, Res_value::TYPE_STRING);
180 ASSERT_EQ(GetStringFromApkAssets(asset_manager, val, cookie), "res/layout/hello_view.xml");
181
182 auto asset = asset_manager.OpenNonAsset("res/layout/hello_view.xml", cookie,
183 Asset::ACCESS_RANDOM);
184 auto dynamic_ref_table = asset_manager.GetDynamicRefTableForCookie(cookie);
185 auto xml_tree = util::make_unique<ResXMLTree>(std::move(dynamic_ref_table));
186 status_t err = xml_tree->setTo(asset->getBuffer(true), asset->getLength(), false);
187 ASSERT_EQ(err, NO_ERROR);
188
189 while (xml_tree->next() != ResXMLParser::START_TAG) { }
190
191 // The resource id of @id/hello_view should be rewritten to the resource id/hello_view within the
192 // target.
193 ASSERT_EQ(xml_tree->getAttributeNameResID(0), 0x010100d0 /* android:attr/id */);
194 ASSERT_EQ(xml_tree->getAttributeDataType(0), Res_value::TYPE_REFERENCE);
195 ASSERT_EQ(xml_tree->getAttributeData(0), overlayable::R::id::hello_view);
196
197 // The resource id of @android:string/yes should not be rewritten even though it overlays
198 // string/overlayable10 in the target.
199 ASSERT_EQ(xml_tree->getAttributeNameResID(1), 0x0101014f /* android:attr/text */);
200 ASSERT_EQ(xml_tree->getAttributeDataType(1), Res_value::TYPE_REFERENCE);
201 ASSERT_EQ(xml_tree->getAttributeData(1), 0x01040013 /* android:string/yes */);
202
203 // The resource id of the attribute within the overlay should be rewritten to the resource id of
204 // the attribute in the target.
205 ASSERT_EQ(xml_tree->getAttributeNameResID(2), overlayable::R::attr::max_lines);
206 ASSERT_EQ(xml_tree->getAttributeDataType(2), Res_value::TYPE_INT_DEC);
207 ASSERT_EQ(xml_tree->getAttributeData(2), 4);
Adam Lesinskif90f2f8d2014-06-06 14:27:00 -0700208}
209
Adam Lesinskied69ce82017-03-20 10:55:01 -0700210TEST_F(IdmapTest, OverlaidResourceHasSameName) {
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700211 AssetManager2 asset_manager;
212 asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(),
213 overlay_assets_.get()});
Adam Lesinskif90f2f8d2014-06-06 14:27:00 -0700214
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700215 AssetManager2::ResourceName name;
216 ASSERT_TRUE(asset_manager.GetResourceName(overlayable::R::string::overlayable9, &name));
217 ASSERT_EQ(std::string(name.package), "com.android.overlayable");
218 ASSERT_EQ(String16(name.type16), u"string");
219 ASSERT_EQ(std::string(name.entry), "overlayable9");
Adam Lesinskied69ce82017-03-20 10:55:01 -0700220}
221
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700222TEST_F(IdmapTest, OverlayLoaderInterop) {
223 std::string contents;
224 auto loader_assets = ApkAssets::LoadArsc(GetTestDataPath() + "/loader/resources.arsc",
225 /* for_loader */ true);
Adam Lesinskied69ce82017-03-20 10:55:01 -0700226
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700227 AssetManager2 asset_manager;
228 asset_manager.SetApkAssets({overlayable_assets_.get(), loader_assets.get(),
229 overlay_assets_.get()});
Adam Lesinskied69ce82017-03-20 10:55:01 -0700230
231 Res_value val;
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700232 ResTable_config config;
233 uint32_t flags;
234 ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::string::overlayable11,
235 false /* may_be_bag */,
236 0 /* density_override */, &val, &config,
237 &flags);
238 std::cout << asset_manager.GetLastResourceResolution();
239 ASSERT_EQ(cookie, 1U);
240 ASSERT_EQ(val.dataType, Res_value::TYPE_STRING);
241 ASSERT_EQ(GetStringFromApkAssets(asset_manager, val, cookie), "loader");
Adam Lesinskif90f2f8d2014-06-06 14:27:00 -0700242}
243
Adam Lesinski4c67a472016-11-10 16:43:59 -0800244} // namespace