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