| /* | |
| * Copyright (C) 2018 The Android Open Source Project | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| /* | |
| * # idmap file format (current version) | |
| * | |
| * idmap := header data* | |
| * header := magic version target_crc overlay_crc fulfilled_policies | |
| * enforce_overlayable target_path overlay_path overlay_name | |
| * debug_info | |
| * data := data_header target_entry* target_inline_entry* | |
| target_inline_entry_value* config* overlay_entry* string_pool | |
| * data_header := target_entry_count target_inline_entry_count | |
| target_inline_entry_value_count config_count overlay_entry_count | |
| * string_pool_index | |
| * target_entry := target_id overlay_id | |
| * target_inline_entry := target_id start_value_index value_count | |
| * target_inline_entry_value := config_index Res_value::size padding(1) Res_value::type | |
| * Res_value::value | |
| * config := target_id Res_value::size padding(1) Res_value::type | |
| * Res_value::value | |
| * overlay_entry := overlay_id target_id | |
| * | |
| * debug_info := string | |
| * enforce_overlayable := <uint32_t> | |
| * fulfilled_policies := <uint32_t> | |
| * magic := <uint32_t> | |
| * overlay_crc := <uint32_t> | |
| * overlay_entry_count := <uint32_t> | |
| * overlay_id := <uint32_t> | |
| * overlay_package_id := <uint8_t> | |
| * overlay_name := string | |
| * overlay_path := string | |
| * padding(n) := <uint8_t>[n] | |
| * Res_value::size := <uint16_t> | |
| * Res_value::type := <uint8_t> | |
| * Res_value::value := <uint32_t> | |
| * string := <uint32_t> <uint8_t>+ padding(n) | |
| * string_pool := string | |
| * string_pool_index := <uint32_t> | |
| * string_pool_length := <uint32_t> | |
| * target_crc := <uint32_t> | |
| * target_entry_count := <uint32_t> | |
| * target_inline_entry_count := <uint32_t> | |
| * target_inline_entry_value_count := <uint32_t> | |
| * config_count := <uint32_t> | |
| * config_index := <uint32_t> | |
| * start_value_index := <uint32_t> | |
| * value_count := <uint32_t> | |
| * target_id := <uint32_t> | |
| * target_package_id := <uint8_t> | |
| * target_path := string | |
| * value_type := <uint8_t> | |
| * value_data := <uint32_t> | |
| * version := <uint32_t> | |
| */ | |
| #ifndef IDMAP2_INCLUDE_IDMAP2_IDMAP_H_ | |
| #define IDMAP2_INCLUDE_IDMAP2_IDMAP_H_ | |
| #include <istream> | |
| #include <memory> | |
| #include <string> | |
| #include <string_view> | |
| #include <vector> | |
| #include "android-base/macros.h" | |
| #include "androidfw/ResourceTypes.h" | |
| #include "androidfw/StringPiece.h" | |
| #include "androidfw/ConfigDescription.h" | |
| #include "idmap2/ResourceContainer.h" | |
| #include "idmap2/ResourceMapping.h" | |
| namespace android::idmap2 { | |
| class Idmap; | |
| class Visitor; | |
| // magic number: all idmap files start with this | |
| static constexpr const uint32_t kIdmapMagic = android::kIdmapMagic; | |
| // current version of the idmap binary format; must be incremented when the format is changed | |
| static constexpr const uint32_t kIdmapCurrentVersion = android::kIdmapCurrentVersion; | |
| class IdmapHeader { | |
| public: | |
| static std::unique_ptr<const IdmapHeader> FromBinaryStream(std::istream& stream); | |
| inline uint32_t GetMagic() const { | |
| return magic_; | |
| } | |
| inline uint32_t GetVersion() const { | |
| return version_; | |
| } | |
| inline uint32_t GetTargetCrc() const { | |
| return target_crc_; | |
| } | |
| inline uint32_t GetOverlayCrc() const { | |
| return overlay_crc_; | |
| } | |
| inline uint32_t GetFulfilledPolicies() const { | |
| return fulfilled_policies_; | |
| } | |
| bool GetEnforceOverlayable() const { | |
| return enforce_overlayable_; | |
| } | |
| const std::string& GetTargetPath() const { | |
| return target_path_; | |
| } | |
| const std::string& GetOverlayPath() const { | |
| return overlay_path_; | |
| } | |
| const std::string& GetOverlayName() const { | |
| return overlay_name_; | |
| } | |
| const std::string& GetDebugInfo() const { | |
| return debug_info_; | |
| } | |
| // Invariant: anytime the idmap data encoding is changed, the idmap version | |
| // field *must* be incremented. Because of this, we know that if the idmap | |
| // header is up-to-date the entire file is up-to-date. | |
| Result<Unit> IsUpToDate(const TargetResourceContainer& target, | |
| const OverlayResourceContainer& overlay, const std::string& overlay_name, | |
| PolicyBitmask fulfilled_policies, bool enforce_overlayable) const; | |
| Result<Unit> IsUpToDate(const std::string& target_path, const std::string& overlay_path, | |
| const std::string& overlay_name, uint32_t target_crc, | |
| uint32_t overlay_crc, PolicyBitmask fulfilled_policies, | |
| bool enforce_overlayable) const; | |
| void accept(Visitor* v) const; | |
| private: | |
| IdmapHeader() = default; | |
| uint32_t magic_; | |
| uint32_t version_; | |
| uint32_t target_crc_; | |
| uint32_t overlay_crc_; | |
| uint32_t fulfilled_policies_; | |
| bool enforce_overlayable_; | |
| std::string target_path_; | |
| std::string overlay_path_; | |
| std::string overlay_name_; | |
| std::string debug_info_; | |
| friend Idmap; | |
| DISALLOW_COPY_AND_ASSIGN(IdmapHeader); | |
| }; | |
| class IdmapData { | |
| public: | |
| class Header { | |
| public: | |
| static std::unique_ptr<const Header> FromBinaryStream(std::istream& stream); | |
| [[nodiscard]] inline uint32_t GetTargetEntryCount() const { | |
| return target_entry_count; | |
| } | |
| [[nodiscard]] inline uint32_t GetTargetInlineEntryCount() const { | |
| return target_entry_inline_count; | |
| } | |
| [[nodiscard]] inline uint32_t GetTargetInlineEntryValueCount() const { | |
| return target_entry_inline_value_count; | |
| } | |
| [[nodiscard]] inline uint32_t GetConfigCount() const { | |
| return config_count; | |
| } | |
| [[nodiscard]] inline uint32_t GetOverlayEntryCount() const { | |
| return overlay_entry_count; | |
| } | |
| [[nodiscard]] inline uint32_t GetStringPoolIndexOffset() const { | |
| return string_pool_index_offset; | |
| } | |
| void accept(Visitor* v) const; | |
| private: | |
| uint32_t target_entry_count; | |
| uint32_t target_entry_inline_count; | |
| uint32_t target_entry_inline_value_count; | |
| uint32_t config_count; | |
| uint32_t overlay_entry_count; | |
| uint32_t string_pool_index_offset; | |
| Header() = default; | |
| friend Idmap; | |
| friend IdmapData; | |
| DISALLOW_COPY_AND_ASSIGN(Header); | |
| }; | |
| struct TargetEntry { | |
| ResourceId target_id; | |
| ResourceId overlay_id; | |
| }; | |
| struct TargetInlineEntry { | |
| ResourceId target_id; | |
| std::map<ConfigDescription, TargetValue> values; | |
| }; | |
| struct OverlayEntry { | |
| ResourceId overlay_id; | |
| ResourceId target_id; | |
| }; | |
| static std::unique_ptr<const IdmapData> FromBinaryStream(std::istream& stream); | |
| static Result<std::unique_ptr<const IdmapData>> FromResourceMapping( | |
| const ResourceMapping& resource_mapping); | |
| const std::unique_ptr<const Header>& GetHeader() const { | |
| return header_; | |
| } | |
| const std::vector<TargetEntry>& GetTargetEntries() const { | |
| return target_entries_; | |
| } | |
| const std::vector<TargetInlineEntry>& GetTargetInlineEntries() const { | |
| return target_inline_entries_; | |
| } | |
| [[nodiscard]] const std::vector<OverlayEntry>& GetOverlayEntries() const { | |
| return overlay_entries_; | |
| } | |
| [[nodiscard]] const std::string& GetStringPoolData() const { | |
| return string_pool_data_; | |
| } | |
| void accept(Visitor* v) const; | |
| private: | |
| IdmapData() = default; | |
| std::unique_ptr<const Header> header_; | |
| std::vector<TargetEntry> target_entries_; | |
| std::vector<TargetInlineEntry> target_inline_entries_; | |
| std::vector<OverlayEntry> overlay_entries_; | |
| std::string string_pool_data_; | |
| friend Idmap; | |
| DISALLOW_COPY_AND_ASSIGN(IdmapData); | |
| }; | |
| class Idmap { | |
| public: | |
| static std::string CanonicalIdmapPathFor(std::string_view absolute_dir, | |
| std::string_view absolute_apk_path); | |
| static Result<std::unique_ptr<const Idmap>> FromBinaryStream(std::istream& stream); | |
| // In the current version of idmap, the first package in each resources.arsc | |
| // file is used; change this in the next version of idmap to use a named | |
| // package instead; also update FromApkAssets to take additional parameters: | |
| // the target and overlay package names | |
| static Result<std::unique_ptr<const Idmap>> FromContainers( | |
| const TargetResourceContainer& target, const OverlayResourceContainer& overlay, | |
| const std::string& overlay_name, const PolicyBitmask& fulfilled_policies, | |
| bool enforce_overlayable); | |
| const std::unique_ptr<const IdmapHeader>& GetHeader() const { | |
| return header_; | |
| } | |
| const std::vector<std::unique_ptr<const IdmapData>>& GetData() const { | |
| return data_; | |
| } | |
| void accept(Visitor* v) const; | |
| private: | |
| Idmap() = default; | |
| std::unique_ptr<const IdmapHeader> header_; | |
| std::vector<std::unique_ptr<const IdmapData>> data_; | |
| DISALLOW_COPY_AND_ASSIGN(Idmap); | |
| }; | |
| class Visitor { | |
| public: | |
| virtual ~Visitor() = default; | |
| virtual void visit(const Idmap& idmap) = 0; | |
| virtual void visit(const IdmapHeader& header) = 0; | |
| virtual void visit(const IdmapData& data) = 0; | |
| virtual void visit(const IdmapData::Header& header) = 0; | |
| }; | |
| inline size_t CalculatePadding(size_t data_length) { | |
| return (4 - (data_length % 4)) % 4; | |
| } | |
| } // namespace android::idmap2 | |
| #endif // IDMAP2_INCLUDE_IDMAP2_IDMAP_H_ |