blob: 64304f64d22c9a8817e77df4702db3ef54059b81 [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
25#include "TestHelpers.h"
26#include "gmock/gmock.h"
27#include "gtest/gtest.h"
28#include "idmap2/ResourceMapping.h"
29
Ryan Mitchelle753ffe2019-09-23 09:47:02 -070030using android::Res_value;
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -070031using android::idmap2::utils::ExtractOverlayManifestInfo;
32
33namespace android::idmap2 {
34
35#define ASSERT_RESULT(r) \
36 do { \
37 auto result = r; \
38 ASSERT_TRUE(result) << result.GetErrorMessage(); \
39 } while (0)
40
41Result<ResourceMapping> TestGetResourceMapping(const android::StringPiece& local_target_apk_path,
42 const android::StringPiece& local_overlay_apk_path,
43 const OverlayManifestInfo& overlay_info,
44 const PolicyBitmask& fulfilled_policies,
45 bool enforce_overlayable) {
46 const std::string target_apk_path(GetTestDataPath() + local_target_apk_path.data());
47 std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
48 if (!target_apk) {
49 return Error(R"(Failed to load target apk "%s")", target_apk_path.data());
50 }
51
52 const std::string overlay_apk_path(GetTestDataPath() + local_overlay_apk_path.data());
53 std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
54 if (!overlay_apk) {
55 return Error(R"(Failed to load overlay apk "%s")", overlay_apk_path.data());
56 }
57
58 return ResourceMapping::FromApkAssets(*target_apk, *overlay_apk, overlay_info, fulfilled_policies,
59 enforce_overlayable);
60}
61
62Result<ResourceMapping> TestGetResourceMapping(const android::StringPiece& local_target_apk_path,
63 const android::StringPiece& local_overlay_apk_path,
64 const PolicyBitmask& fulfilled_policies,
65 bool enforce_overlayable) {
66 auto overlay_info = ExtractOverlayManifestInfo(GetTestDataPath() + local_overlay_apk_path.data());
67 if (!overlay_info) {
68 return overlay_info.GetError();
69 }
70 return TestGetResourceMapping(local_target_apk_path, local_overlay_apk_path, *overlay_info,
71 fulfilled_policies, enforce_overlayable);
72}
73
74Result<Unit> MappingExists(const ResourceMapping& mapping, const ResourceId& target_resource,
75 const uint8_t type, const uint32_t value, bool rewrite) {
76 auto target_map = mapping.GetTargetToOverlayMap();
77 auto entry_map = target_map.find(target_resource);
78 if (entry_map == target_map.end()) {
79 return Error("Failed to find mapping for target resource");
80 }
81
82 if (entry_map->second.data_type != type) {
83 return Error(R"(Expected type: "0x%02x" Actual type: "0x%02x")", type,
84 entry_map->second.data_type);
85 }
86
87 if (entry_map->second.data_value != value) {
88 return Error(R"(Expected value: "0x%08x" Actual value: "0x%08x")", type,
89 entry_map->second.data_value);
90 }
91
92 auto overlay_map = mapping.GetOverlayToTargetMap();
93 auto overlay_iter = overlay_map.find(entry_map->second.data_value);
94 if ((overlay_iter != overlay_map.end()) != rewrite) {
95 return Error(R"(Expected rewriting: "%s")", rewrite ? "true" : "false");
96 }
97
98 return Result<Unit>({});
99}
100
101TEST(ResourceMappingTests, ResourcesFromApkAssetsLegacy) {
102 OverlayManifestInfo info{};
103 info.target_package = "test.target";
104 info.target_name = "TestResources";
105 info.resource_mapping = 0U; // no xml
106 auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay.apk", info,
107 PolicyFlags::POLICY_PUBLIC,
108 /* enforce_overlayable */ false);
109
110 ASSERT_TRUE(resources) << resources.GetErrorMessage();
111 auto& res = *resources;
112 ASSERT_EQ(res.GetTargetToOverlayMap().size(), 4U);
Ryan Mitchelle753ffe2019-09-23 09:47:02 -0700113 ASSERT_RESULT(MappingExists(res, 0x7f010000, Res_value::TYPE_REFERENCE, 0x7f010000,
114 false /* rewrite */)); // integer/int1
115 ASSERT_RESULT(MappingExists(res, 0x7f02000c, Res_value::TYPE_REFERENCE, 0x7f020000,
116 false /* rewrite */)); // string/str1
117 ASSERT_RESULT(MappingExists(res, 0x7f02000e, Res_value::TYPE_REFERENCE, 0x7f020001,
118 false /* rewrite */)); // string/str3
119 ASSERT_RESULT(MappingExists(res, 0x7f02000f, Res_value::TYPE_REFERENCE, 0x7f020002,
120 false /* rewrite */)); // string/str4
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700121}
122
123TEST(ResourceMappingTests, ResourcesFromApkAssetsNonMatchingNames) {
124 OverlayManifestInfo info{};
125 info.target_package = "test.target";
126 info.target_name = "TestResources";
127 info.resource_mapping = 0x7f030003; // xml/overlays_swap
128 auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay.apk", info,
129 PolicyFlags::POLICY_PUBLIC,
130 /* enforce_overlayable */ false);
131
132 ASSERT_TRUE(resources) << resources.GetErrorMessage();
133 auto& res = *resources;
134 ASSERT_EQ(res.GetTargetToOverlayMap().size(), 3U);
Ryan Mitchelle753ffe2019-09-23 09:47:02 -0700135 ASSERT_RESULT(MappingExists(res, 0x7f02000c, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f020002,
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700136 true /* rewrite */)); // string/str1 -> string/str4
Ryan Mitchelle753ffe2019-09-23 09:47:02 -0700137 ASSERT_RESULT(MappingExists(res, 0x7f02000e, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f020000,
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700138 true /* rewrite */)); // string/str3 -> string/str1
Ryan Mitchelle753ffe2019-09-23 09:47:02 -0700139 ASSERT_RESULT(MappingExists(res, 0x7f02000f, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f020001,
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700140 true /* rewrite */)); // string/str4 -> string/str3
141}
142
Ryan Mitchelle753ffe2019-09-23 09:47:02 -0700143TEST(ResourceMappingTests, DoNotRewriteNonOverlayResourceId) {
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700144 OverlayManifestInfo info{};
145 info.target_package = "test.target";
146 info.target_name = "TestResources";
147 info.resource_mapping = 0x7f030001; // xml/overlays_different_packages
148 auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay.apk", info,
149 PolicyFlags::POLICY_PUBLIC,
150 /* enforce_overlayable */ false);
151
152 ASSERT_TRUE(resources) << resources.GetErrorMessage();
153 auto& res = *resources;
154 ASSERT_EQ(res.GetTargetToOverlayMap().size(), 2U);
155 ASSERT_EQ(res.GetOverlayToTargetMap().size(), 1U);
Ryan Mitchelle753ffe2019-09-23 09:47:02 -0700156 ASSERT_RESULT(MappingExists(res, 0x7f02000c, Res_value::TYPE_REFERENCE, 0x0104000a,
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700157 false /* rewrite */)); // string/str1 -> android:string/ok
Ryan Mitchelle753ffe2019-09-23 09:47:02 -0700158 ASSERT_RESULT(MappingExists(res, 0x7f02000e, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f020001,
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700159 true /* rewrite */)); // string/str3 -> string/str4
160}
161
162TEST(ResourceMappingTests, InlineResources) {
163 OverlayManifestInfo info{};
164 info.target_package = "test.target";
165 info.target_name = "TestResources";
166 info.resource_mapping = 0x7f030002; // xml/overlays_inline
167 auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay.apk", info,
168 PolicyFlags::POLICY_PUBLIC,
169 /* enforce_overlayable */ false);
170
171 constexpr size_t overlay_string_pool_size = 8U;
172 ASSERT_TRUE(resources) << resources.GetErrorMessage();
173 auto& res = *resources;
174 ASSERT_EQ(res.GetTargetToOverlayMap().size(), 2U);
175 ASSERT_EQ(res.GetOverlayToTargetMap().size(), 0U);
Ryan Mitchelle753ffe2019-09-23 09:47:02 -0700176 ASSERT_RESULT(MappingExists(res, 0x7f02000c, Res_value::TYPE_STRING,
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700177 overlay_string_pool_size + 0U,
178 false /* rewrite */)); // string/str1 -> "Hello World"
Ryan Mitchelle753ffe2019-09-23 09:47:02 -0700179 ASSERT_RESULT(MappingExists(res, 0x7f010000, Res_value::TYPE_INT_DEC, 73U,
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700180 false /* rewrite */)); // string/str1 -> "Hello World"
181}
182
183TEST(ResourceMappingTests, CreateIdmapFromApkAssetsPolicySystemPublic) {
184 auto resources =
185 TestGetResourceMapping("/target/target.apk", "/system-overlay/system-overlay.apk",
186 PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
187 /* enforce_overlayable */ true);
188
189 ASSERT_TRUE(resources) << resources.GetErrorMessage();
190 auto& res = *resources;
191 ASSERT_EQ(res.GetTargetToOverlayMap().size(), 3U);
Ryan Mitchelle753ffe2019-09-23 09:47:02 -0700192 ASSERT_RESULT(MappingExists(res, 0x7f020008, Res_value::TYPE_REFERENCE, 0x7f010000,
193 false /* rewrite */)); // string/policy_public
194 ASSERT_RESULT(MappingExists(res, 0x7f02000a, Res_value::TYPE_REFERENCE, 0x7f010001,
195 false /* rewrite */)); // string/policy_system
196 ASSERT_RESULT(MappingExists(res, 0x7f02000b, Res_value::TYPE_REFERENCE, 0x7f010002,
197 false /* rewrite */)); // string/policy_system_vendor
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700198}
199
200// Resources that are not declared as overlayable and resources that a protected by policies the
201// overlay does not fulfill must not map to overlay resources.
202TEST(ResourceMappingTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalid) {
203 auto resources = TestGetResourceMapping(
204 "/target/target.apk", "/system-overlay-invalid/system-overlay-invalid.apk",
205 PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
206 /* enforce_overlayable */ true);
207
208 ASSERT_TRUE(resources) << resources.GetErrorMessage();
209 auto& res = *resources;
210 ASSERT_EQ(res.GetTargetToOverlayMap().size(), 3U);
Ryan Mitchelle753ffe2019-09-23 09:47:02 -0700211 ASSERT_RESULT(MappingExists(res, 0x7f020008, Res_value::TYPE_REFERENCE, 0x7f010005,
212 false /* rewrite */)); // string/policy_public
213 ASSERT_RESULT(MappingExists(res, 0x7f02000a, Res_value::TYPE_REFERENCE, 0x7f010007,
214 false /* rewrite */)); // string/policy_system
215 ASSERT_RESULT(MappingExists(res, 0x7f02000b, Res_value::TYPE_REFERENCE, 0x7f010008,
216 false /* rewrite */)); // string/policy_system_vendor
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700217}
218
219// Resources that are not declared as overlayable and resources that a protected by policies the
220// overlay does not fulfilled can map to overlay resources when overlayable enforcement is turned
221// off.
222TEST(ResourceMappingTests, ResourcesFromApkAssetsPolicySystemPublicInvalidIgnoreOverlayable) {
223 auto resources = TestGetResourceMapping(
224 "/target/target.apk", "/system-overlay-invalid/system-overlay-invalid.apk",
225 PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
226 /* enforce_overlayable */ false);
227
228 ASSERT_TRUE(resources) << resources.GetErrorMessage();
229 auto& res = *resources;
230 ASSERT_EQ(res.GetTargetToOverlayMap().size(), 9U);
Ryan Mitchelle753ffe2019-09-23 09:47:02 -0700231 ASSERT_RESULT(MappingExists(res, 0x7f020003, Res_value::TYPE_REFERENCE, 0x7f010000,
232 false /* rewrite */)); // string/not_overlayable
233 ASSERT_RESULT(MappingExists(res, 0x7f020004, Res_value::TYPE_REFERENCE, 0x7f010001,
234 false /* rewrite */)); // string/other
235 ASSERT_RESULT(MappingExists(res, 0x7f020005, Res_value::TYPE_REFERENCE, 0x7f010002,
236 false /* rewrite */)); // string/policy_odm
237 ASSERT_RESULT(MappingExists(res, 0x7f020006, Res_value::TYPE_REFERENCE, 0x7f010003,
238 false /* rewrite */)); // string/policy_oem
239 ASSERT_RESULT(MappingExists(res, 0x7f020007, Res_value::TYPE_REFERENCE, 0x7f010004,
240 false /* rewrite */)); // string/policy_product
241 ASSERT_RESULT(MappingExists(res, 0x7f020008, Res_value::TYPE_REFERENCE, 0x7f010005,
242 false /* rewrite */)); // string/policy_public
243 ASSERT_RESULT(MappingExists(res, 0x7f020009, Res_value::TYPE_REFERENCE, 0x7f010006,
244 false /* rewrite */)); // string/policy_signature
245 ASSERT_RESULT(MappingExists(res, 0x7f02000a, Res_value::TYPE_REFERENCE, 0x7f010007,
246 false /* rewrite */)); // string/policy_system
247 ASSERT_RESULT(MappingExists(res, 0x7f02000b, Res_value::TYPE_REFERENCE, 0x7f010008,
248 false /* rewrite */)); // string/policy_system_vendor
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700249}
250
251// Overlays that do not target an <overlayable> tag can overlay resources defined within any
252// <overlayable> tag.
253TEST(ResourceMappingTests, ResourcesFromApkAssetsNoDefinedOverlayableAndNoTargetName) {
254 auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay-no-name.apk",
255 PolicyFlags::POLICY_PUBLIC,
256 /* enforce_overlayable */ false);
257
258 ASSERT_TRUE(resources) << resources.GetErrorMessage();
259 auto& res = *resources;
260 ASSERT_EQ(res.GetTargetToOverlayMap().size(), 4U);
Ryan Mitchelle753ffe2019-09-23 09:47:02 -0700261 ASSERT_RESULT(MappingExists(res, 0x7f010000, Res_value::TYPE_REFERENCE, 0x7f010000,
262 false /* rewrite */)); // integer/int1
263 ASSERT_RESULT(MappingExists(res, 0x7f02000c, Res_value::TYPE_REFERENCE, 0x7f020000,
264 false /* rewrite */)); // string/str1
265 ASSERT_RESULT(MappingExists(res, 0x7f02000e, Res_value::TYPE_REFERENCE, 0x7f020001,
266 false /* rewrite */)); // string/str3
267 ASSERT_RESULT(MappingExists(res, 0x7f02000f, Res_value::TYPE_REFERENCE, 0x7f020002,
268 false /* rewrite */)); // string/str4
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700269}
270
271// Overlays that are neither pre-installed nor signed with the same signature as the target cannot
272// overlay packages that have not defined overlayable resources.
273TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPoliciesPublicFail) {
274 auto resources =
275 TestGetResourceMapping("/target/target-no-overlayable.apk", "/overlay/overlay-no-name.apk",
276 PolicyFlags::POLICY_PUBLIC,
277 /* enforce_overlayable */ true);
278
279 ASSERT_TRUE(resources) << resources.GetErrorMessage();
280 ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 0U);
281}
282
283// Overlays that are pre-installed or are signed with the same signature as the target can overlay
284// packages that have not defined overlayable resources.
285TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPolicies) {
286 auto CheckEntries = [&](const PolicyBitmask& fulfilled_policies) -> void {
287 auto resources = TestGetResourceMapping("/target/target-no-overlayable.apk",
288 "/system-overlay-invalid/system-overlay-invalid.apk",
289 fulfilled_policies,
290 /* enforce_overlayable */ true);
291
292 ASSERT_TRUE(resources) << resources.GetErrorMessage();
293 auto& res = *resources;
294 ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 9U);
Ryan Mitchelle753ffe2019-09-23 09:47:02 -0700295 ASSERT_RESULT(MappingExists(res, 0x7f020003, Res_value::TYPE_REFERENCE, 0x7f010000,
296 false /* rewrite */)); // string/not_overlayable
297 ASSERT_RESULT(MappingExists(res, 0x7f020004, Res_value::TYPE_REFERENCE, 0x7f010001,
298 false /* rewrite */)); // string/other
299 ASSERT_RESULT(MappingExists(res, 0x7f020005, Res_value::TYPE_REFERENCE, 0x7f010002,
300 false /* rewrite */)); // string/policy_odm
301 ASSERT_RESULT(MappingExists(res, 0x7f020006, Res_value::TYPE_REFERENCE, 0x7f010003,
302 false /* rewrite */)); // string/policy_oem
303 ASSERT_RESULT(MappingExists(res, 0x7f020007, Res_value::TYPE_REFERENCE, 0x7f010004,
304 false /* rewrite */)); // string/policy_product
305 ASSERT_RESULT(MappingExists(res, 0x7f020008, Res_value::TYPE_REFERENCE, 0x7f010005,
306 false /* rewrite */)); // string/policy_public
307 ASSERT_RESULT(MappingExists(res, 0x7f020009, Res_value::TYPE_REFERENCE, 0x7f010006,
308 false /* rewrite */)); // string/policy_signature
309 ASSERT_RESULT(MappingExists(res, 0x7f02000a, Res_value::TYPE_REFERENCE, 0x7f010007,
310 false /* rewrite */)); // string/policy_system
311 ASSERT_RESULT(MappingExists(res, 0x7f02000b, Res_value::TYPE_REFERENCE, 0x7f010008,
312 false /* rewrite */)); // string/policy_system_vendor
Ryan Mitchell9e4f52b2019-09-19 12:15:52 -0700313 };
314
315 CheckEntries(PolicyFlags::POLICY_SIGNATURE);
316 CheckEntries(PolicyFlags::POLICY_PRODUCT_PARTITION);
317 CheckEntries(PolicyFlags::POLICY_SYSTEM_PARTITION);
318 CheckEntries(PolicyFlags::POLICY_VENDOR_PARTITION);
319 CheckEntries(PolicyFlags::POLICY_ODM_PARTITION);
320 CheckEntries(PolicyFlags::POLICY_OEM_PARTITION);
321}
322
323} // namespace android::idmap2