1 /*
2  * Copyright (C) 2014 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 __APK_BUILDER_H
18 #define __APK_BUILDER_H
19 
20 #include <set>
21 #include <utils/Errors.h>
22 #include <utils/String8.h>
23 #include <utils/StrongPointer.h>
24 #include <utils/Vector.h>
25 
26 #include "ConfigDescription.h"
27 #include "OutputSet.h"
28 #include "ResourceFilter.h"
29 
30 class ApkSplit;
31 class AaptFile;
32 
33 class ApkBuilder : public android::RefBase {
34 public:
35     explicit ApkBuilder(const sp<WeakResourceFilter>& configFilter);
36 
37     /**
38      * Tells the builder to generate a separate APK for resources that
39      * match the configurations specified. Split APKs can not have
40      * overlapping resources.
41      *
42      * NOTE: All splits should be set up before any files are added.
43      */
44     android::status_t createSplitForConfigs(const std::set<ConfigDescription>& configs);
45 
46     /**
47      * Adds a file to be written to the final APK. It's name must not collide
48      * with that of any files previously added. When a Split APK is being
49      * generated, duplicates can exist as long as they are in different splits
50      * (resources.arsc, AndroidManifest.xml).
51      */
52     android::status_t addEntry(const String8& path, const android::sp<AaptFile>& file);
53 
getSplits()54     android::Vector<sp<ApkSplit> >& getSplits() {
55         return mSplits;
56     }
57 
getBaseSplit()58     android::sp<ApkSplit> getBaseSplit() {
59         return mSplits[0];
60     }
61 
62     void print() const;
63 
64 private:
65     android::sp<ResourceFilter> mConfigFilter;
66     android::sp<AndResourceFilter> mDefaultFilter;
67     android::Vector<sp<ApkSplit> > mSplits;
68 };
69 
70 class ApkSplit : public OutputSet {
71 public:
72     android::status_t addEntry(const String8& path, const android::sp<AaptFile>& file);
73 
getEntries()74     const std::set<OutputEntry>& getEntries() const {
75         return mFiles;
76     }
77 
getConfigs()78     const std::set<ConfigDescription>& getConfigs() const {
79         return mConfigs;
80     }
81 
matches(const sp<AaptFile> & file)82     bool matches(const sp<AaptFile>& file) const {
83         return mFilter->match(file->getGroupEntry().toParams());
84     }
85 
getResourceFilter()86     sp<ResourceFilter> getResourceFilter() const {
87         return mFilter;
88     }
89 
getPrintableName()90     const android::String8& getPrintableName() const {
91         return mName;
92     }
93 
getDirectorySafeName()94     const android::String8& getDirectorySafeName() const {
95         return mDirName;
96     }
97 
getPackageSafeName()98     const android::String8& getPackageSafeName() const {
99         return mPackageSafeName;
100     }
101 
isBase()102     bool isBase() const {
103         return mIsBase;
104     }
105 
106     void print() const;
107 
108 private:
109     friend class ApkBuilder;
110 
111     ApkSplit(const std::set<ConfigDescription>& configs, const android::sp<ResourceFilter>& filter, bool isBase=false);
112 
113     std::set<ConfigDescription> mConfigs;
114     const sp<ResourceFilter> mFilter;
115     const bool mIsBase;
116     String8 mName;
117     String8 mDirName;
118     String8 mPackageSafeName;
119     std::set<OutputEntry> mFiles;
120 };
121 
122 #endif // __APK_BUILDER_H
123