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