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_TABLEMERGER_H
18 #define AAPT_TABLEMERGER_H
19 
20 #include <functional>
21 #include <map>
22 
23 #include "android-base/macros.h"
24 
25 #include "Resource.h"
26 #include "ResourceTable.h"
27 #include "ResourceValues.h"
28 #include "filter/ConfigFilter.h"
29 #include "io/File.h"
30 #include "process/IResourceTableConsumer.h"
31 #include "util/Util.h"
32 
33 namespace aapt {
34 
35 struct TableMergerOptions {
36   /**
37    * If true, resources in overlays can be added without previously having
38    * existed.
39    */
40   bool auto_add_overlay = false;
41 };
42 
43 /**
44  * TableMerger takes resource tables and merges all packages within the tables
45  * that have the same
46  * package ID.
47  *
48  * If a package has a different name, all the entries in that table have their
49  * names mangled
50  * to include the package name. This way there are no collisions. In order to do
51  * this correctly,
52  * the TableMerger needs to also mangle any FileReference paths. Once these are
53  * mangled,
54  * the original source path of the file, along with the new destination path is
55  * recorded in the
56  * queue returned from getFileMergeQueue().
57  *
58  * Once the merging is complete, a separate process can go collect the files
59  * from the various
60  * source APKs and either copy or process their XML and put them in the correct
61  * location in
62  * the final APK.
63  */
64 class TableMerger {
65  public:
66   /**
67    * Note: The out_table ResourceTable must live longer than this TableMerger.
68    * References are made to this ResourceTable for efficiency reasons.
69    */
70   TableMerger(IAaptContext* context, ResourceTable* out_table,
71               const TableMergerOptions& options);
72 
merged_packages()73   const std::set<std::string>& merged_packages() const {
74     return merged_packages_;
75   }
76 
77   /**
78    * Merges resources from the same or empty package. This is for local sources.
79    * An io::IFileCollection is optional and used to find the referenced Files
80    * and process them.
81    */
82   bool Merge(const Source& src, ResourceTable* table,
83              io::IFileCollection* collection = nullptr);
84 
85   /**
86    * Merges resources from an overlay ResourceTable.
87    * An io::IFileCollection is optional and used to find the referenced Files
88    * and process them.
89    */
90   bool MergeOverlay(const Source& src, ResourceTable* table,
91                     io::IFileCollection* collection = nullptr);
92 
93   /**
94    * Merges resources from the given package, mangling the name. This is for
95    * static libraries.
96    * An io::IFileCollection is needed in order to find the referenced Files and
97    * process them.
98    */
99   bool MergeAndMangle(const Source& src, const android::StringPiece& package, ResourceTable* table,
100                       io::IFileCollection* collection);
101 
102   /**
103    * Merges a compiled file that belongs to this same or empty package. This is
104    * for local sources.
105    */
106   bool MergeFile(const ResourceFile& fileDesc, io::IFile* file);
107 
108   /**
109    * Merges a compiled file from an overlay, overriding an existing definition.
110    */
111   bool MergeFileOverlay(const ResourceFile& fileDesc, io::IFile* file);
112 
113  private:
114   DISALLOW_COPY_AND_ASSIGN(TableMerger);
115 
116   using FileMergeCallback = std::function<bool(const ResourceNameRef&,
117                                                const ConfigDescription& config,
118                                                FileReference*, FileReference*)>;
119 
120   IAaptContext* context_;
121   ResourceTable* master_table_;
122   TableMergerOptions options_;
123   ResourceTablePackage* master_package_;
124   std::set<std::string> merged_packages_;
125 
126   bool MergeFileImpl(const ResourceFile& file_desc, io::IFile* file,
127                      bool overlay);
128 
129   bool MergeImpl(const Source& src, ResourceTable* src_table,
130                  io::IFileCollection* collection, bool overlay, bool allow_new);
131 
132   bool DoMerge(const Source& src, ResourceTable* src_table,
133                ResourceTablePackage* src_package, const bool mangle_package,
134                const bool overlay, const bool allow_new_resources,
135                const FileMergeCallback& callback);
136 
137   std::unique_ptr<FileReference> CloneAndMangleFile(const std::string& package,
138                                                     const FileReference& value);
139 };
140 
141 }  // namespace aapt
142 
143 #endif /* AAPT_TABLEMERGER_H */
144