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
30class ApkSplit;
31class AaptFile;
32
33class ApkBuilder : public android::RefBase {
34public:
35    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
54    android::Vector<sp<ApkSplit> >& getSplits() {
55        return mSplits;
56    }
57
58    android::sp<ApkSplit> getBaseSplit() {
59        return mSplits[0];
60    }
61
62    void print() const;
63
64private:
65    android::sp<ResourceFilter> mConfigFilter;
66    android::sp<AndResourceFilter> mDefaultFilter;
67    android::Vector<sp<ApkSplit> > mSplits;
68};
69
70class ApkSplit : public OutputSet {
71public:
72    android::status_t addEntry(const String8& path, const android::sp<AaptFile>& file);
73
74    const std::set<OutputEntry>& getEntries() const {
75        return mFiles;
76    }
77
78    const std::set<ConfigDescription>& getConfigs() const {
79        return mConfigs;
80    }
81
82    bool matches(const sp<AaptFile>& file) const {
83        return mFilter->match(file->getGroupEntry().toParams());
84    }
85
86    sp<ResourceFilter> getResourceFilter() const {
87        return mFilter;
88    }
89
90    const android::String8& getPrintableName() const {
91        return mName;
92    }
93
94    const android::String8& getDirectorySafeName() const {
95        return mDirName;
96    }
97
98    const android::String8& getPackageSafeName() const {
99        return mPackageSafeName;
100    }
101
102    bool isBase() const {
103        return mIsBase;
104    }
105
106    void print() const;
107
108private:
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