blob: de039f440e33f1d73c1ed3e1125dbd8bad3309e1 [file] [log] [blame]
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -07001/*
2 * Copyright (C) 2018 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 <cstdio> // fclose
18#include <fstream>
19#include <memory>
20#include <sstream>
21#include <string>
22#include <utility>
23#include <vector>
24
Winson62ac8b52019-12-04 08:36:48 -080025#include "R.h"
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -070026#include "TestHelpers.h"
Winson62ac8b52019-12-04 08:36:48 -080027#include "androidfw/ResourceTypes.h"
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -070028#include "gmock/gmock.h"
29#include "gtest/gtest.h"
Mårten Kongstadd7e8a532019-10-11 08:32:04 +020030#include "idmap2/LogInfo.h"
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -070031#include "idmap2/ResourceMapping.h"
32
Ryan Mitchelle753ffe2019-09-23 09:47:02 -070033using android::Res_value;
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -070034using android::idmap2::utils::ExtractOverlayManifestInfo;
35
Winson62ac8b52019-12-04 08:36:48 -080036using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
37
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -070038namespace android::idmap2 {
39
40#define ASSERT_RESULT(r) \
41 do { \
42 auto result = r; \
43 ASSERT_TRUE(result) << result.GetErrorMessage(); \
44 } while (0)
45
46Result<ResourceMapping> TestGetResourceMapping(const android::StringPiece& local_target_apk_path,
47 const android::StringPiece& local_overlay_apk_path,
48 const OverlayManifestInfo& overlay_info,
49 const PolicyBitmask& fulfilled_policies,
50 bool enforce_overlayable) {
51 const std::string target_apk_path(GetTestDataPath() + local_target_apk_path.data());
52 std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
53 if (!target_apk) {
54 return Error(R"(Failed to load target apk "%s")", target_apk_path.data());
55 }
56
57 const std::string overlay_apk_path(GetTestDataPath() + local_overlay_apk_path.data());
58 std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
59 if (!overlay_apk) {
60 return Error(R"(Failed to load overlay apk "%s")", overlay_apk_path.data());
61 }
62
Mårten Kongstadd7e8a532019-10-11 08:32:04 +020063 LogInfo log_info;
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -070064 return ResourceMapping::FromApkAssets(*target_apk, *overlay_apk, overlay_info, fulfilled_policies,
Mårten Kongstadd7e8a532019-10-11 08:32:04 +020065 enforce_overlayable, log_info);
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -070066}
67
68Result<ResourceMapping> TestGetResourceMapping(const android::StringPiece& local_target_apk_path,
69 const android::StringPiece& local_overlay_apk_path,
70 const PolicyBitmask& fulfilled_policies,
71 bool enforce_overlayable) {
72 auto overlay_info = ExtractOverlayManifestInfo(GetTestDataPath() + local_overlay_apk_path.data());
73 if (!overlay_info) {
74 return overlay_info.GetError();
75 }
76 return TestGetResourceMapping(local_target_apk_path, local_overlay_apk_path, *overlay_info,
77 fulfilled_policies, enforce_overlayable);
78}
79
80Result<Unit> MappingExists(const ResourceMapping& mapping, const ResourceId& target_resource,
81 const uint8_t type, const uint32_t value, bool rewrite) {
82 auto target_map = mapping.GetTargetToOverlayMap();
83 auto entry_map = target_map.find(target_resource);
84 if (entry_map == target_map.end()) {
85 return Error("Failed to find mapping for target resource");
86 }
87
88 if (entry_map->second.data_type != type) {
89 return Error(R"(Expected type: "0x%02x" Actual type: "0x%02x")", type,
90 entry_map->second.data_type);
91 }
92
93 if (entry_map->second.data_value != value) {
94 return Error(R"(Expected value: "0x%08x" Actual value: "0x%08x")", type,
95 entry_map->second.data_value);
96 }
97
98 auto overlay_map = mapping.GetOverlayToTargetMap();
99 auto overlay_iter = overlay_map.find(entry_map->second.data_value);
100 if ((overlay_iter != overlay_map.end()) != rewrite) {
101 return Error(R"(Expected rewriting: "%s")", rewrite ? "true" : "false");
102 }
103
104 return Result<Unit>({});
105}
106
107TEST(ResourceMappingTests, ResourcesFromApkAssetsLegacy) {
108 OverlayManifestInfo info{};
109 info.target_package = "test.target";
110 info.target_name = "TestResources";
111 info.resource_mapping = 0U; // no xml
112 auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay.apk", info,
Winson62ac8b52019-12-04 08:36:48 -0800113 PolicyFlags::PUBLIC,
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700114 /* enforce_overlayable */ false);
115
116 ASSERT_TRUE(resources) << resources.GetErrorMessage();
117 auto& res = *resources;
118 ASSERT_EQ(res.GetTargetToOverlayMap().size(), 4U);
Winson62ac8b52019-12-04 08:36:48 -0800119 ASSERT_RESULT(MappingExists(res, R::target::integer::int1, Res_value::TYPE_REFERENCE,
120 R::overlay::integer::int1, false /* rewrite */));
121 ASSERT_RESULT(MappingExists(res, R::target::string::str1, Res_value::TYPE_REFERENCE,
122 R::overlay::string::str1, false /* rewrite */));
123 ASSERT_RESULT(MappingExists(res, R::target::string::str3, Res_value::TYPE_REFERENCE,
124 R::overlay::string::str3, false /* rewrite */));
125 ASSERT_RESULT(MappingExists(res, R::target::string::str4, Res_value::TYPE_REFERENCE,
126 R::overlay::string::str4, false /* rewrite */));
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700127}
128
129TEST(ResourceMappingTests, ResourcesFromApkAssetsNonMatchingNames) {
130 OverlayManifestInfo info{};
131 info.target_package = "test.target";
132 info.target_name = "TestResources";
133 info.resource_mapping = 0x7f030003; // xml/overlays_swap
134 auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay.apk", info,
Winson62ac8b52019-12-04 08:36:48 -0800135 PolicyFlags::PUBLIC,
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700136 /* enforce_overlayable */ false);
137
138 ASSERT_TRUE(resources) << resources.GetErrorMessage();
139 auto& res = *resources;
140 ASSERT_EQ(res.GetTargetToOverlayMap().size(), 3U);
Winson62ac8b52019-12-04 08:36:48 -0800141 ASSERT_RESULT(MappingExists(res, R::target::string::str1, Res_value::TYPE_DYNAMIC_REFERENCE,
142 R::overlay::string::str4, true /* rewrite */));
143 ASSERT_RESULT(MappingExists(res, R::target::string::str3, Res_value::TYPE_DYNAMIC_REFERENCE,
144 R::overlay::string::str1, true /* rewrite */));
145 ASSERT_RESULT(MappingExists(res, R::target::string::str4, Res_value::TYPE_DYNAMIC_REFERENCE,
146 R::overlay::string::str3, true /* rewrite */));
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700147}
148
Ryan Mitchelle753ffe2019-09-23 09:47:02 -0700149TEST(ResourceMappingTests, DoNotRewriteNonOverlayResourceId) {
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700150 OverlayManifestInfo info{};
151 info.target_package = "test.target";
152 info.target_name = "TestResources";
153 info.resource_mapping = 0x7f030001; // xml/overlays_different_packages
154 auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay.apk", info,
Winson62ac8b52019-12-04 08:36:48 -0800155 PolicyFlags::PUBLIC,
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700156 /* enforce_overlayable */ false);
157
158 ASSERT_TRUE(resources) << resources.GetErrorMessage();
159 auto& res = *resources;
160 ASSERT_EQ(res.GetTargetToOverlayMap().size(), 2U);
161 ASSERT_EQ(res.GetOverlayToTargetMap().size(), 1U);
Winson62ac8b52019-12-04 08:36:48 -0800162 ASSERT_RESULT(MappingExists(res, R::target::string::str1, Res_value::TYPE_REFERENCE, 0x0104000a,
163 false /* rewrite */)); // -> android:string/ok
164 ASSERT_RESULT(MappingExists(res, R::target::string::str3, Res_value::TYPE_DYNAMIC_REFERENCE,
165 0x7f020001, true /* rewrite */));
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700166}
167
168TEST(ResourceMappingTests, InlineResources) {
169 OverlayManifestInfo info{};
170 info.target_package = "test.target";
171 info.target_name = "TestResources";
172 info.resource_mapping = 0x7f030002; // xml/overlays_inline
173 auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay.apk", info,
Winson62ac8b52019-12-04 08:36:48 -0800174 PolicyFlags::PUBLIC,
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700175 /* enforce_overlayable */ false);
176
177 constexpr size_t overlay_string_pool_size = 8U;
178 ASSERT_TRUE(resources) << resources.GetErrorMessage();
179 auto& res = *resources;
180 ASSERT_EQ(res.GetTargetToOverlayMap().size(), 2U);
181 ASSERT_EQ(res.GetOverlayToTargetMap().size(), 0U);
Winson62ac8b52019-12-04 08:36:48 -0800182 ASSERT_RESULT(MappingExists(res, R::target::string::str1, Res_value::TYPE_STRING,
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700183 overlay_string_pool_size + 0U,
Winson62ac8b52019-12-04 08:36:48 -0800184 false /* rewrite */)); // -> "Hello World"
185 ASSERT_RESULT(MappingExists(res, R::target::integer::int1, Res_value::TYPE_INT_DEC, 73U,
186 false /* rewrite */)); // -> 73
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700187}
188
189TEST(ResourceMappingTests, CreateIdmapFromApkAssetsPolicySystemPublic) {
190 auto resources =
191 TestGetResourceMapping("/target/target.apk", "/system-overlay/system-overlay.apk",
Winson62ac8b52019-12-04 08:36:48 -0800192 PolicyFlags::SYSTEM_PARTITION | PolicyFlags::PUBLIC,
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700193 /* enforce_overlayable */ true);
194
195 ASSERT_TRUE(resources) << resources.GetErrorMessage();
196 auto& res = *resources;
197 ASSERT_EQ(res.GetTargetToOverlayMap().size(), 3U);
Winson62ac8b52019-12-04 08:36:48 -0800198 ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, Res_value::TYPE_REFERENCE,
199 R::system_overlay::string::policy_public, false /* rewrite */));
200 ASSERT_RESULT(MappingExists(res, R::target::string::policy_system, Res_value::TYPE_REFERENCE,
201 R::system_overlay::string::policy_system, false /* rewrite */));
202 ASSERT_RESULT(
203 MappingExists(res, R::target::string::policy_system_vendor, Res_value::TYPE_REFERENCE,
204 R::system_overlay::string::policy_system_vendor, false /* rewrite */));
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700205}
206
207// Resources that are not declared as overlayable and resources that a protected by policies the
208// overlay does not fulfill must not map to overlay resources.
209TEST(ResourceMappingTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalid) {
Winson62ac8b52019-12-04 08:36:48 -0800210 auto resources = TestGetResourceMapping("/target/target.apk",
211 "/system-overlay-invalid/system-overlay-invalid.apk",
212 PolicyFlags::SYSTEM_PARTITION | PolicyFlags::PUBLIC,
213 /* enforce_overlayable */ true);
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700214
215 ASSERT_TRUE(resources) << resources.GetErrorMessage();
216 auto& res = *resources;
217 ASSERT_EQ(res.GetTargetToOverlayMap().size(), 3U);
Winson62ac8b52019-12-04 08:36:48 -0800218 ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, Res_value::TYPE_REFERENCE,
219 R::system_overlay_invalid::string::policy_public,
220 false /* rewrite */));
221 ASSERT_RESULT(MappingExists(res, R::target::string::policy_system, Res_value::TYPE_REFERENCE,
222 R::system_overlay_invalid::string::policy_system,
223 false /* rewrite */));
224 ASSERT_RESULT(
225 MappingExists(res, R::target::string::policy_system_vendor, Res_value::TYPE_REFERENCE,
226 R::system_overlay_invalid::string::policy_system_vendor, false /* rewrite */));
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700227}
228
229// Resources that are not declared as overlayable and resources that a protected by policies the
230// overlay does not fulfilled can map to overlay resources when overlayable enforcement is turned
231// off.
232TEST(ResourceMappingTests, ResourcesFromApkAssetsPolicySystemPublicInvalidIgnoreOverlayable) {
Winson62ac8b52019-12-04 08:36:48 -0800233 auto resources = TestGetResourceMapping("/target/target.apk",
234 "/system-overlay-invalid/system-overlay-invalid.apk",
235 PolicyFlags::SYSTEM_PARTITION | PolicyFlags::PUBLIC,
236 /* enforce_overlayable */ false);
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700237
238 ASSERT_TRUE(resources) << resources.GetErrorMessage();
239 auto& res = *resources;
Winsonf56ade32019-12-04 11:32:41 -0800240 ASSERT_EQ(res.GetTargetToOverlayMap().size(), 10U);
Winson62ac8b52019-12-04 08:36:48 -0800241 ASSERT_RESULT(MappingExists(res, R::target::string::not_overlayable, Res_value::TYPE_REFERENCE,
242 R::system_overlay_invalid::string::not_overlayable,
243 false /* rewrite */));
244 ASSERT_RESULT(MappingExists(res, R::target::string::other, Res_value::TYPE_REFERENCE,
245 R::system_overlay_invalid::string::other, false /* rewrite */));
Winsonf56ade32019-12-04 11:32:41 -0800246 ASSERT_RESULT(MappingExists(res, R::target::string::policy_actor, Res_value::TYPE_REFERENCE,
247 R::system_overlay_invalid::string::policy_actor,
248 false /* rewrite */));
Winson62ac8b52019-12-04 08:36:48 -0800249 ASSERT_RESULT(MappingExists(res, R::target::string::policy_odm, Res_value::TYPE_REFERENCE,
250 R::system_overlay_invalid::string::policy_odm, false /* rewrite */));
251 ASSERT_RESULT(MappingExists(res, R::target::string::policy_oem, Res_value::TYPE_REFERENCE,
252 R::system_overlay_invalid::string::policy_oem, false /* rewrite */));
253 ASSERT_RESULT(MappingExists(res, R::target::string::policy_product, Res_value::TYPE_REFERENCE,
254 R::system_overlay_invalid::string::policy_product,
255 false /* rewrite */));
256 ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, Res_value::TYPE_REFERENCE,
257 R::system_overlay_invalid::string::policy_public,
258 false /* rewrite */));
259 ASSERT_RESULT(MappingExists(res, R::target::string::policy_signature, Res_value::TYPE_REFERENCE,
260 R::system_overlay_invalid::string::policy_signature,
261 false /* rewrite */));
262 ASSERT_RESULT(MappingExists(res, R::target::string::policy_system, Res_value::TYPE_REFERENCE,
263 R::system_overlay_invalid::string::policy_system,
264 false /* rewrite */));
265 ASSERT_RESULT(
266 MappingExists(res, R::target::string::policy_system_vendor, Res_value::TYPE_REFERENCE,
267 R::system_overlay_invalid::string::policy_system_vendor, false /* rewrite */));
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700268}
269
270// Overlays that do not target an <overlayable> tag can overlay resources defined within any
271// <overlayable> tag.
272TEST(ResourceMappingTests, ResourcesFromApkAssetsNoDefinedOverlayableAndNoTargetName) {
273 auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay-no-name.apk",
Winson62ac8b52019-12-04 08:36:48 -0800274 PolicyFlags::PUBLIC,
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700275 /* enforce_overlayable */ false);
276
277 ASSERT_TRUE(resources) << resources.GetErrorMessage();
278 auto& res = *resources;
279 ASSERT_EQ(res.GetTargetToOverlayMap().size(), 4U);
Winson62ac8b52019-12-04 08:36:48 -0800280 ASSERT_RESULT(MappingExists(res, R::target::integer::int1, Res_value::TYPE_REFERENCE,
281 R::overlay::integer::int1, false /* rewrite */));
282 ASSERT_RESULT(MappingExists(res, R::target::string::str1, Res_value::TYPE_REFERENCE,
283 R::overlay::string::str1, false /* rewrite */));
284 ASSERT_RESULT(MappingExists(res, R::target::string::str3, Res_value::TYPE_REFERENCE,
285 R::overlay::string::str3, false /* rewrite */));
286 ASSERT_RESULT(MappingExists(res, R::target::string::str4, Res_value::TYPE_REFERENCE,
287 R::overlay::string::str4, false /* rewrite */));
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700288}
289
Ryan Mitchelle88ef742020-06-03 12:55:02 -0700290// Overlays that are neither pre-installed nor signed with the same signature as the target cannot
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700291// overlay packages that have not defined overlayable resources.
Ryan Mitchelle88ef742020-06-03 12:55:02 -0700292TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPoliciesPublicFail) {
293 auto resources = TestGetResourceMapping("/target/target-no-overlayable.apk",
294 "/overlay/overlay-no-name.apk", PolicyFlags::PUBLIC,
295 /* enforce_overlayable */ true);
Ryan Mitchellaf93f5d2020-05-26 14:29:03 -0700296
Ryan Mitchelle88ef742020-06-03 12:55:02 -0700297 ASSERT_TRUE(resources) << resources.GetErrorMessage();
298 ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 0U);
299}
300
301// Overlays that are pre-installed or are signed with the same signature as the target can overlay
302// packages that have not defined overlayable resources.
303TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPolicies) {
304 auto CheckEntries = [&](const PolicyBitmask& fulfilled_policies) -> void {
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700305 auto resources = TestGetResourceMapping("/target/target-no-overlayable.apk",
306 "/system-overlay-invalid/system-overlay-invalid.apk",
Ryan Mitchelle88ef742020-06-03 12:55:02 -0700307 fulfilled_policies,
308 /* enforce_overlayable */ true);
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700309
Ryan Mitchelle88ef742020-06-03 12:55:02 -0700310 ASSERT_TRUE(resources) << resources.GetErrorMessage();
311 auto& res = *resources;
312 ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 10U);
313 ASSERT_RESULT(MappingExists(res, R::target::string::not_overlayable, Res_value::TYPE_REFERENCE,
314 R::system_overlay_invalid::string::not_overlayable,
315 false /* rewrite */));
316 ASSERT_RESULT(MappingExists(res, R::target::string::other, Res_value::TYPE_REFERENCE,
317 R::system_overlay_invalid::string::other, false /* rewrite */));
318 ASSERT_RESULT(MappingExists(res, R::target::string::policy_actor, Res_value::TYPE_REFERENCE,
319 R::system_overlay_invalid::string::policy_actor,
320 false /* rewrite */));
321 ASSERT_RESULT(MappingExists(res, R::target::string::policy_odm, Res_value::TYPE_REFERENCE,
322 R::system_overlay_invalid::string::policy_odm,
323 false /* rewrite */));
324 ASSERT_RESULT(MappingExists(res, R::target::string::policy_oem, Res_value::TYPE_REFERENCE,
325 R::system_overlay_invalid::string::policy_oem,
326 false /* rewrite */));
327 ASSERT_RESULT(MappingExists(res, R::target::string::policy_product, Res_value::TYPE_REFERENCE,
328 R::system_overlay_invalid::string::policy_product,
329 false /* rewrite */));
330 ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, Res_value::TYPE_REFERENCE,
331 R::system_overlay_invalid::string::policy_public,
332 false /* rewrite */));
333 ASSERT_RESULT(MappingExists(res, R::target::string::policy_signature, Res_value::TYPE_REFERENCE,
334 R::system_overlay_invalid::string::policy_signature,
335 false /* rewrite */));
336 ASSERT_RESULT(MappingExists(res, R::target::string::policy_system, Res_value::TYPE_REFERENCE,
337 R::system_overlay_invalid::string::policy_system,
338 false /* rewrite */));
339 ASSERT_RESULT(MappingExists(
340 res, R::target::string::policy_system_vendor, Res_value::TYPE_REFERENCE,
341 R::system_overlay_invalid::string::policy_system_vendor, false /* rewrite */));
342 };
343
344 CheckEntries(PolicyFlags::SIGNATURE);
345 CheckEntries(PolicyFlags::PRODUCT_PARTITION);
346 CheckEntries(PolicyFlags::SYSTEM_PARTITION);
347 CheckEntries(PolicyFlags::VENDOR_PARTITION);
348 CheckEntries(PolicyFlags::ODM_PARTITION);
349 CheckEntries(PolicyFlags::OEM_PARTITION);
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700350}
351
352} // namespace android::idmap2