1 /*
2  * Copyright (C) 2015 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 AAPT_LINKER_LINKERS_H
18 #define AAPT_LINKER_LINKERS_H
19 
20 #include <set>
21 #include <unordered_set>
22 
23 #include "android-base/macros.h"
24 
25 #include "Resource.h"
26 #include "SdkConstants.h"
27 #include "process/IResourceTableConsumer.h"
28 #include "xml/XmlDom.h"
29 
30 namespace aapt {
31 
32 class ResourceTable;
33 class ResourceEntry;
34 struct ConfigDescription;
35 
36 /**
37  * Defines the location in which a value exists. This determines visibility of
38  * other package's private symbols.
39  */
40 struct CallSite {
41   ResourceNameRef resource;
42 };
43 
44 /**
45  * Determines whether a versioned resource should be created. If a versioned
46  * resource already exists, it takes precedence.
47  */
48 bool ShouldGenerateVersionedResource(const ResourceEntry* entry, const ConfigDescription& config,
49                                      const ApiVersion sdk_version_to_generate);
50 
51 // Finds the next largest ApiVersion of the config which is identical to the given config except
52 // for sdkVersion.
53 ApiVersion FindNextApiVersionForConfig(const ResourceEntry* entry, const ConfigDescription& config);
54 
55 class AutoVersioner : public IResourceTableConsumer {
56  public:
57   AutoVersioner() = default;
58 
59   bool Consume(IAaptContext* context, ResourceTable* table) override;
60 
61  private:
62   DISALLOW_COPY_AND_ASSIGN(AutoVersioner);
63 };
64 
65 /**
66  * If any attribute resource values are defined as public, this consumer will
67  * move all private
68  * attribute resource values to a private ^private-attr type, avoiding backwards
69  * compatibility
70  * issues with new apps running on old platforms.
71  *
72  * The Android platform ignores resource attributes it doesn't recognize, so an
73  * app developer can
74  * use new attributes in their layout XML files without worrying about
75  * versioning. This assumption
76  * actually breaks on older platforms. OEMs may add private attributes that are
77  * used internally.
78  * AAPT originally assigned all private attributes IDs immediately proceeding
79  * the public attributes'
80  * IDs.
81  *
82  * This means that on a newer Android platform, an ID previously assigned to a
83  * private attribute
84  * may end up assigned to a public attribute.
85  *
86  * App developers assume using the newer attribute is safe on older platforms
87  * because it will
88  * be ignored. Instead, the platform thinks the new attribute is an older,
89  * private attribute and
90  * will interpret it as such. This leads to unintended styling and exceptions
91  * thrown due to
92  * unexpected types.
93  *
94  * By moving the private attributes to a completely different type, this ID
95  * conflict will never
96  * occur.
97  */
98 class PrivateAttributeMover : public IResourceTableConsumer {
99  public:
100   PrivateAttributeMover() = default;
101 
102   bool Consume(IAaptContext* context, ResourceTable* table) override;
103 
104  private:
105   DISALLOW_COPY_AND_ASSIGN(PrivateAttributeMover);
106 };
107 
108 class ResourceConfigValue;
109 
110 class ProductFilter : public IResourceTableConsumer {
111  public:
112   using ResourceConfigValueIter = std::vector<std::unique_ptr<ResourceConfigValue>>::iterator;
113 
ProductFilter(std::unordered_set<std::string> products)114   explicit ProductFilter(std::unordered_set<std::string> products) : products_(products) {
115   }
116 
117   ResourceConfigValueIter SelectProductToKeep(
118       const ResourceNameRef& name, const ResourceConfigValueIter begin,
119       const ResourceConfigValueIter end, IDiagnostics* diag);
120 
121   bool Consume(IAaptContext* context, ResourceTable* table) override;
122 
123  private:
124   DISALLOW_COPY_AND_ASSIGN(ProductFilter);
125 
126   std::unordered_set<std::string> products_;
127 };
128 
129 /**
130  * Removes namespace nodes and URI information from the XmlResource.
131  *
132  * Once an XmlResource is processed by this consumer, it is no longer able to
133  * have its attributes
134  * parsed. As such, this XmlResource must have already been processed by
135  * XmlReferenceLinker.
136  */
137 class XmlNamespaceRemover : public IXmlResourceConsumer {
138  public:
keep_uris_(keep_uris)139   explicit XmlNamespaceRemover(bool keep_uris = false) : keep_uris_(keep_uris){};
140 
141   bool Consume(IAaptContext* context, xml::XmlResource* resource) override;
142 
143  private:
144   DISALLOW_COPY_AND_ASSIGN(XmlNamespaceRemover);
145 
146   bool keep_uris_;
147 };
148 
149 /**
150  * Resolves attributes in the XmlResource and compiles string values to resource
151  * values.
152  * Once an XmlResource is processed by this linker, it is ready to be flattened.
153  */
154 class XmlReferenceLinker : public IXmlResourceConsumer {
155  public:
156   XmlReferenceLinker() = default;
157 
158   bool Consume(IAaptContext* context, xml::XmlResource* resource) override;
159 
160  private:
161   DISALLOW_COPY_AND_ASSIGN(XmlReferenceLinker);
162 };
163 
164 }  // namespace aapt
165 
166 #endif /* AAPT_LINKER_LINKERS_H */
167