1 //
2 // Copyright 2011 The Android Open Source Project
3 //
4 // Build resource files from raw assets.
5 //
6 
7 #ifndef RESOURCE_FILTER_H
8 #define RESOURCE_FILTER_H
9 
10 #include <androidfw/ResourceTypes.h>
11 #include <set>
12 #include <utility>
13 #include <utils/Errors.h>
14 #include <utils/String8.h>
15 #include <utils/StrongPointer.h>
16 #include <utils/Vector.h>
17 
18 #include "AaptAssets.h"
19 #include "ConfigDescription.h"
20 
21 class ResourceFilter : public virtual android::RefBase {
22 public:
23     virtual bool match(const android::ResTable_config& config) const = 0;
24 };
25 
26 /**
27  * Implements logic for parsing and handling "-c" options.
28  */
29 class WeakResourceFilter : public ResourceFilter {
30 public:
WeakResourceFilter()31     WeakResourceFilter()
32         : mContainsPseudoAccented(false)
33         , mContainsPseudoBidi(false) {}
34 
35     android::status_t parse(const android::String8& str);
36 
37     bool match(const android::ResTable_config& config) const;
38 
isEmpty()39     inline bool isEmpty() const {
40         return mConfigMask == 0;
41     }
42 
containsPseudo()43     inline bool containsPseudo() const {
44         return mContainsPseudoAccented;
45     }
46 
containsPseudoBidi()47     inline bool containsPseudoBidi() const {
48         return mContainsPseudoBidi;
49     }
50 
51 private:
52     ConfigDescription mDefault;
53     uint32_t mConfigMask;
54     android::Vector<std::pair<ConfigDescription, uint32_t> > mConfigs;
55 
56     bool mContainsPseudoAccented;
57     bool mContainsPseudoBidi;
58 };
59 
60 /**
61  * Matches resources that have at least one of the configurations
62  * that this filter is looking for. In order to match a configuration,
63  * the resource must have the exact same configuration.
64  *
65  * This filter acts as a logical OR when matching resources.
66  *
67  * For example, if the filter is looking for resources with
68  * fr-land, de-land, or sw600dp:
69  *
70  * (PASS) fr-land
71  * (FAIL) fr
72  * (PASS) de-land
73  * (FAIL) de
74  * (FAIL) de-sw600dp
75  * (PASS) sw600dp
76  * (FAIL) sw600dp-land
77  */
78 class StrongResourceFilter : public ResourceFilter {
79 public:
StrongResourceFilter()80     StrongResourceFilter() {}
StrongResourceFilter(const std::set<ConfigDescription> & configs)81     explicit StrongResourceFilter(const std::set<ConfigDescription>& configs)
82         : mConfigs(configs) {}
83 
84     android::status_t parse(const android::String8& str);
85 
match(const android::ResTable_config & config)86     bool match(const android::ResTable_config& config) const {
87         std::set<ConfigDescription>::const_iterator iter = mConfigs.begin();
88         for (; iter != mConfigs.end(); iter++) {
89             if (iter->compare(config) == 0) {
90                 return true;
91             }
92         }
93         return false;
94     }
95 
getConfigs()96     inline const std::set<ConfigDescription>& getConfigs() const {
97         return mConfigs;
98     }
99 
100 private:
101     std::set<ConfigDescription> mConfigs;
102 };
103 
104 /**
105  * Negates the response of the target filter.
106  */
107 class InverseResourceFilter : public ResourceFilter {
108 public:
InverseResourceFilter(const android::sp<ResourceFilter> & filter)109     explicit InverseResourceFilter(const android::sp<ResourceFilter>& filter)
110         : mFilter(filter) {}
111 
match(const android::ResTable_config & config)112     bool match(const android::ResTable_config& config) const {
113         return !mFilter->match(config);
114     }
115 
116 private:
117     const android::sp<ResourceFilter> mFilter;
118 };
119 
120 /**
121  * A logical AND of all the added filters.
122  */
123 class AndResourceFilter : public ResourceFilter {
124 public:
addFilter(const android::sp<ResourceFilter> & filter)125     void addFilter(const android::sp<ResourceFilter>& filter) {
126         mFilters.add(filter);
127     }
128 
match(const android::ResTable_config & config)129     bool match(const android::ResTable_config& config) const {
130         const size_t N = mFilters.size();
131         for (size_t i = 0; i < N; i++) {
132             if (!mFilters[i]->match(config)) {
133                 return false;
134             }
135         }
136         return true;
137     }
138 
139 private:
140     android::Vector<android::sp<ResourceFilter> > mFilters;
141 };
142 #endif
143