1 /*
2  * Copyright (C) 2019 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 #ifndef IDMAP2_INCLUDE_IDMAP2_RESOURCEMAPPING_H_
18 #define IDMAP2_INCLUDE_IDMAP2_RESOURCEMAPPING_H_
19 
20 #include <map>
21 #include <memory>
22 #include <utility>
23 
24 #include "androidfw/ApkAssets.h"
25 #include "idmap2/LogInfo.h"
26 #include "idmap2/Policies.h"
27 #include "idmap2/ResourceUtils.h"
28 #include "idmap2/Result.h"
29 #include "idmap2/XmlParser.h"
30 
31 using android::idmap2::utils::OverlayManifestInfo;
32 
33 using PolicyBitmask = android::ResTable_overlayable_policy_header::PolicyBitmask;
34 
35 namespace android::idmap2 {
36 
37 struct TargetValue {
38   typedef uint8_t DataType;
39   typedef uint32_t DataValue;
40   DataType data_type;
41   DataValue data_value;
42 };
43 
44 using TargetResourceMap = std::map<ResourceId, TargetValue>;
45 using OverlayResourceMap = std::map<ResourceId, ResourceId>;
46 
47 class ResourceMapping {
48  public:
49   // Creates a ResourceMapping using the target and overlay APKs. Setting enforce_overlayable to
50   // `false` disables all overlayable and policy enforcement: this is intended for backwards
51   // compatibility pre-Q and unit tests.
52   static Result<ResourceMapping> FromApkAssets(const ApkAssets& target_apk_assets,
53                                                const ApkAssets& overlay_apk_assets,
54                                                const OverlayManifestInfo& overlay_info,
55                                                const PolicyBitmask& fulfilled_policies,
56                                                bool enforce_overlayable, LogInfo& log_info);
57 
58   // Retrieves the mapping of target resource id to overlay value.
GetTargetToOverlayMap()59   inline TargetResourceMap GetTargetToOverlayMap() const {
60     return target_map_;
61   }
62 
63   // Retrieves the mapping of overlay resource id to target resource id. This allows a reference to
64   // an overlay resource to appear as a reference to its corresponding target resource at runtime.
65   OverlayResourceMap GetOverlayToTargetMap() const;
66 
67   // Retrieves the build-time package id of the target package.
GetTargetPackageId()68   inline uint32_t GetTargetPackageId() const {
69     return target_package_id_;
70   }
71 
72   // Retrieves the build-time package id of the overlay package.
GetOverlayPackageId()73   inline uint32_t GetOverlayPackageId() const {
74     return overlay_package_id_;
75   }
76 
77   // Retrieves the offset that was added to the index of inline string overlay values so the indices
78   // do not collide with the indices of the overlay resource table string pool.
GetStringPoolOffset()79   inline uint32_t GetStringPoolOffset() const {
80     return string_pool_offset_;
81   }
82 
83   // Retrieves the raw string pool data from the xml referenced in android:resourcesMap.
GetStringPoolData()84   inline const std::pair<const uint8_t*, uint32_t> GetStringPoolData() const {
85     return std::make_pair(string_pool_data_.get(), string_pool_data_length_);
86   }
87 
88  private:
89   ResourceMapping() = default;
90 
91   // Apps a mapping of target resource id to the type and value of the data that overlays the
92   // target resource. The data_type is the runtime format of the data value (see
93   // Res_value::dataType). If rewrite_overlay_reference is `true` then references to an overlay
94   // resource should appear as a reference to its corresponding target resource at runtime.
95   Result<Unit> AddMapping(ResourceId target_resource, TargetValue::DataType data_type,
96                           TargetValue::DataValue data_value, bool rewrite_overlay_reference);
97 
98   // Removes the overlay value mapping for the target resource.
99   void RemoveMapping(ResourceId target_resource);
100 
101   // Parses the mapping of target resources to overlay resources to generate a ResourceMapping.
102   static Result<ResourceMapping> CreateResourceMapping(const AssetManager2* target_am,
103                                                        const LoadedPackage* target_package,
104                                                        const LoadedPackage* overlay_package,
105                                                        size_t string_pool_offset,
106                                                        const XmlParser& overlay_parser,
107                                                        LogInfo& log_info);
108 
109   // Generates a ResourceMapping that maps target resources to overlay resources by name. To overlay
110   // a target resource, a resource must exist in the overlay with the same type and entry name as
111   // the target resource.
112   static Result<ResourceMapping> CreateResourceMappingLegacy(const AssetManager2* target_am,
113                                                              const AssetManager2* overlay_am,
114                                                              const LoadedPackage* target_package,
115                                                              const LoadedPackage* overlay_package);
116 
117   // Removes resources that do not pass policy or overlayable checks of the target package.
118   void FilterOverlayableResources(const AssetManager2* target_am,
119                                   const LoadedPackage* target_package,
120                                   const LoadedPackage* overlay_package,
121                                   const OverlayManifestInfo& overlay_info,
122                                   const PolicyBitmask& fulfilled_policies, LogInfo& log_info);
123 
124   TargetResourceMap target_map_;
125   std::multimap<ResourceId, ResourceId> overlay_map_;
126 
127   uint32_t target_package_id_ = 0;
128   uint32_t overlay_package_id_ = 0;
129   uint32_t string_pool_offset_ = 0;
130   uint32_t string_pool_data_length_ = 0;
131   std::unique_ptr<uint8_t[]> string_pool_data_ = nullptr;
132 };
133 
134 }  // namespace android::idmap2
135 
136 #endif  // IDMAP2_INCLUDE_IDMAP2_RESOURCEMAPPING_H_
137