blob: bedebd66cb2f098b3562dd09c49c2fc30353bf42 [file] [log] [blame]
Adam Lesinski7ad11102016-10-28 16:39:15 -07001/*
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/LoadedArsc.h"
18
Adam Lesinski64ee69d2018-01-08 17:38:30 -080019#include "androidfw/ResourceUtils.h"
20
Adam Lesinski7ad11102016-10-28 16:39:15 -070021#include "TestHelpers.h"
22#include "data/basic/R.h"
Adam Lesinskida431a22016-12-29 16:08:16 -050023#include "data/libclient/R.h"
Adam Lesinski73f6f9d2017-11-14 10:18:05 -080024#include "data/sparse/R.h"
Adam Lesinski7ad11102016-10-28 16:39:15 -070025#include "data/styles/R.h"
26
27namespace app = com::android::app;
28namespace basic = com::android::basic;
Adam Lesinskida431a22016-12-29 16:08:16 -050029namespace libclient = com::android::libclient;
Adam Lesinski73f6f9d2017-11-14 10:18:05 -080030namespace sparse = com::android::sparse;
Adam Lesinski7ad11102016-10-28 16:39:15 -070031
Adam Lesinski64ee69d2018-01-08 17:38:30 -080032using ::testing::Eq;
33using ::testing::Ge;
34using ::testing::IsNull;
35using ::testing::NotNull;
36using ::testing::SizeIs;
37using ::testing::StrEq;
38
Adam Lesinski7ad11102016-10-28 16:39:15 -070039namespace android {
40
41TEST(LoadedArscTest, LoadSinglePackageArsc) {
Adam Lesinski7ad11102016-10-28 16:39:15 -070042 std::string contents;
43 ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/styles/styles.apk", "resources.arsc",
44 &contents));
45
Adam Lesinski970bd8d2017-09-25 13:21:55 -070046 std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
Adam Lesinski64ee69d2018-01-08 17:38:30 -080047 ASSERT_THAT(loaded_arsc, NotNull());
Adam Lesinski7ad11102016-10-28 16:39:15 -070048
Adam Lesinski64ee69d2018-01-08 17:38:30 -080049 const LoadedPackage* package =
50 loaded_arsc->GetPackageById(get_package_id(app::R::string::string_one));
51 ASSERT_THAT(package, NotNull());
52 EXPECT_THAT(package->GetPackageName(), StrEq("com.android.app"));
53 EXPECT_THAT(package->GetPackageId(), Eq(0x7f));
Adam Lesinskida431a22016-12-29 16:08:16 -050054
Adam Lesinski64ee69d2018-01-08 17:38:30 -080055 const uint8_t type_index = get_type_id(app::R::string::string_one) - 1;
56 const uint16_t entry_index = get_entry_id(app::R::string::string_one);
Adam Lesinski7ad11102016-10-28 16:39:15 -070057
Adam Lesinski64ee69d2018-01-08 17:38:30 -080058 const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(type_index);
59 ASSERT_THAT(type_spec, NotNull());
60 ASSERT_THAT(type_spec->type_count, Ge(1u));
Adam Lesinski7ad11102016-10-28 16:39:15 -070061
Adam Lesinski64ee69d2018-01-08 17:38:30 -080062 const ResTable_type* type = type_spec->types[0];
63 ASSERT_THAT(type, NotNull());
64 ASSERT_THAT(LoadedPackage::GetEntry(type, entry_index), NotNull());
Adam Lesinski7ad11102016-10-28 16:39:15 -070065}
66
Adam Lesinski73f6f9d2017-11-14 10:18:05 -080067TEST(LoadedArscTest, LoadSparseEntryApp) {
68 std::string contents;
69 ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/sparse/sparse.apk", "resources.arsc",
70 &contents));
71
72 std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
Adam Lesinski64ee69d2018-01-08 17:38:30 -080073 ASSERT_THAT(loaded_arsc, NotNull());
Adam Lesinski73f6f9d2017-11-14 10:18:05 -080074
Adam Lesinski64ee69d2018-01-08 17:38:30 -080075 const LoadedPackage* package =
76 loaded_arsc->GetPackageById(get_package_id(sparse::R::integer::foo_9));
77 ASSERT_THAT(package, NotNull());
Adam Lesinski73f6f9d2017-11-14 10:18:05 -080078
Adam Lesinski64ee69d2018-01-08 17:38:30 -080079 const uint8_t type_index = get_type_id(sparse::R::integer::foo_9) - 1;
80 const uint16_t entry_index = get_entry_id(sparse::R::integer::foo_9);
81
82 const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(type_index);
83 ASSERT_THAT(type_spec, NotNull());
84 ASSERT_THAT(type_spec->type_count, Ge(1u));
85
86 const ResTable_type* type = type_spec->types[0];
87 ASSERT_THAT(type, NotNull());
88 ASSERT_THAT(LoadedPackage::GetEntry(type, entry_index), NotNull());
Adam Lesinski73f6f9d2017-11-14 10:18:05 -080089}
90
Adam Lesinskida431a22016-12-29 16:08:16 -050091TEST(LoadedArscTest, LoadSharedLibrary) {
92 std::string contents;
93 ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/lib_one/lib_one.apk", "resources.arsc",
94 &contents));
95
Adam Lesinski970bd8d2017-09-25 13:21:55 -070096 std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
Adam Lesinski64ee69d2018-01-08 17:38:30 -080097 ASSERT_THAT(loaded_arsc, NotNull());
Adam Lesinskida431a22016-12-29 16:08:16 -050098
99 const auto& packages = loaded_arsc->GetPackages();
Adam Lesinski64ee69d2018-01-08 17:38:30 -0800100 ASSERT_THAT(packages, SizeIs(1u));
Adam Lesinskida431a22016-12-29 16:08:16 -0500101 EXPECT_TRUE(packages[0]->IsDynamic());
Adam Lesinski64ee69d2018-01-08 17:38:30 -0800102 EXPECT_THAT(packages[0]->GetPackageName(), StrEq("com.android.lib_one"));
103 EXPECT_THAT(packages[0]->GetPackageId(), Eq(0));
Adam Lesinskida431a22016-12-29 16:08:16 -0500104
105 const auto& dynamic_pkg_map = packages[0]->GetDynamicPackageMap();
106
107 // The library has no dependencies.
108 ASSERT_TRUE(dynamic_pkg_map.empty());
109}
110
111TEST(LoadedArscTest, LoadAppLinkedAgainstSharedLibrary) {
112 std::string contents;
113 ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/libclient/libclient.apk",
114 "resources.arsc", &contents));
115
Adam Lesinski970bd8d2017-09-25 13:21:55 -0700116 std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
Adam Lesinski64ee69d2018-01-08 17:38:30 -0800117 ASSERT_THAT(loaded_arsc, NotNull());
Adam Lesinskida431a22016-12-29 16:08:16 -0500118
119 const auto& packages = loaded_arsc->GetPackages();
Adam Lesinski64ee69d2018-01-08 17:38:30 -0800120 ASSERT_THAT(packages, SizeIs(1u));
Adam Lesinskida431a22016-12-29 16:08:16 -0500121 EXPECT_FALSE(packages[0]->IsDynamic());
Adam Lesinski64ee69d2018-01-08 17:38:30 -0800122 EXPECT_THAT(packages[0]->GetPackageName(), StrEq("com.android.libclient"));
123 EXPECT_THAT(packages[0]->GetPackageId(), Eq(0x7f));
Adam Lesinskida431a22016-12-29 16:08:16 -0500124
125 const auto& dynamic_pkg_map = packages[0]->GetDynamicPackageMap();
126
127 // The library has two dependencies.
Adam Lesinski64ee69d2018-01-08 17:38:30 -0800128 ASSERT_THAT(dynamic_pkg_map, SizeIs(2u));
129 EXPECT_THAT(dynamic_pkg_map[0].package_name, StrEq("com.android.lib_one"));
130 EXPECT_THAT(dynamic_pkg_map[0].package_id, Eq(0x02));
Adam Lesinskida431a22016-12-29 16:08:16 -0500131
Adam Lesinski64ee69d2018-01-08 17:38:30 -0800132 EXPECT_THAT(dynamic_pkg_map[1].package_name, StrEq("com.android.lib_two"));
133 EXPECT_THAT(dynamic_pkg_map[1].package_id, Eq(0x03));
Adam Lesinskida431a22016-12-29 16:08:16 -0500134}
135
136TEST(LoadedArscTest, LoadAppAsSharedLibrary) {
137 std::string contents;
138 ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/appaslib/appaslib.apk",
139 "resources.arsc", &contents));
140
Adam Lesinski970bd8d2017-09-25 13:21:55 -0700141 std::unique_ptr<const LoadedArsc> loaded_arsc =
142 LoadedArsc::Load(StringPiece(contents), nullptr /*loaded_idmap*/, false /*system*/,
143 true /*load_as_shared_library*/);
Adam Lesinski64ee69d2018-01-08 17:38:30 -0800144 ASSERT_THAT(loaded_arsc, NotNull());
Adam Lesinskida431a22016-12-29 16:08:16 -0500145
146 const auto& packages = loaded_arsc->GetPackages();
Adam Lesinski64ee69d2018-01-08 17:38:30 -0800147 ASSERT_THAT(packages, SizeIs(1u));
Adam Lesinskida431a22016-12-29 16:08:16 -0500148 EXPECT_TRUE(packages[0]->IsDynamic());
Adam Lesinski64ee69d2018-01-08 17:38:30 -0800149 EXPECT_THAT(packages[0]->GetPackageId(), Eq(0x7f));
Adam Lesinskida431a22016-12-29 16:08:16 -0500150}
151
Adam Lesinskic6aada92017-01-13 15:34:14 -0800152TEST(LoadedArscTest, LoadFeatureSplit) {
153 std::string contents;
154 ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/feature/feature.apk", "resources.arsc",
155 &contents));
Adam Lesinski970bd8d2017-09-25 13:21:55 -0700156 std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
Adam Lesinski64ee69d2018-01-08 17:38:30 -0800157 ASSERT_THAT(loaded_arsc, NotNull());
Adam Lesinskic6aada92017-01-13 15:34:14 -0800158
Adam Lesinski64ee69d2018-01-08 17:38:30 -0800159 const LoadedPackage* package =
160 loaded_arsc->GetPackageById(get_package_id(basic::R::string::test3));
161 ASSERT_THAT(package, NotNull());
Adam Lesinskic6aada92017-01-13 15:34:14 -0800162
Adam Lesinski64ee69d2018-01-08 17:38:30 -0800163 uint8_t type_index = get_type_id(basic::R::string::test3) - 1;
164 uint8_t entry_index = get_entry_id(basic::R::string::test3);
165
166 const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(type_index);
167 ASSERT_THAT(type_spec, NotNull());
168 ASSERT_THAT(type_spec->type_count, Ge(1u));
169 ASSERT_THAT(type_spec->types[0], NotNull());
Adam Lesinskic6aada92017-01-13 15:34:14 -0800170
171 size_t len;
Adam Lesinski64ee69d2018-01-08 17:38:30 -0800172 const char16_t* type_name16 =
173 package->GetTypeStringPool()->stringAt(type_spec->type_spec->id - 1, &len);
174 ASSERT_THAT(type_name16, NotNull());
175 EXPECT_THAT(util::Utf16ToUtf8(StringPiece16(type_name16, len)), StrEq("string"));
Adam Lesinskic6aada92017-01-13 15:34:14 -0800176
Adam Lesinski64ee69d2018-01-08 17:38:30 -0800177 ASSERT_THAT(LoadedPackage::GetEntry(type_spec->types[0], entry_index), NotNull());
Adam Lesinskic6aada92017-01-13 15:34:14 -0800178}
179
Adam Lesinski970bd8d2017-09-25 13:21:55 -0700180class MockLoadedIdmap : public LoadedIdmap {
181 public:
182 MockLoadedIdmap() : LoadedIdmap() {
183 local_header_.magic = kIdmapMagic;
184 local_header_.version = kIdmapCurrentVersion;
185 local_header_.target_package_id = 0x08;
186 local_header_.type_count = 1;
187 header_ = &local_header_;
188
189 entry_header = util::unique_cptr<IdmapEntry_header>(
190 (IdmapEntry_header*)::malloc(sizeof(IdmapEntry_header) + sizeof(uint32_t)));
191 entry_header->target_type_id = 0x03;
192 entry_header->overlay_type_id = 0x02;
193 entry_header->entry_id_offset = 1;
194 entry_header->entry_count = 1;
195 entry_header->entries[0] = 0x00000000u;
196 type_map_[entry_header->overlay_type_id] = entry_header.get();
197 }
198
199 private:
200 Idmap_header local_header_;
201 util::unique_cptr<IdmapEntry_header> entry_header;
202};
203
204TEST(LoadedArscTest, LoadOverlay) {
Adam Lesinski64ee69d2018-01-08 17:38:30 -0800205 std::string contents;
Adam Lesinski970bd8d2017-09-25 13:21:55 -0700206 ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/overlay/overlay.apk", "resources.arsc",
Adam Lesinski64ee69d2018-01-08 17:38:30 -0800207 &contents));
Adam Lesinski970bd8d2017-09-25 13:21:55 -0700208
209 MockLoadedIdmap loaded_idmap;
210
211 std::unique_ptr<const LoadedArsc> loaded_arsc =
Adam Lesinski64ee69d2018-01-08 17:38:30 -0800212 LoadedArsc::Load(StringPiece(contents), &loaded_idmap);
213 ASSERT_THAT(loaded_arsc, NotNull());
Adam Lesinski970bd8d2017-09-25 13:21:55 -0700214
Adam Lesinski64ee69d2018-01-08 17:38:30 -0800215 const LoadedPackage* package = loaded_arsc->GetPackageById(0x08u);
216 ASSERT_THAT(package, NotNull());
Adam Lesinski970bd8d2017-09-25 13:21:55 -0700217
Adam Lesinski64ee69d2018-01-08 17:38:30 -0800218 const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(0x03u - 1);
219 ASSERT_THAT(type_spec, NotNull());
220 ASSERT_THAT(type_spec->type_count, Ge(1u));
221 ASSERT_THAT(type_spec->types[0], NotNull());
222
223 // The entry being overlaid doesn't exist at the original entry index.
224 ASSERT_THAT(LoadedPackage::GetEntry(type_spec->types[0], 0x0001u), IsNull());
225
226 // Since this is an overlay, the actual entry ID must be mapped.
227 ASSERT_THAT(type_spec->idmap_entries, NotNull());
228 uint16_t target_entry_id = 0u;
229 ASSERT_TRUE(LoadedIdmap::Lookup(type_spec->idmap_entries, 0x0001u, &target_entry_id));
230 ASSERT_THAT(target_entry_id, Eq(0x0u));
231 ASSERT_THAT(LoadedPackage::GetEntry(type_spec->types[0], 0x0000), NotNull());
Adam Lesinski970bd8d2017-09-25 13:21:55 -0700232}
233
Adam Lesinski7ad11102016-10-28 16:39:15 -0700234// structs with size fields (like Res_value, ResTable_entry) should be
235// backwards and forwards compatible (aka checking the size field against
236// sizeof(Res_value) might not be backwards compatible.
237TEST(LoadedArscTest, LoadingShouldBeForwardsAndBackwardsCompatible) { ASSERT_TRUE(false); }
238
239} // namespace android