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 <androidfw/ApkAssets.h>
21 
22 #include <map>
23 #include <memory>
24 #include <utility>
25 
26 #include "idmap2/FabricatedOverlay.h"
27 #include "idmap2/LogInfo.h"
28 #include "idmap2/Policies.h"
29 #include "idmap2/ResourceUtils.h"
30 #include "idmap2/Result.h"
31 #include "idmap2/XmlParser.h"
32 
33 using PolicyBitmask = android::ResTable_overlayable_policy_header::PolicyBitmask;
34 
35 namespace android::idmap2 {
36 using TargetResourceMap = std::map<ResourceId, std::variant<ResourceId, TargetValue>>;
37 using OverlayResourceMap = std::map<ResourceId, ResourceId>;
38 
39 class ResourceMapping {
40  public:
41   // Creates a ResourceMapping using the target and overlay APKs. Setting enforce_overlayable to
42   // `false` disables all overlayable and policy enforcement: this is intended for backwards
43   // compatibility pre-Q and unit tests.
44   static Result<ResourceMapping> FromContainers(const TargetResourceContainer& target,
45                                                 const OverlayResourceContainer& overlay,
46                                                 const OverlayManifestInfo& overlay_info,
47                                                 const PolicyBitmask& fulfilled_policies,
48                                                 bool enforce_overlayable, LogInfo& log_info);
49 
50   // Retrieves the mapping of target resource id to overlay value.
51   WARN_UNUSED const TargetResourceMap& GetTargetToOverlayMap() const;
52 
53   // Retrieves the mapping of overlay resource id to target resource id. This allows a reference to
54   // an overlay resource to appear as a reference to its corresponding target resource at runtime.
55   WARN_UNUSED const OverlayResourceMap& GetOverlayToTargetMap() const;
56 
57   // Retrieves the offset that was added to the index of inline string overlay values so the indices
58   // do not collide with the indices of the overlay resource table string pool.
59   WARN_UNUSED uint32_t GetStringPoolOffset() const;
60 
61   // Retrieves the raw string pool data from the xml referenced in android:resourcesMap.
62   WARN_UNUSED StringPiece GetStringPoolData() const;
63 
64  private:
65   ResourceMapping() = default;
66 
67   // Maps a target resource id to an overlay resource id or a android::Res_value value.
68   //
69   // If `allow_rewriting_` is true, then the overlay-to-target map will be populated if the target
70   // resource id is mapped to an overlay resource id.
71   Result<Unit> AddMapping(ResourceId target_resource,
72                           const std::variant<OverlayData::ResourceIdValue, TargetValue>& value);
73 
74   TargetResourceMap target_map_;
75   OverlayResourceMap overlay_map_;
76   uint32_t string_pool_offset_ = 0;
77   uint32_t string_pool_data_length_ = 0;
78   std::unique_ptr<uint8_t[]> string_pool_data_ = nullptr;
79 };
80 
GetTargetToOverlayMap()81 inline const TargetResourceMap& ResourceMapping::GetTargetToOverlayMap() const {
82   return target_map_;
83 }
84 
GetOverlayToTargetMap()85 inline const OverlayResourceMap& ResourceMapping::GetOverlayToTargetMap() const {
86   return overlay_map_;
87 }
88 
GetStringPoolOffset()89 inline uint32_t ResourceMapping::GetStringPoolOffset() const {
90   return string_pool_offset_;
91 }
92 
GetStringPoolData()93 inline StringPiece ResourceMapping::GetStringPoolData() const {
94   return StringPiece(reinterpret_cast<const char*>(string_pool_data_.get()),
95                      string_pool_data_length_);
96 }
97 
98 }  // namespace android::idmap2
99 
100 #endif  // IDMAP2_INCLUDE_IDMAP2_RESOURCEMAPPING_H_
101