blob: 8d1de1af56d2a9c3c2b290733e3882dca6ed8c67 [file] [log] [blame]
Adam Lesinski970bd8d2017-09-25 13:21:55 -07001/*
2 * Copyright (C) 2017 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#define ATRACE_TAG ATRACE_TAG_RESOURCES
18
19#include "androidfw/Idmap.h"
20
Yurii Zubrytskyie7c1f002024-01-30 13:50:57 -080021#include "android-base/file.h"
Adam Lesinski970bd8d2017-09-25 13:21:55 -070022#include "android-base/logging.h"
23#include "android-base/stringprintf.h"
Yurii Zubrytskyie7c1f002024-01-30 13:50:57 -080024#include "android-base/utf8.h"
Yurii Zubrytskyi548c1ab2025-02-06 15:41:54 -080025#include "androidfw/AssetManager.h"
Ryan Mitchell8a891d82019-07-01 09:48:23 -070026#include "androidfw/ResourceTypes.h"
27#include "androidfw/Util.h"
Yurii Zubrytskyi548c1ab2025-02-06 15:41:54 -080028#include "androidfw/misc.h"
Adam Lesinski970bd8d2017-09-25 13:21:55 -070029#include "utils/ByteOrder.h"
30#include "utils/Trace.h"
31
32#ifdef _WIN32
33#ifdef ERROR
34#undef ERROR
35#endif
36#endif
37
Adam Lesinski970bd8d2017-09-25 13:21:55 -070038using ::android::base::StringPrintf;
39
40namespace android {
41
Ryan Mitchell0699f1d2020-12-03 15:41:42 -080042// See frameworks/base/cmds/idmap2/include/idmap2/Idmap.h for full idmap file format specification.
43struct Idmap_header {
44 // Always 0x504D4449 ('IDMP')
45 uint32_t magic;
46 uint32_t version;
Adam Lesinski970bd8d2017-09-25 13:21:55 -070047
Ryan Mitchell0699f1d2020-12-03 15:41:42 -080048 uint32_t target_crc32;
49 uint32_t overlay_crc32;
50
51 uint32_t fulfilled_policies;
52 uint32_t enforce_overlayable;
53
54 // overlay_path, target_path, and other string values encoded in the idmap header and read and
55 // stored in separate structures. This allows the idmap header data to be casted to this struct
56 // without having to read/store each header entry separately.
57};
58
59struct Idmap_data_header {
Ryan Mitchell0699f1d2020-12-03 15:41:42 -080060 uint32_t target_entry_count;
61 uint32_t target_inline_entry_count;
Jeremy Meyerbe2b7792022-08-23 17:42:50 +000062 uint32_t target_inline_entry_value_count;
63 uint32_t configuration_count;
Ryan Mitchell0699f1d2020-12-03 15:41:42 -080064 uint32_t overlay_entry_count;
65
66 uint32_t string_pool_index_offset;
67};
68
Ryan Mitchell0699f1d2020-12-03 15:41:42 -080069struct Idmap_target_entry_inline {
Jeremy Meyerbe2b7792022-08-23 17:42:50 +000070 uint32_t start_value_index;
71 uint32_t value_count;
72};
73
74struct Idmap_target_entry_inline_value {
75 uint32_t config_index;
Ryan Mitchell0699f1d2020-12-03 15:41:42 -080076 Res_value value;
77};
78
Yurii Zubrytskyid67e90e2024-08-30 17:39:56 -070079static constexpr uint32_t convert_dev_target_id(uint32_t dev_target_id) {
80 return (0x00FFFFFFU & dtohl(dev_target_id));
81}
MÃ¥rten Kongstadd7e8a532019-10-11 08:32:04 +020082
Ryan Mitchell8a891d82019-07-01 09:48:23 -070083OverlayStringPool::OverlayStringPool(const LoadedIdmap* loaded_idmap)
Ryan Mitchell73bfe412019-11-12 16:22:04 -080084 : data_header_(loaded_idmap->data_header_),
85 idmap_string_pool_(loaded_idmap->string_pool_.get()) { };
Ryan Mitchell8a891d82019-07-01 09:48:23 -070086
87OverlayStringPool::~OverlayStringPool() {
88 uninit();
89}
90
Ryan Mitchelldb21f09a2020-11-16 23:08:18 +000091base::expected<StringPiece16, NullOrIOError> OverlayStringPool::stringAt(size_t idx) const {
Ryan Mitchell8a891d82019-07-01 09:48:23 -070092 const size_t offset = dtohl(data_header_->string_pool_index_offset);
Ryan Mitchelldf9e7322019-12-12 10:23:54 -080093 if (idmap_string_pool_ != nullptr && idx >= ResStringPool::size() && idx >= offset) {
Ryan Mitchelldb21f09a2020-11-16 23:08:18 +000094 return idmap_string_pool_->stringAt(idx - offset);
Adam Lesinski970bd8d2017-09-25 13:21:55 -070095 }
96
Ryan Mitchelldb21f09a2020-11-16 23:08:18 +000097 return ResStringPool::stringAt(idx);
Ryan Mitchell8a891d82019-07-01 09:48:23 -070098}
99
Ryan Mitchelldb21f09a2020-11-16 23:08:18 +0000100base::expected<StringPiece, NullOrIOError> OverlayStringPool::string8At(size_t idx) const {
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700101 const size_t offset = dtohl(data_header_->string_pool_index_offset);
Ryan Mitchelldf9e7322019-12-12 10:23:54 -0800102 if (idmap_string_pool_ != nullptr && idx >= ResStringPool::size() && idx >= offset) {
Ryan Mitchelldb21f09a2020-11-16 23:08:18 +0000103 return idmap_string_pool_->string8At(idx - offset);
Adam Lesinski970bd8d2017-09-25 13:21:55 -0700104 }
105
Ryan Mitchelldb21f09a2020-11-16 23:08:18 +0000106 return ResStringPool::string8At(idx);
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700107}
108
Ryan Mitchelldf9e7322019-12-12 10:23:54 -0800109size_t OverlayStringPool::size() const {
110 return ResStringPool::size() + (idmap_string_pool_ != nullptr ? idmap_string_pool_->size() : 0U);
111}
112
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700113OverlayDynamicRefTable::OverlayDynamicRefTable(const Idmap_data_header* data_header,
Yurii Zubrytskyid67e90e2024-08-30 17:39:56 -0700114 Idmap_overlay_entries entries,
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700115 uint8_t target_assigned_package_id)
116 : data_header_(data_header),
117 entries_(entries),
Yurii Zubrytskyid67e90e2024-08-30 17:39:56 -0700118 target_assigned_package_id_(target_assigned_package_id) {
119}
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700120
121status_t OverlayDynamicRefTable::lookupResourceId(uint32_t* resId) const {
Yurii Zubrytskyid67e90e2024-08-30 17:39:56 -0700122 const auto count = dtohl(data_header_->overlay_entry_count);
123 const auto overlay_it_end = entries_.overlay_id + count;
124 const auto entry_it = std::lower_bound(entries_.overlay_id, overlay_it_end, *resId,
125 [](uint32_t dev_overlay_id, uint32_t overlay_id) {
126 return dtohl(dev_overlay_id) < overlay_id;
127 });
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700128
Yurii Zubrytskyid67e90e2024-08-30 17:39:56 -0700129 if (entry_it == overlay_it_end || dtohl(*entry_it) != *resId) {
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700130 // A mapping for the target resource id could not be found.
131 return DynamicRefTable::lookupResourceId(resId);
Adam Lesinski970bd8d2017-09-25 13:21:55 -0700132 }
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700133
Yurii Zubrytskyid67e90e2024-08-30 17:39:56 -0700134 const auto index = entry_it - entries_.overlay_id;
135 *resId = convert_dev_target_id(entries_.target_id[index]) |
136 (((uint32_t)target_assigned_package_id_) << 24U);
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700137 return NO_ERROR;
138}
139
140status_t OverlayDynamicRefTable::lookupResourceIdNoRewrite(uint32_t* resId) const {
141 return DynamicRefTable::lookupResourceId(resId);
142}
143
Biswarup Palbc306b42025-02-06 23:31:30 +0000144IdmapResMap::IdmapResMap(const Idmap_data_header* data_header, const Idmap_constraints& constraints,
145 Idmap_target_entries entries, Idmap_target_inline_entries inline_entries,
Jeremy Meyerbe2b7792022-08-23 17:42:50 +0000146 const Idmap_target_entry_inline_value* inline_entry_values,
Yurii Zubrytskyid67e90e2024-08-30 17:39:56 -0700147 const ConfigDescription* configs, uint8_t target_assigned_package_id,
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700148 const OverlayDynamicRefTable* overlay_ref_table)
149 : data_header_(data_header),
Biswarup Palbc306b42025-02-06 23:31:30 +0000150 constraints_(constraints),
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700151 entries_(entries),
Ryan Mitchellbf1f45b2020-09-29 17:22:52 -0700152 inline_entries_(inline_entries),
Jeremy Meyerbe2b7792022-08-23 17:42:50 +0000153 inline_entry_values_(inline_entry_values),
154 configurations_(configs),
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700155 target_assigned_package_id_(target_assigned_package_id),
Yurii Zubrytskyid67e90e2024-08-30 17:39:56 -0700156 overlay_ref_table_(overlay_ref_table) {
157}
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700158
159IdmapResMap::Result IdmapResMap::Lookup(uint32_t target_res_id) const {
Ryan Mitchellbf1f45b2020-09-29 17:22:52 -0700160 if ((target_res_id >> 24U) != target_assigned_package_id_) {
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700161 // The resource id must have the same package id as the target package.
162 return {};
163 }
164
Ryan Mitchell2ed8bfa2021-01-08 13:34:28 -0800165 // The resource ids encoded within the idmap are build-time resource ids so do not consider the
166 // package id when determining if the resource in the target package is overlaid.
167 target_res_id &= 0x00FFFFFFU;
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700168
Ryan Mitchellbf1f45b2020-09-29 17:22:52 -0700169 // Check if the target resource is mapped to an overlay resource.
Yurii Zubrytskyid67e90e2024-08-30 17:39:56 -0700170 const auto target_end = entries_.target_id + dtohl(data_header_->target_entry_count);
171 auto target_it = std::lower_bound(entries_.target_id, target_end, target_res_id,
172 [](uint32_t dev_target_id, uint32_t target_id) {
173 return convert_dev_target_id(dev_target_id) < target_id;
174 });
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700175
Yurii Zubrytskyid67e90e2024-08-30 17:39:56 -0700176 if (target_it != target_end && convert_dev_target_id(*target_it) == target_res_id) {
177 const auto index = target_it - entries_.target_id;
178 uint32_t overlay_resource_id = dtohl(entries_.overlay_id[index]);
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700179 // Lookup the resource without rewriting the overlay resource id back to the target resource id
180 // being looked up.
181 overlay_ref_table_->lookupResourceIdNoRewrite(&overlay_resource_id);
182 return Result(overlay_resource_id);
183 }
184
Ryan Mitchellbf1f45b2020-09-29 17:22:52 -0700185 // Check if the target resources is mapped to an inline table entry.
Yurii Zubrytskyid67e90e2024-08-30 17:39:56 -0700186 const auto inline_entry_target_end =
187 inline_entries_.target_id + dtohl(data_header_->target_inline_entry_count);
188 const auto inline_entry_target_it =
189 std::lower_bound(inline_entries_.target_id, inline_entry_target_end, target_res_id,
190 [](uint32_t dev_target_id, uint32_t target_id) {
191 return convert_dev_target_id(dev_target_id) < target_id;
192 });
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700193
Yurii Zubrytskyid67e90e2024-08-30 17:39:56 -0700194 if (inline_entry_target_it != inline_entry_target_end &&
195 convert_dev_target_id(*inline_entry_target_it) == target_res_id) {
196 const auto index = inline_entry_target_it - inline_entries_.target_id;
Jeremy Meyerbe2b7792022-08-23 17:42:50 +0000197 std::map<ConfigDescription, Res_value> values_map;
Yurii Zubrytskyid67e90e2024-08-30 17:39:56 -0700198 const auto& inline_entry = inline_entries_.entry[index];
199 for (int i = 0; i < dtohl(inline_entry.value_count); i++) {
200 const auto& value = inline_entry_values_[dtohl(inline_entry.start_value_index) + i];
201 const auto& config = configurations_[dtohl(value.config_index)];
Jeremy Meyerbe2b7792022-08-23 17:42:50 +0000202 values_map[config] = value.value;
203 }
Yurii Zubrytskyia5bc9582022-11-30 23:53:59 -0800204 return Result(std::move(values_map));
Ryan Mitchellbf1f45b2020-09-29 17:22:52 -0700205 }
206 return {};
Adam Lesinski970bd8d2017-09-25 13:21:55 -0700207}
208
Ryan Mitchell0699f1d2020-12-03 15:41:42 -0800209namespace {
210template <typename T>
Yurii Zubrytskyid67e90e2024-08-30 17:39:56 -0700211const T* ReadType(const uint8_t** in_out_data_ptr, size_t* in_out_size, const char* label,
Ryan Mitchell0699f1d2020-12-03 15:41:42 -0800212 size_t count = 1) {
213 if (!util::IsFourByteAligned(*in_out_data_ptr)) {
Yurii Zubrytskyid67e90e2024-08-30 17:39:56 -0700214 LOG(ERROR) << "Idmap " << label << " in " << __func__ << " is not word aligned.";
Ryan Mitchell0699f1d2020-12-03 15:41:42 -0800215 return {};
216 }
217 if ((*in_out_size / sizeof(T)) < count) {
Yurii Zubrytskyid67e90e2024-08-30 17:39:56 -0700218 LOG(ERROR) << "Idmap too small for the number of " << label << " in " << __func__
219 << " entries (" << count << ").";
Ryan Mitchell0699f1d2020-12-03 15:41:42 -0800220 return nullptr;
221 }
222 auto data_ptr = *in_out_data_ptr;
223 const size_t read_size = sizeof(T) * count;
224 *in_out_data_ptr += read_size;
225 *in_out_size -= read_size;
226 return reinterpret_cast<const T*>(data_ptr);
Adam Lesinski970bd8d2017-09-25 13:21:55 -0700227}
228
Ryan Mitchell0699f1d2020-12-03 15:41:42 -0800229std::optional<std::string_view> ReadString(const uint8_t** in_out_data_ptr, size_t* in_out_size,
Yurii Zubrytskyid67e90e2024-08-30 17:39:56 -0700230 const char* label) {
231 const auto* len = ReadType<uint32_t>(in_out_data_ptr, in_out_size, label);
Ryan Mitchell0699f1d2020-12-03 15:41:42 -0800232 if (len == nullptr) {
233 return {};
Adam Lesinski970bd8d2017-09-25 13:21:55 -0700234 }
Ryan Mitchell0699f1d2020-12-03 15:41:42 -0800235 const auto* data = ReadType<char>(in_out_data_ptr, in_out_size, label, *len);
236 if (data == nullptr) {
237 return {};
Adam Lesinski970bd8d2017-09-25 13:21:55 -0700238 }
Ryan Mitchell0699f1d2020-12-03 15:41:42 -0800239 // Strings are padded to the next 4 byte boundary.
240 const uint32_t padding_size = (4U - ((size_t)*in_out_data_ptr & 0x3U)) % 4U;
241 for (uint32_t i = 0; i < padding_size; i++) {
242 if (**in_out_data_ptr != 0) {
Yurii Zubrytskyid67e90e2024-08-30 17:39:56 -0700243 LOG(ERROR) << " Idmap padding of " << label << " in " << __func__ << " is non-zero.";
Ryan Mitchell0699f1d2020-12-03 15:41:42 -0800244 return {};
245 }
246 *in_out_data_ptr += sizeof(uint8_t);
247 *in_out_size -= sizeof(uint8_t);
Adam Lesinski970bd8d2017-09-25 13:21:55 -0700248 }
Ryan Mitchell0699f1d2020-12-03 15:41:42 -0800249 return std::string_view(data, *len);
250}
Biswarup Palbc306b42025-02-06 23:31:30 +0000251} // namespace
Adam Lesinski970bd8d2017-09-25 13:21:55 -0700252
Yurii Zubrytskyie7c1f002024-01-30 13:50:57 -0800253// O_PATH is a lightweight way of creating an FD, only exists on Linux
254#ifndef O_PATH
255#define O_PATH (0)
256#endif
257
258LoadedIdmap::LoadedIdmap(const std::string& idmap_path, const Idmap_header* header,
Biswarup Palbc306b42025-02-06 23:31:30 +0000259 const Idmap_data_header* data_header, const Idmap_constraints& constraints,
Biswarup Palb1608a92025-01-31 13:09:44 +0000260 Idmap_target_entries target_entries,
Yurii Zubrytskyid67e90e2024-08-30 17:39:56 -0700261 Idmap_target_inline_entries target_inline_entries,
Jeremy Meyerbe2b7792022-08-23 17:42:50 +0000262 const Idmap_target_entry_inline_value* inline_entry_values,
Yurii Zubrytskyid67e90e2024-08-30 17:39:56 -0700263 const ConfigDescription* configs, Idmap_overlay_entries overlay_entries,
Ryan Mitchell0699f1d2020-12-03 15:41:42 -0800264 std::unique_ptr<ResStringPool>&& string_pool,
Yurii Zubrytskyia5bc9582022-11-30 23:53:59 -0800265 std::string_view overlay_apk_path, std::string_view target_apk_path)
266 : header_(header),
267 data_header_(data_header),
Biswarup Palbc306b42025-02-06 23:31:30 +0000268 constraints_(constraints),
Yurii Zubrytskyia5bc9582022-11-30 23:53:59 -0800269 target_entries_(target_entries),
270 target_inline_entries_(target_inline_entries),
271 inline_entry_values_(inline_entry_values),
272 configurations_(configs),
273 overlay_entries_(overlay_entries),
274 string_pool_(std::move(string_pool)),
Yurii Zubrytskyia5bc9582022-11-30 23:53:59 -0800275 overlay_apk_path_(overlay_apk_path),
276 target_apk_path_(target_apk_path),
Yurii Zubrytskyi548c1ab2025-02-06 15:41:54 -0800277 idmap_last_mod_time_(kInvalidModDate) {
278 if (!isReadonlyFilesystem(std::string(overlay_apk_path_).c_str()) ||
279 !(target_apk_path_ == AssetManager::TARGET_APK_PATH ||
280 isReadonlyFilesystem(std::string(target_apk_path_).c_str()))) {
281 idmap_fd_.reset(
282 android::base::utf8::open(idmap_path.c_str(), O_RDONLY | O_CLOEXEC | O_BINARY | O_PATH));
283 idmap_last_mod_time_ = getFileModDate(idmap_fd_);
284 }
Yurii Zubrytskyid67e90e2024-08-30 17:39:56 -0700285}
Adam Lesinski970bd8d2017-09-25 13:21:55 -0700286
Yurii Zubrytskyia5775142022-11-02 17:49:49 -0700287std::unique_ptr<LoadedIdmap> LoadedIdmap::Load(StringPiece idmap_path, StringPiece idmap_data) {
Adam Lesinski970bd8d2017-09-25 13:21:55 -0700288 ATRACE_CALL();
Ryan Mitchell0699f1d2020-12-03 15:41:42 -0800289 size_t data_size = idmap_data.size();
290 auto data_ptr = reinterpret_cast<const uint8_t*>(idmap_data.data());
291
292 // Parse the idmap header
293 auto header = ReadType<Idmap_header>(&data_ptr, &data_size, "header");
294 if (header == nullptr) {
295 return {};
296 }
297 if (dtohl(header->magic) != kIdmapMagic) {
298 LOG(ERROR) << StringPrintf("Invalid Idmap file: bad magic value (was 0x%08x, expected 0x%08x)",
299 dtohl(header->magic), kIdmapMagic);
300 return {};
301 }
302 if (dtohl(header->version) != kIdmapCurrentVersion) {
303 // We are strict about versions because files with this format are generated at runtime and
304 // don't need backwards compatibility.
305 LOG(ERROR) << StringPrintf("Version mismatch in Idmap (was 0x%08x, expected 0x%08x)",
306 dtohl(header->version), kIdmapCurrentVersion);
307 return {};
308 }
Brandon Liu9e93ae42023-03-23 00:16:19 +0000309 std::optional<std::string_view> target_path = ReadString(&data_ptr, &data_size, "target path");
Biswarup Palb1608a92025-01-31 13:09:44 +0000310 if (!target_path) {
311 return {};
312 }
Ryan Mitchell0699f1d2020-12-03 15:41:42 -0800313 std::optional<std::string_view> overlay_path = ReadString(&data_ptr, &data_size, "overlay path");
314 if (!overlay_path) {
315 return {};
316 }
Ryan Mitchell30dc2e02020-12-02 11:43:18 -0800317 if (!ReadString(&data_ptr, &data_size, "target name") ||
318 !ReadString(&data_ptr, &data_size, "debug info")) {
Adam Lesinski970bd8d2017-09-25 13:21:55 -0700319 return {};
320 }
321
Biswarup Palbc306b42025-02-06 23:31:30 +0000322 auto constraint_count = ReadType<uint32_t>(&data_ptr, &data_size, "constraint count");
323 if (!constraint_count) {
324 LOG(ERROR) << "idmap doesn't have constraint count";
Biswarup Palb1608a92025-01-31 13:09:44 +0000325 return {};
326 }
Biswarup Palbc306b42025-02-06 23:31:30 +0000327 auto constraint_entries = *constraint_count > 0 ?
328 ReadType<Idmap_constraint>(&data_ptr, &data_size, "constraints", dtohl(*constraint_count))
Biswarup Palb1608a92025-01-31 13:09:44 +0000329 : nullptr;
Biswarup Palbc306b42025-02-06 23:31:30 +0000330 if (*constraint_count > 0 && !constraint_entries) {
331 LOG(ERROR) << "no constraint entries in idmap with non-zero constraints";
Biswarup Palb1608a92025-01-31 13:09:44 +0000332 return {};
333 }
Biswarup Palbc306b42025-02-06 23:31:30 +0000334 Idmap_constraints constraints{.constraint_count = *constraint_count,
335 .constraint_entries = constraint_entries};
Biswarup Palb1608a92025-01-31 13:09:44 +0000336
Ryan Mitchell0699f1d2020-12-03 15:41:42 -0800337 // Parse the idmap data blocks. Currently idmap2 can only generate one data block.
338 auto data_header = ReadType<Idmap_data_header>(&data_ptr, &data_size, "data header");
339 if (data_header == nullptr) {
Adam Lesinski970bd8d2017-09-25 13:21:55 -0700340 return {};
341 }
Yurii Zubrytskyid67e90e2024-08-30 17:39:56 -0700342 Idmap_target_entries target_entries{
343 .target_id = ReadType<uint32_t>(&data_ptr, &data_size, "entries.target_id",
344 dtohl(data_header->target_entry_count)),
345 .overlay_id = ReadType<uint32_t>(&data_ptr, &data_size, "entries.overlay_id",
346 dtohl(data_header->target_entry_count)),
347 };
348 if (!target_entries.target_id || !target_entries.overlay_id) {
Ryan Mitchellbf1f45b2020-09-29 17:22:52 -0700349 return {};
350 }
Yurii Zubrytskyid67e90e2024-08-30 17:39:56 -0700351 Idmap_target_inline_entries target_inline_entries{
352 .target_id = ReadType<uint32_t>(&data_ptr, &data_size, "target inline.target_id",
353 dtohl(data_header->target_inline_entry_count)),
354 .entry = ReadType<Idmap_target_entry_inline>(&data_ptr, &data_size, "target inline.entry",
355 dtohl(data_header->target_inline_entry_count))};
356 if (!target_inline_entries.target_id || !target_inline_entries.entry) {
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700357 return {};
Adam Lesinski970bd8d2017-09-25 13:21:55 -0700358 }
Jeremy Meyerbe2b7792022-08-23 17:42:50 +0000359
360 auto target_inline_entry_values = ReadType<Idmap_target_entry_inline_value>(
361 &data_ptr, &data_size, "target inline values",
362 dtohl(data_header->target_inline_entry_value_count));
363 if (target_inline_entry_values == nullptr) {
364 return {};
365 }
366
367 auto configurations = ReadType<ConfigDescription>(
368 &data_ptr, &data_size, "configurations",
369 dtohl(data_header->configuration_count));
370 if (configurations == nullptr) {
371 return {};
372 }
373
Yurii Zubrytskyid67e90e2024-08-30 17:39:56 -0700374 Idmap_overlay_entries overlay_entries{
375 .overlay_id = ReadType<uint32_t>(&data_ptr, &data_size, "overlay entries.overlay_id",
376 dtohl(data_header->overlay_entry_count)),
377 .target_id = ReadType<uint32_t>(&data_ptr, &data_size, "overlay entries.target_id",
378 dtohl(data_header->overlay_entry_count)),
379 };
380 if (!overlay_entries.overlay_id || !overlay_entries.target_id) {
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700381 return {};
382 }
Ryan Mitchell0699f1d2020-12-03 15:41:42 -0800383 std::optional<std::string_view> string_pool = ReadString(&data_ptr, &data_size, "string pool");
384 if (!string_pool) {
385 return {};
386 }
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700387 auto idmap_string_pool = util::make_unique<ResStringPool>();
Ryan Mitchell0699f1d2020-12-03 15:41:42 -0800388 if (!string_pool->empty()) {
389 const status_t err = idmap_string_pool->setTo(string_pool->data(), string_pool->size());
Ryan Mitchell8a891d82019-07-01 09:48:23 -0700390 if (err != NO_ERROR) {
391 LOG(ERROR) << "idmap string pool corrupt.";
392 return {};
393 }
394 }
395
Ryan Mitchell831b0722021-01-13 10:11:18 -0800396 if (data_size != 0) {
397 LOG(ERROR) << "idmap parsed with " << data_size << "bytes remaining";
398 return {};
399 }
400
Ryan Mitchell73bfe412019-11-12 16:22:04 -0800401 // Can't use make_unique because LoadedIdmap constructor is private.
Ryan Mitchell0699f1d2020-12-03 15:41:42 -0800402 return std::unique_ptr<LoadedIdmap>(
Biswarup Palbc306b42025-02-06 23:31:30 +0000403 new LoadedIdmap(std::string(idmap_path), header, data_header, constraints, target_entries,
404 target_inline_entries, target_inline_entry_values, configurations,
405 overlay_entries, std::move(idmap_string_pool), *overlay_path, *target_path));
Adam Lesinski970bd8d2017-09-25 13:21:55 -0700406}
407
Yurii Zubrytskyi548c1ab2025-02-06 15:41:54 -0800408UpToDate LoadedIdmap::IsUpToDate() const {
409 if (idmap_last_mod_time_ == kInvalidModDate) {
410 return UpToDate::Always;
411 }
412 return fromBool(idmap_last_mod_time_ == getFileModDate(idmap_fd_.get()));
Ryan Mitchella9093052020-03-26 17:15:01 -0700413}
414
Adam Lesinski970bd8d2017-09-25 13:21:55 -0700415} // namespace android