1*d57664e9SAndroid Build Coastguard Worker /*
2*d57664e9SAndroid Build Coastguard Worker * Copyright (C) 2018 The Android Open Source Project
3*d57664e9SAndroid Build Coastguard Worker *
4*d57664e9SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*d57664e9SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*d57664e9SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*d57664e9SAndroid Build Coastguard Worker *
8*d57664e9SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*d57664e9SAndroid Build Coastguard Worker *
10*d57664e9SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*d57664e9SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*d57664e9SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*d57664e9SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*d57664e9SAndroid Build Coastguard Worker * limitations under the License.
15*d57664e9SAndroid Build Coastguard Worker */
16*d57664e9SAndroid Build Coastguard Worker
17*d57664e9SAndroid Build Coastguard Worker #include "DumpManifest.h"
18*d57664e9SAndroid Build Coastguard Worker
19*d57664e9SAndroid Build Coastguard Worker #include <androidfw/ApkParsing.h>
20*d57664e9SAndroid Build Coastguard Worker
21*d57664e9SAndroid Build Coastguard Worker #include <algorithm>
22*d57664e9SAndroid Build Coastguard Worker #include <array>
23*d57664e9SAndroid Build Coastguard Worker #include <memory>
24*d57664e9SAndroid Build Coastguard Worker #include <set>
25*d57664e9SAndroid Build Coastguard Worker #include <string_view>
26*d57664e9SAndroid Build Coastguard Worker #include <vector>
27*d57664e9SAndroid Build Coastguard Worker
28*d57664e9SAndroid Build Coastguard Worker #include "LoadedApk.h"
29*d57664e9SAndroid Build Coastguard Worker #include "SdkConstants.h"
30*d57664e9SAndroid Build Coastguard Worker #include "ValueVisitor.h"
31*d57664e9SAndroid Build Coastguard Worker #include "androidfw/ConfigDescription.h"
32*d57664e9SAndroid Build Coastguard Worker #include "androidfw/FileStream.h"
33*d57664e9SAndroid Build Coastguard Worker #include "io/File.h"
34*d57664e9SAndroid Build Coastguard Worker #include "process/IResourceTableConsumer.h"
35*d57664e9SAndroid Build Coastguard Worker #include "xml/XmlDom.h"
36*d57664e9SAndroid Build Coastguard Worker
37*d57664e9SAndroid Build Coastguard Worker using ::android::base::StringPrintf;
38*d57664e9SAndroid Build Coastguard Worker using ::android::ConfigDescription;
39*d57664e9SAndroid Build Coastguard Worker
40*d57664e9SAndroid Build Coastguard Worker namespace aapt {
41*d57664e9SAndroid Build Coastguard Worker
42*d57664e9SAndroid Build Coastguard Worker /**
43*d57664e9SAndroid Build Coastguard Worker * These are attribute resource constants for the platform, as found in android.R.attr.
44*d57664e9SAndroid Build Coastguard Worker */
45*d57664e9SAndroid Build Coastguard Worker enum {
46*d57664e9SAndroid Build Coastguard Worker LABEL_ATTR = 0x01010001,
47*d57664e9SAndroid Build Coastguard Worker ICON_ATTR = 0x01010002,
48*d57664e9SAndroid Build Coastguard Worker NAME_ATTR = 0x01010003,
49*d57664e9SAndroid Build Coastguard Worker PERMISSION_ATTR = 0x01010006,
50*d57664e9SAndroid Build Coastguard Worker EXPORTED_ATTR = 0x01010010,
51*d57664e9SAndroid Build Coastguard Worker GRANT_URI_PERMISSIONS_ATTR = 0x0101001b,
52*d57664e9SAndroid Build Coastguard Worker PRIORITY_ATTR = 0x0101001c,
53*d57664e9SAndroid Build Coastguard Worker RESOURCE_ATTR = 0x01010025,
54*d57664e9SAndroid Build Coastguard Worker DEBUGGABLE_ATTR = 0x0101000f,
55*d57664e9SAndroid Build Coastguard Worker TARGET_PACKAGE_ATTR = 0x01010021,
56*d57664e9SAndroid Build Coastguard Worker VALUE_ATTR = 0x01010024,
57*d57664e9SAndroid Build Coastguard Worker VERSION_CODE_ATTR = 0x0101021b,
58*d57664e9SAndroid Build Coastguard Worker VERSION_NAME_ATTR = 0x0101021c,
59*d57664e9SAndroid Build Coastguard Worker SCREEN_ORIENTATION_ATTR = 0x0101001e,
60*d57664e9SAndroid Build Coastguard Worker MIN_SDK_VERSION_ATTR = 0x0101020c,
61*d57664e9SAndroid Build Coastguard Worker MAX_SDK_VERSION_ATTR = 0x01010271,
62*d57664e9SAndroid Build Coastguard Worker REQ_TOUCH_SCREEN_ATTR = 0x01010227,
63*d57664e9SAndroid Build Coastguard Worker REQ_KEYBOARD_TYPE_ATTR = 0x01010228,
64*d57664e9SAndroid Build Coastguard Worker REQ_HARD_KEYBOARD_ATTR = 0x01010229,
65*d57664e9SAndroid Build Coastguard Worker REQ_NAVIGATION_ATTR = 0x0101022a,
66*d57664e9SAndroid Build Coastguard Worker REQ_FIVE_WAY_NAV_ATTR = 0x01010232,
67*d57664e9SAndroid Build Coastguard Worker TARGET_SDK_VERSION_ATTR = 0x01010270,
68*d57664e9SAndroid Build Coastguard Worker TEST_ONLY_ATTR = 0x01010272,
69*d57664e9SAndroid Build Coastguard Worker ANY_DENSITY_ATTR = 0x0101026c,
70*d57664e9SAndroid Build Coastguard Worker GL_ES_VERSION_ATTR = 0x01010281,
71*d57664e9SAndroid Build Coastguard Worker SMALL_SCREEN_ATTR = 0x01010284,
72*d57664e9SAndroid Build Coastguard Worker NORMAL_SCREEN_ATTR = 0x01010285,
73*d57664e9SAndroid Build Coastguard Worker LARGE_SCREEN_ATTR = 0x01010286,
74*d57664e9SAndroid Build Coastguard Worker XLARGE_SCREEN_ATTR = 0x010102bf,
75*d57664e9SAndroid Build Coastguard Worker REQUIRED_ATTR = 0x0101028e,
76*d57664e9SAndroid Build Coastguard Worker INSTALL_LOCATION_ATTR = 0x010102b7,
77*d57664e9SAndroid Build Coastguard Worker SCREEN_SIZE_ATTR = 0x010102ca,
78*d57664e9SAndroid Build Coastguard Worker SCREEN_DENSITY_ATTR = 0x010102cb,
79*d57664e9SAndroid Build Coastguard Worker REQUIRES_SMALLEST_WIDTH_DP_ATTR = 0x01010364,
80*d57664e9SAndroid Build Coastguard Worker COMPATIBLE_WIDTH_LIMIT_DP_ATTR = 0x01010365,
81*d57664e9SAndroid Build Coastguard Worker LARGEST_WIDTH_LIMIT_DP_ATTR = 0x01010366,
82*d57664e9SAndroid Build Coastguard Worker PUBLIC_KEY_ATTR = 0x010103a6,
83*d57664e9SAndroid Build Coastguard Worker CATEGORY_ATTR = 0x010103e8,
84*d57664e9SAndroid Build Coastguard Worker BANNER_ATTR = 0x10103f2,
85*d57664e9SAndroid Build Coastguard Worker ISGAME_ATTR = 0x10103f4,
86*d57664e9SAndroid Build Coastguard Worker VERSION_ATTR = 0x01010519,
87*d57664e9SAndroid Build Coastguard Worker CERT_DIGEST_ATTR = 0x01010548,
88*d57664e9SAndroid Build Coastguard Worker REQUIRED_FEATURE_ATTR = 0x01010554,
89*d57664e9SAndroid Build Coastguard Worker REQUIRED_NOT_FEATURE_ATTR = 0x01010555,
90*d57664e9SAndroid Build Coastguard Worker IS_STATIC_ATTR = 0x0101055a,
91*d57664e9SAndroid Build Coastguard Worker REQUIRED_SYSTEM_PROPERTY_NAME_ATTR = 0x01010565,
92*d57664e9SAndroid Build Coastguard Worker REQUIRED_SYSTEM_PROPERTY_VALUE_ATTR = 0x01010566,
93*d57664e9SAndroid Build Coastguard Worker COMPILE_SDK_VERSION_ATTR = 0x01010572,
94*d57664e9SAndroid Build Coastguard Worker COMPILE_SDK_VERSION_CODENAME_ATTR = 0x01010573,
95*d57664e9SAndroid Build Coastguard Worker VERSION_MAJOR_ATTR = 0x01010577,
96*d57664e9SAndroid Build Coastguard Worker PACKAGE_TYPE_ATTR = 0x01010587,
97*d57664e9SAndroid Build Coastguard Worker USES_PERMISSION_FLAGS_ATTR = 0x01010644,
98*d57664e9SAndroid Build Coastguard Worker };
99*d57664e9SAndroid Build Coastguard Worker
100*d57664e9SAndroid Build Coastguard Worker const std::string& kAndroidNamespace = "http://schemas.android.com/apk/res/android";
101*d57664e9SAndroid Build Coastguard Worker constexpr int kNeverForLocation = 0x00010000;
102*d57664e9SAndroid Build Coastguard Worker
103*d57664e9SAndroid Build Coastguard Worker /** Retrieves the attribute of the element with the specified attribute resource id. */
FindAttribute(xml::Element * el,uint32_t resd_id)104*d57664e9SAndroid Build Coastguard Worker static xml::Attribute* FindAttribute(xml::Element *el, uint32_t resd_id) {
105*d57664e9SAndroid Build Coastguard Worker for (auto& a : el->attributes) {
106*d57664e9SAndroid Build Coastguard Worker if (a.compiled_attribute && a.compiled_attribute.value().id) {
107*d57664e9SAndroid Build Coastguard Worker if (a.compiled_attribute.value().id.value() == resd_id) {
108*d57664e9SAndroid Build Coastguard Worker return std::move(&a);
109*d57664e9SAndroid Build Coastguard Worker }
110*d57664e9SAndroid Build Coastguard Worker }
111*d57664e9SAndroid Build Coastguard Worker }
112*d57664e9SAndroid Build Coastguard Worker return nullptr;
113*d57664e9SAndroid Build Coastguard Worker }
114*d57664e9SAndroid Build Coastguard Worker
115*d57664e9SAndroid Build Coastguard Worker /** Retrieves the attribute of the element that has the specified namespace and attribute name. */
FindAttribute(xml::Element * el,const std::string & package,const std::string & name)116*d57664e9SAndroid Build Coastguard Worker static xml::Attribute* FindAttribute(xml::Element *el, const std::string &package,
117*d57664e9SAndroid Build Coastguard Worker const std::string &name) {
118*d57664e9SAndroid Build Coastguard Worker return el->FindAttribute(package, name);
119*d57664e9SAndroid Build Coastguard Worker }
120*d57664e9SAndroid Build Coastguard Worker
121*d57664e9SAndroid Build Coastguard Worker class Architectures {
122*d57664e9SAndroid Build Coastguard Worker public:
123*d57664e9SAndroid Build Coastguard Worker std::set<std::string> architectures;
124*d57664e9SAndroid Build Coastguard Worker std::set<std::string> alt_architectures;
125*d57664e9SAndroid Build Coastguard Worker
Print(text::Printer * printer)126*d57664e9SAndroid Build Coastguard Worker void Print(text::Printer* printer) {
127*d57664e9SAndroid Build Coastguard Worker if (!architectures.empty()) {
128*d57664e9SAndroid Build Coastguard Worker printer->Print("native-code:");
129*d57664e9SAndroid Build Coastguard Worker for (auto& arch : architectures) {
130*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" '%s'", arch.data()));
131*d57664e9SAndroid Build Coastguard Worker }
132*d57664e9SAndroid Build Coastguard Worker printer->Print("\n");
133*d57664e9SAndroid Build Coastguard Worker }
134*d57664e9SAndroid Build Coastguard Worker if (!alt_architectures.empty()) {
135*d57664e9SAndroid Build Coastguard Worker printer->Print("alt-native-code:");
136*d57664e9SAndroid Build Coastguard Worker for (auto& arch : alt_architectures) {
137*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" '%s'", arch.data()));
138*d57664e9SAndroid Build Coastguard Worker }
139*d57664e9SAndroid Build Coastguard Worker printer->Print("\n");
140*d57664e9SAndroid Build Coastguard Worker }
141*d57664e9SAndroid Build Coastguard Worker }
142*d57664e9SAndroid Build Coastguard Worker
ToProto(pb::Badging * out_badging)143*d57664e9SAndroid Build Coastguard Worker void ToProto(pb::Badging* out_badging) {
144*d57664e9SAndroid Build Coastguard Worker auto out_architectures = out_badging->mutable_architectures();
145*d57664e9SAndroid Build Coastguard Worker for (auto& arch : architectures) {
146*d57664e9SAndroid Build Coastguard Worker out_architectures->add_architectures(arch);
147*d57664e9SAndroid Build Coastguard Worker }
148*d57664e9SAndroid Build Coastguard Worker for (auto& arch : alt_architectures) {
149*d57664e9SAndroid Build Coastguard Worker out_architectures->add_alt_architectures(arch);
150*d57664e9SAndroid Build Coastguard Worker }
151*d57664e9SAndroid Build Coastguard Worker }
152*d57664e9SAndroid Build Coastguard Worker };
153*d57664e9SAndroid Build Coastguard Worker
154*d57664e9SAndroid Build Coastguard Worker const static std::array<std::string_view, 14> printable_components{"app-widget",
155*d57664e9SAndroid Build Coastguard Worker "device-admin",
156*d57664e9SAndroid Build Coastguard Worker "ime",
157*d57664e9SAndroid Build Coastguard Worker "wallpaper",
158*d57664e9SAndroid Build Coastguard Worker "accessibility",
159*d57664e9SAndroid Build Coastguard Worker "print-service",
160*d57664e9SAndroid Build Coastguard Worker "payment",
161*d57664e9SAndroid Build Coastguard Worker "search",
162*d57664e9SAndroid Build Coastguard Worker "document-provider",
163*d57664e9SAndroid Build Coastguard Worker "launcher",
164*d57664e9SAndroid Build Coastguard Worker "notification-listener",
165*d57664e9SAndroid Build Coastguard Worker "dream",
166*d57664e9SAndroid Build Coastguard Worker "camera",
167*d57664e9SAndroid Build Coastguard Worker "camera-secure"};
168*d57664e9SAndroid Build Coastguard Worker
169*d57664e9SAndroid Build Coastguard Worker class Components {
170*d57664e9SAndroid Build Coastguard Worker public:
171*d57664e9SAndroid Build Coastguard Worker std::set<std::string, std::less<>> discovered_components;
172*d57664e9SAndroid Build Coastguard Worker bool other_activities = false;
173*d57664e9SAndroid Build Coastguard Worker bool other_receivers = false;
174*d57664e9SAndroid Build Coastguard Worker bool other_services = false;
175*d57664e9SAndroid Build Coastguard Worker
Print(text::Printer * printer)176*d57664e9SAndroid Build Coastguard Worker void Print(text::Printer* printer) {
177*d57664e9SAndroid Build Coastguard Worker for (auto& component : printable_components) {
178*d57664e9SAndroid Build Coastguard Worker if (discovered_components.find(component) != discovered_components.end()) {
179*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("provides-component:'%s'\n", component.data()));
180*d57664e9SAndroid Build Coastguard Worker }
181*d57664e9SAndroid Build Coastguard Worker }
182*d57664e9SAndroid Build Coastguard Worker // Print presence of main activity
183*d57664e9SAndroid Build Coastguard Worker if (discovered_components.find("main") != discovered_components.end()) {
184*d57664e9SAndroid Build Coastguard Worker printer->Print("main\n");
185*d57664e9SAndroid Build Coastguard Worker }
186*d57664e9SAndroid Build Coastguard Worker
187*d57664e9SAndroid Build Coastguard Worker if (other_activities) {
188*d57664e9SAndroid Build Coastguard Worker printer->Print("other-activities\n");
189*d57664e9SAndroid Build Coastguard Worker }
190*d57664e9SAndroid Build Coastguard Worker if (other_receivers) {
191*d57664e9SAndroid Build Coastguard Worker printer->Print("other-receivers\n");
192*d57664e9SAndroid Build Coastguard Worker }
193*d57664e9SAndroid Build Coastguard Worker if (other_services) {
194*d57664e9SAndroid Build Coastguard Worker printer->Print("other-services\n");
195*d57664e9SAndroid Build Coastguard Worker }
196*d57664e9SAndroid Build Coastguard Worker }
197*d57664e9SAndroid Build Coastguard Worker
ToProto(pb::Badging * out_badging)198*d57664e9SAndroid Build Coastguard Worker void ToProto(pb::Badging* out_badging) {
199*d57664e9SAndroid Build Coastguard Worker auto out_components = out_badging->mutable_components();
200*d57664e9SAndroid Build Coastguard Worker for (auto& component : printable_components) {
201*d57664e9SAndroid Build Coastguard Worker auto discovered = discovered_components.find(component);
202*d57664e9SAndroid Build Coastguard Worker if (discovered != discovered_components.end()) {
203*d57664e9SAndroid Build Coastguard Worker out_components->add_provided_components(*discovered);
204*d57664e9SAndroid Build Coastguard Worker }
205*d57664e9SAndroid Build Coastguard Worker }
206*d57664e9SAndroid Build Coastguard Worker out_components->set_main(discovered_components.find("main") != discovered_components.end());
207*d57664e9SAndroid Build Coastguard Worker out_components->set_other_activities(other_activities);
208*d57664e9SAndroid Build Coastguard Worker out_components->set_other_receivers(other_receivers);
209*d57664e9SAndroid Build Coastguard Worker out_components->set_other_services(other_services);
210*d57664e9SAndroid Build Coastguard Worker }
211*d57664e9SAndroid Build Coastguard Worker };
212*d57664e9SAndroid Build Coastguard Worker
213*d57664e9SAndroid Build Coastguard Worker class CommonFeatureGroup;
214*d57664e9SAndroid Build Coastguard Worker class FeatureGroup;
215*d57664e9SAndroid Build Coastguard Worker class SupportsScreen;
216*d57664e9SAndroid Build Coastguard Worker
217*d57664e9SAndroid Build Coastguard Worker class ManifestExtractor {
218*d57664e9SAndroid Build Coastguard Worker public:
219*d57664e9SAndroid Build Coastguard Worker explicit ManifestExtractor(LoadedApk* apk, DumpManifestOptions& options);
220*d57664e9SAndroid Build Coastguard Worker
221*d57664e9SAndroid Build Coastguard Worker class Element {
222*d57664e9SAndroid Build Coastguard Worker public:
223*d57664e9SAndroid Build Coastguard Worker Element() = default;
224*d57664e9SAndroid Build Coastguard Worker virtual ~Element() = default;
225*d57664e9SAndroid Build Coastguard Worker
226*d57664e9SAndroid Build Coastguard Worker static std::unique_ptr<Element> Inflate(ManifestExtractor* extractor, xml::Element* el,
227*d57664e9SAndroid Build Coastguard Worker const std::string& parent_tag);
228*d57664e9SAndroid Build Coastguard Worker
229*d57664e9SAndroid Build Coastguard Worker /** Writes out the extracted contents of the element. */
Print(text::Printer * printer)230*d57664e9SAndroid Build Coastguard Worker virtual void Print(text::Printer* printer) {
231*d57664e9SAndroid Build Coastguard Worker }
232*d57664e9SAndroid Build Coastguard Worker
233*d57664e9SAndroid Build Coastguard Worker /** Saves extracted information into Badging proto. */
ToProto(pb::Badging * out_badging)234*d57664e9SAndroid Build Coastguard Worker virtual void ToProto(pb::Badging* out_badging) {
235*d57664e9SAndroid Build Coastguard Worker }
236*d57664e9SAndroid Build Coastguard Worker
237*d57664e9SAndroid Build Coastguard Worker /** Adds an element to the list of children of the element. */
AddChild(std::unique_ptr<Element> & child)238*d57664e9SAndroid Build Coastguard Worker void AddChild(std::unique_ptr<Element>& child) { children_.push_back(std::move(child)); }
239*d57664e9SAndroid Build Coastguard Worker
240*d57664e9SAndroid Build Coastguard Worker template <typename Predicate>
Filter(Predicate && func)241*d57664e9SAndroid Build Coastguard Worker void Filter(Predicate&& func) {
242*d57664e9SAndroid Build Coastguard Worker children_.erase(std::remove_if(children_.begin(), children_.end(),
243*d57664e9SAndroid Build Coastguard Worker [&](const auto& e) { return func(e.get()); }),
244*d57664e9SAndroid Build Coastguard Worker children_.end());
245*d57664e9SAndroid Build Coastguard Worker }
246*d57664e9SAndroid Build Coastguard Worker
247*d57664e9SAndroid Build Coastguard Worker /** Retrieves the list of children of the element. */
children() const248*d57664e9SAndroid Build Coastguard Worker const std::vector<std::unique_ptr<Element>>& children() const {
249*d57664e9SAndroid Build Coastguard Worker return children_;
250*d57664e9SAndroid Build Coastguard Worker }
251*d57664e9SAndroid Build Coastguard Worker
252*d57664e9SAndroid Build Coastguard Worker /** Retrieves the extracted xml element tag. */
tag() const253*d57664e9SAndroid Build Coastguard Worker const std::string& tag() const {
254*d57664e9SAndroid Build Coastguard Worker return tag_;
255*d57664e9SAndroid Build Coastguard Worker }
256*d57664e9SAndroid Build Coastguard Worker
257*d57664e9SAndroid Build Coastguard Worker /** Whether this element has special Extract/Print/ToProto logic. */
is_featured() const258*d57664e9SAndroid Build Coastguard Worker bool is_featured() const {
259*d57664e9SAndroid Build Coastguard Worker return featured_;
260*d57664e9SAndroid Build Coastguard Worker }
261*d57664e9SAndroid Build Coastguard Worker
262*d57664e9SAndroid Build Coastguard Worker protected:
extractor() const263*d57664e9SAndroid Build Coastguard Worker ManifestExtractor* extractor() const {
264*d57664e9SAndroid Build Coastguard Worker return extractor_;
265*d57664e9SAndroid Build Coastguard Worker }
266*d57664e9SAndroid Build Coastguard Worker
267*d57664e9SAndroid Build Coastguard Worker /** Retrieves and stores the information extracted from the xml element. */
Extract(xml::Element * el)268*d57664e9SAndroid Build Coastguard Worker virtual void Extract(xml::Element* el) { }
269*d57664e9SAndroid Build Coastguard Worker
270*d57664e9SAndroid Build Coastguard Worker /*
271*d57664e9SAndroid Build Coastguard Worker * Retrieves a configuration value of the resource entry that best matches the specified
272*d57664e9SAndroid Build Coastguard Worker * configuration.
273*d57664e9SAndroid Build Coastguard Worker */
BestConfigValue(ResourceEntry * entry,const ConfigDescription & match)274*d57664e9SAndroid Build Coastguard Worker static Value* BestConfigValue(ResourceEntry* entry,
275*d57664e9SAndroid Build Coastguard Worker const ConfigDescription& match) {
276*d57664e9SAndroid Build Coastguard Worker if (!entry) {
277*d57664e9SAndroid Build Coastguard Worker return nullptr;
278*d57664e9SAndroid Build Coastguard Worker }
279*d57664e9SAndroid Build Coastguard Worker
280*d57664e9SAndroid Build Coastguard Worker // Determine the config that best matches the desired config
281*d57664e9SAndroid Build Coastguard Worker ResourceConfigValue* best_value = nullptr;
282*d57664e9SAndroid Build Coastguard Worker for (auto& value : entry->values) {
283*d57664e9SAndroid Build Coastguard Worker if (!value->config.match(match)) {
284*d57664e9SAndroid Build Coastguard Worker continue;
285*d57664e9SAndroid Build Coastguard Worker }
286*d57664e9SAndroid Build Coastguard Worker
287*d57664e9SAndroid Build Coastguard Worker if (best_value != nullptr) {
288*d57664e9SAndroid Build Coastguard Worker if (!value->config.isBetterThan(best_value->config, &match)) {
289*d57664e9SAndroid Build Coastguard Worker if (value->config.compare(best_value->config) != 0) {
290*d57664e9SAndroid Build Coastguard Worker continue;
291*d57664e9SAndroid Build Coastguard Worker }
292*d57664e9SAndroid Build Coastguard Worker }
293*d57664e9SAndroid Build Coastguard Worker }
294*d57664e9SAndroid Build Coastguard Worker
295*d57664e9SAndroid Build Coastguard Worker best_value = value.get();
296*d57664e9SAndroid Build Coastguard Worker }
297*d57664e9SAndroid Build Coastguard Worker
298*d57664e9SAndroid Build Coastguard Worker // The entry has no values
299*d57664e9SAndroid Build Coastguard Worker if (!best_value) {
300*d57664e9SAndroid Build Coastguard Worker return nullptr;
301*d57664e9SAndroid Build Coastguard Worker }
302*d57664e9SAndroid Build Coastguard Worker
303*d57664e9SAndroid Build Coastguard Worker return best_value->value.get();
304*d57664e9SAndroid Build Coastguard Worker }
305*d57664e9SAndroid Build Coastguard Worker
306*d57664e9SAndroid Build Coastguard Worker /** Retrieves the resource assigned to the specified resource id if one exists. */
FindValueById(const ResourceTable * table,const ResourceId & res_id,const ConfigDescription & config=DefaultConfig ())307*d57664e9SAndroid Build Coastguard Worker Value* FindValueById(const ResourceTable* table, const ResourceId& res_id,
308*d57664e9SAndroid Build Coastguard Worker const ConfigDescription& config = DefaultConfig()) {
309*d57664e9SAndroid Build Coastguard Worker if (table) {
310*d57664e9SAndroid Build Coastguard Worker for (auto& package : table->packages) {
311*d57664e9SAndroid Build Coastguard Worker for (auto& type : package->types) {
312*d57664e9SAndroid Build Coastguard Worker for (auto& entry : type->entries) {
313*d57664e9SAndroid Build Coastguard Worker if (entry->id && entry->id.value() == res_id.id) {
314*d57664e9SAndroid Build Coastguard Worker if (auto value = BestConfigValue(entry.get(), config)) {
315*d57664e9SAndroid Build Coastguard Worker return value;
316*d57664e9SAndroid Build Coastguard Worker }
317*d57664e9SAndroid Build Coastguard Worker }
318*d57664e9SAndroid Build Coastguard Worker }
319*d57664e9SAndroid Build Coastguard Worker }
320*d57664e9SAndroid Build Coastguard Worker }
321*d57664e9SAndroid Build Coastguard Worker }
322*d57664e9SAndroid Build Coastguard Worker return nullptr;
323*d57664e9SAndroid Build Coastguard Worker }
324*d57664e9SAndroid Build Coastguard Worker
325*d57664e9SAndroid Build Coastguard Worker /** Attempts to resolve the reference to a non-reference value. */
ResolveReference(Reference * ref,const ConfigDescription & config=DefaultConfig ())326*d57664e9SAndroid Build Coastguard Worker Value* ResolveReference(Reference* ref, const ConfigDescription& config = DefaultConfig()) {
327*d57664e9SAndroid Build Coastguard Worker const int kMaxIterations = 40;
328*d57664e9SAndroid Build Coastguard Worker int i = 0;
329*d57664e9SAndroid Build Coastguard Worker while (ref && ref->id && i++ < kMaxIterations) {
330*d57664e9SAndroid Build Coastguard Worker auto table = extractor_->apk_->GetResourceTable();
331*d57664e9SAndroid Build Coastguard Worker if (auto value = FindValueById(table, ref->id.value(), config)) {
332*d57664e9SAndroid Build Coastguard Worker if (ValueCast<Reference>(value)) {
333*d57664e9SAndroid Build Coastguard Worker ref = ValueCast<Reference>(value);
334*d57664e9SAndroid Build Coastguard Worker } else {
335*d57664e9SAndroid Build Coastguard Worker return value;
336*d57664e9SAndroid Build Coastguard Worker }
337*d57664e9SAndroid Build Coastguard Worker }
338*d57664e9SAndroid Build Coastguard Worker }
339*d57664e9SAndroid Build Coastguard Worker return nullptr;
340*d57664e9SAndroid Build Coastguard Worker }
341*d57664e9SAndroid Build Coastguard Worker
342*d57664e9SAndroid Build Coastguard Worker /**
343*d57664e9SAndroid Build Coastguard Worker * Retrieves the integer value of the attribute . If the value of the attribute is a reference,
344*d57664e9SAndroid Build Coastguard Worker * this will attempt to resolve the reference to an integer value.
345*d57664e9SAndroid Build Coastguard Worker **/
GetAttributeInteger(xml::Attribute * attr,const ConfigDescription & config=DefaultConfig ())346*d57664e9SAndroid Build Coastguard Worker int32_t* GetAttributeInteger(xml::Attribute* attr,
347*d57664e9SAndroid Build Coastguard Worker const ConfigDescription& config = DefaultConfig()) {
348*d57664e9SAndroid Build Coastguard Worker if (attr != nullptr) {
349*d57664e9SAndroid Build Coastguard Worker if (attr->compiled_value) {
350*d57664e9SAndroid Build Coastguard Worker // Resolve references using the configuration
351*d57664e9SAndroid Build Coastguard Worker Value* value = attr->compiled_value.get();
352*d57664e9SAndroid Build Coastguard Worker if (ValueCast<Reference>(value)) {
353*d57664e9SAndroid Build Coastguard Worker value = ResolveReference(ValueCast<Reference>(value), config);
354*d57664e9SAndroid Build Coastguard Worker } else {
355*d57664e9SAndroid Build Coastguard Worker value = attr->compiled_value.get();
356*d57664e9SAndroid Build Coastguard Worker }
357*d57664e9SAndroid Build Coastguard Worker // Retrieve the integer data if possible
358*d57664e9SAndroid Build Coastguard Worker if (value != nullptr) {
359*d57664e9SAndroid Build Coastguard Worker if (BinaryPrimitive* intValue = ValueCast<BinaryPrimitive>(value)) {
360*d57664e9SAndroid Build Coastguard Worker return (int32_t*) &intValue->value.data;
361*d57664e9SAndroid Build Coastguard Worker }
362*d57664e9SAndroid Build Coastguard Worker }
363*d57664e9SAndroid Build Coastguard Worker }
364*d57664e9SAndroid Build Coastguard Worker }
365*d57664e9SAndroid Build Coastguard Worker return nullptr;
366*d57664e9SAndroid Build Coastguard Worker }
367*d57664e9SAndroid Build Coastguard Worker
368*d57664e9SAndroid Build Coastguard Worker /**
369*d57664e9SAndroid Build Coastguard Worker * A version of GetAttributeInteger that returns a default integer if the attribute does not
370*d57664e9SAndroid Build Coastguard Worker * exist or cannot be resolved to an integer value.
371*d57664e9SAndroid Build Coastguard Worker **/
GetAttributeIntegerDefault(xml::Attribute * attr,int32_t def,const ConfigDescription & config=DefaultConfig ())372*d57664e9SAndroid Build Coastguard Worker int32_t GetAttributeIntegerDefault(xml::Attribute* attr, int32_t def,
373*d57664e9SAndroid Build Coastguard Worker const ConfigDescription& config = DefaultConfig()) {
374*d57664e9SAndroid Build Coastguard Worker auto value = GetAttributeInteger(attr, config);
375*d57664e9SAndroid Build Coastguard Worker if (value) {
376*d57664e9SAndroid Build Coastguard Worker return *value;
377*d57664e9SAndroid Build Coastguard Worker }
378*d57664e9SAndroid Build Coastguard Worker return def;
379*d57664e9SAndroid Build Coastguard Worker }
380*d57664e9SAndroid Build Coastguard Worker
381*d57664e9SAndroid Build Coastguard Worker /**
382*d57664e9SAndroid Build Coastguard Worker * Retrieves the string value of the attribute. If the value of the attribute is a reference,
383*d57664e9SAndroid Build Coastguard Worker * this will attempt to resolve the reference to a string value.
384*d57664e9SAndroid Build Coastguard Worker **/
GetAttributeString(xml::Attribute * attr,const ConfigDescription & config=DefaultConfig ())385*d57664e9SAndroid Build Coastguard Worker const std::string* GetAttributeString(xml::Attribute* attr,
386*d57664e9SAndroid Build Coastguard Worker const ConfigDescription& config = DefaultConfig()) {
387*d57664e9SAndroid Build Coastguard Worker if (attr != nullptr) {
388*d57664e9SAndroid Build Coastguard Worker if (attr->compiled_value) {
389*d57664e9SAndroid Build Coastguard Worker // Resolve references using the configuration
390*d57664e9SAndroid Build Coastguard Worker Value* value = attr->compiled_value.get();
391*d57664e9SAndroid Build Coastguard Worker if (ValueCast<Reference>(value)) {
392*d57664e9SAndroid Build Coastguard Worker value = ResolveReference(ValueCast<Reference>(value), config);
393*d57664e9SAndroid Build Coastguard Worker } else {
394*d57664e9SAndroid Build Coastguard Worker value = attr->compiled_value.get();
395*d57664e9SAndroid Build Coastguard Worker }
396*d57664e9SAndroid Build Coastguard Worker
397*d57664e9SAndroid Build Coastguard Worker // Retrieve the string data of the value if possible
398*d57664e9SAndroid Build Coastguard Worker if (value != nullptr) {
399*d57664e9SAndroid Build Coastguard Worker if (String* intValue = ValueCast<String>(value)) {
400*d57664e9SAndroid Build Coastguard Worker return &(*intValue->value);
401*d57664e9SAndroid Build Coastguard Worker } else if (RawString* rawValue = ValueCast<RawString>(value)) {
402*d57664e9SAndroid Build Coastguard Worker return &(*rawValue->value);
403*d57664e9SAndroid Build Coastguard Worker } else if (StyledString* styledStrValue = ValueCast<StyledString>(value)) {
404*d57664e9SAndroid Build Coastguard Worker return &(styledStrValue->value->value);
405*d57664e9SAndroid Build Coastguard Worker } else if (FileReference* strValue = ValueCast<FileReference>(value)) {
406*d57664e9SAndroid Build Coastguard Worker return &(*strValue->path);
407*d57664e9SAndroid Build Coastguard Worker }
408*d57664e9SAndroid Build Coastguard Worker }
409*d57664e9SAndroid Build Coastguard Worker }
410*d57664e9SAndroid Build Coastguard Worker
411*d57664e9SAndroid Build Coastguard Worker if (!attr->value.empty()) {
412*d57664e9SAndroid Build Coastguard Worker return &attr->value;
413*d57664e9SAndroid Build Coastguard Worker }
414*d57664e9SAndroid Build Coastguard Worker }
415*d57664e9SAndroid Build Coastguard Worker return nullptr;
416*d57664e9SAndroid Build Coastguard Worker }
417*d57664e9SAndroid Build Coastguard Worker
418*d57664e9SAndroid Build Coastguard Worker /**
419*d57664e9SAndroid Build Coastguard Worker * A version of GetAttributeString that returns a default string if the attribute does not
420*d57664e9SAndroid Build Coastguard Worker * exist or cannot be resolved to an string value.
421*d57664e9SAndroid Build Coastguard Worker **/
GetAttributeStringDefault(xml::Attribute * attr,std::string def,const ConfigDescription & config=DefaultConfig ())422*d57664e9SAndroid Build Coastguard Worker std::string GetAttributeStringDefault(xml::Attribute* attr, std::string def,
423*d57664e9SAndroid Build Coastguard Worker const ConfigDescription& config = DefaultConfig()) {
424*d57664e9SAndroid Build Coastguard Worker auto value = GetAttributeString(attr, config);
425*d57664e9SAndroid Build Coastguard Worker if (value) {
426*d57664e9SAndroid Build Coastguard Worker return *value;
427*d57664e9SAndroid Build Coastguard Worker }
428*d57664e9SAndroid Build Coastguard Worker return def;
429*d57664e9SAndroid Build Coastguard Worker }
430*d57664e9SAndroid Build Coastguard Worker
431*d57664e9SAndroid Build Coastguard Worker private:
432*d57664e9SAndroid Build Coastguard Worker ManifestExtractor* extractor_;
433*d57664e9SAndroid Build Coastguard Worker std::vector<std::unique_ptr<Element>> children_;
434*d57664e9SAndroid Build Coastguard Worker std::string tag_;
435*d57664e9SAndroid Build Coastguard Worker bool featured_ = false;
436*d57664e9SAndroid Build Coastguard Worker };
437*d57664e9SAndroid Build Coastguard Worker
438*d57664e9SAndroid Build Coastguard Worker friend Element;
439*d57664e9SAndroid Build Coastguard Worker
440*d57664e9SAndroid Build Coastguard Worker /** Creates a default configuration used to retrieve resources. */
DefaultConfig()441*d57664e9SAndroid Build Coastguard Worker static ConfigDescription DefaultConfig() {
442*d57664e9SAndroid Build Coastguard Worker ConfigDescription config;
443*d57664e9SAndroid Build Coastguard Worker config.orientation = android::ResTable_config::ORIENTATION_PORT;
444*d57664e9SAndroid Build Coastguard Worker config.density = android::ResTable_config::DENSITY_MEDIUM;
445*d57664e9SAndroid Build Coastguard Worker config.sdkVersion = SDK_CUR_DEVELOPMENT; // Very high.
446*d57664e9SAndroid Build Coastguard Worker config.screenWidthDp = 320;
447*d57664e9SAndroid Build Coastguard Worker config.screenHeightDp = 480;
448*d57664e9SAndroid Build Coastguard Worker config.smallestScreenWidthDp = 320;
449*d57664e9SAndroid Build Coastguard Worker config.screenLayout |= android::ResTable_config::SCREENSIZE_NORMAL;
450*d57664e9SAndroid Build Coastguard Worker return config;
451*d57664e9SAndroid Build Coastguard Worker }
452*d57664e9SAndroid Build Coastguard Worker
453*d57664e9SAndroid Build Coastguard Worker bool Extract(android::IDiagnostics* diag);
454*d57664e9SAndroid Build Coastguard Worker bool Dump(text::Printer* printer);
455*d57664e9SAndroid Build Coastguard Worker bool DumpProto(pb::Badging* out_badging);
456*d57664e9SAndroid Build Coastguard Worker
457*d57664e9SAndroid Build Coastguard Worker /** Recursively visit the xml element tree and return a processed badging element tree. */
458*d57664e9SAndroid Build Coastguard Worker std::unique_ptr<Element> Visit(xml::Element* element, const std::string& parent_tag);
459*d57664e9SAndroid Build Coastguard Worker
460*d57664e9SAndroid Build Coastguard Worker /** Resets target SDK to 0. */
ResetTargetSdk()461*d57664e9SAndroid Build Coastguard Worker void ResetTargetSdk() {
462*d57664e9SAndroid Build Coastguard Worker target_sdk_ = 0;
463*d57664e9SAndroid Build Coastguard Worker }
464*d57664e9SAndroid Build Coastguard Worker
465*d57664e9SAndroid Build Coastguard Worker /** Raises the target sdk value if the min target is greater than the current target. */
RaiseTargetSdk(int32_t min_target)466*d57664e9SAndroid Build Coastguard Worker void RaiseTargetSdk(int32_t min_target) {
467*d57664e9SAndroid Build Coastguard Worker if (min_target > target_sdk_) {
468*d57664e9SAndroid Build Coastguard Worker target_sdk_ = min_target;
469*d57664e9SAndroid Build Coastguard Worker }
470*d57664e9SAndroid Build Coastguard Worker }
471*d57664e9SAndroid Build Coastguard Worker
472*d57664e9SAndroid Build Coastguard Worker /**
473*d57664e9SAndroid Build Coastguard Worker * Retrieves the default feature group that features are added into when <uses-feature>
474*d57664e9SAndroid Build Coastguard Worker * are not in a <feature-group> element.
475*d57664e9SAndroid Build Coastguard Worker **/
common_feature_group()476*d57664e9SAndroid Build Coastguard Worker CommonFeatureGroup* common_feature_group() {
477*d57664e9SAndroid Build Coastguard Worker return commonFeatureGroup_.get();
478*d57664e9SAndroid Build Coastguard Worker }
479*d57664e9SAndroid Build Coastguard Worker
480*d57664e9SAndroid Build Coastguard Worker /**
481*d57664e9SAndroid Build Coastguard Worker * Retrieves a mapping of density values to Configurations for retrieving resources that would be
482*d57664e9SAndroid Build Coastguard Worker * used for that density setting.
483*d57664e9SAndroid Build Coastguard Worker **/
densities() const484*d57664e9SAndroid Build Coastguard Worker const std::map<uint16_t, ConfigDescription> densities() const {
485*d57664e9SAndroid Build Coastguard Worker return densities_;
486*d57664e9SAndroid Build Coastguard Worker }
487*d57664e9SAndroid Build Coastguard Worker
488*d57664e9SAndroid Build Coastguard Worker /**
489*d57664e9SAndroid Build Coastguard Worker * Retrieves a mapping of locale BCP 47 strings to Configurations for retrieving resources that
490*d57664e9SAndroid Build Coastguard Worker * would be used for that locale setting.
491*d57664e9SAndroid Build Coastguard Worker **/
locales() const492*d57664e9SAndroid Build Coastguard Worker const std::map<std::string, ConfigDescription> locales() const {
493*d57664e9SAndroid Build Coastguard Worker return locales_;
494*d57664e9SAndroid Build Coastguard Worker }
495*d57664e9SAndroid Build Coastguard Worker
496*d57664e9SAndroid Build Coastguard Worker /** Retrieves the current stack of parent during data extraction. */
parent_stack() const497*d57664e9SAndroid Build Coastguard Worker const std::vector<Element*>& parent_stack() const {
498*d57664e9SAndroid Build Coastguard Worker return parent_stack_;
499*d57664e9SAndroid Build Coastguard Worker }
500*d57664e9SAndroid Build Coastguard Worker
target_sdk() const501*d57664e9SAndroid Build Coastguard Worker int32_t target_sdk() const {
502*d57664e9SAndroid Build Coastguard Worker return target_sdk_;
503*d57664e9SAndroid Build Coastguard Worker }
504*d57664e9SAndroid Build Coastguard Worker
505*d57664e9SAndroid Build Coastguard Worker LoadedApk* const apk_;
506*d57664e9SAndroid Build Coastguard Worker DumpManifestOptions& options_;
507*d57664e9SAndroid Build Coastguard Worker
508*d57664e9SAndroid Build Coastguard Worker private:
509*d57664e9SAndroid Build Coastguard Worker std::unique_ptr<xml::XmlResource> doc_;
510*d57664e9SAndroid Build Coastguard Worker std::unique_ptr<CommonFeatureGroup> commonFeatureGroup_;
511*d57664e9SAndroid Build Coastguard Worker std::map<std::string, ConfigDescription> locales_;
512*d57664e9SAndroid Build Coastguard Worker std::map<uint16_t, ConfigDescription> densities_;
513*d57664e9SAndroid Build Coastguard Worker std::vector<Element*> parent_stack_;
514*d57664e9SAndroid Build Coastguard Worker int32_t target_sdk_ = 0;
515*d57664e9SAndroid Build Coastguard Worker
516*d57664e9SAndroid Build Coastguard Worker std::unique_ptr<ManifestExtractor::Element> root_element_;
517*d57664e9SAndroid Build Coastguard Worker std::vector<std::unique_ptr<ManifestExtractor::Element>> implied_permissions_;
518*d57664e9SAndroid Build Coastguard Worker std::vector<FeatureGroup*> feature_groups_;
519*d57664e9SAndroid Build Coastguard Worker Components components_;
520*d57664e9SAndroid Build Coastguard Worker Architectures architectures_;
521*d57664e9SAndroid Build Coastguard Worker const SupportsScreen* supports_screen_;
522*d57664e9SAndroid Build Coastguard Worker };
523*d57664e9SAndroid Build Coastguard Worker
524*d57664e9SAndroid Build Coastguard Worker template<typename T> T* ElementCast(ManifestExtractor::Element* element);
525*d57664e9SAndroid Build Coastguard Worker
526*d57664e9SAndroid Build Coastguard Worker /** Recurs through the children of the specified root in depth-first order. */
ForEachChild(ManifestExtractor::Element * root,std::function<void (ManifestExtractor::Element *)> f)527*d57664e9SAndroid Build Coastguard Worker static void ForEachChild(ManifestExtractor::Element* root,
528*d57664e9SAndroid Build Coastguard Worker std::function<void(ManifestExtractor::Element*)> f) {
529*d57664e9SAndroid Build Coastguard Worker for (auto& child : root->children()) {
530*d57664e9SAndroid Build Coastguard Worker f(child.get());
531*d57664e9SAndroid Build Coastguard Worker ForEachChild(child.get(), f);
532*d57664e9SAndroid Build Coastguard Worker }
533*d57664e9SAndroid Build Coastguard Worker }
534*d57664e9SAndroid Build Coastguard Worker
535*d57664e9SAndroid Build Coastguard Worker /**
536*d57664e9SAndroid Build Coastguard Worker * Checks the element and its recursive children for an element that makes the specified
537*d57664e9SAndroid Build Coastguard Worker * conditional function return true. Returns the first element that makes the conditional function
538*d57664e9SAndroid Build Coastguard Worker * return true.
539*d57664e9SAndroid Build Coastguard Worker **/
FindElement(ManifestExtractor::Element * root,std::function<bool (ManifestExtractor::Element *)> f)540*d57664e9SAndroid Build Coastguard Worker static ManifestExtractor::Element* FindElement(ManifestExtractor::Element* root,
541*d57664e9SAndroid Build Coastguard Worker std::function<bool(ManifestExtractor::Element*)> f) {
542*d57664e9SAndroid Build Coastguard Worker if (f(root)) {
543*d57664e9SAndroid Build Coastguard Worker return root;
544*d57664e9SAndroid Build Coastguard Worker }
545*d57664e9SAndroid Build Coastguard Worker const auto& children = root->children();
546*d57664e9SAndroid Build Coastguard Worker for (auto it = children.rbegin(); it != children.rend(); ++it) {
547*d57664e9SAndroid Build Coastguard Worker if (auto b2 = FindElement(it->get(), f)) {
548*d57664e9SAndroid Build Coastguard Worker return b2;
549*d57664e9SAndroid Build Coastguard Worker }
550*d57664e9SAndroid Build Coastguard Worker }
551*d57664e9SAndroid Build Coastguard Worker return nullptr;
552*d57664e9SAndroid Build Coastguard Worker }
553*d57664e9SAndroid Build Coastguard Worker
554*d57664e9SAndroid Build Coastguard Worker /** Represents the <manifest> elements **/
555*d57664e9SAndroid Build Coastguard Worker class Manifest : public ManifestExtractor::Element {
556*d57664e9SAndroid Build Coastguard Worker public:
557*d57664e9SAndroid Build Coastguard Worker Manifest() = default;
558*d57664e9SAndroid Build Coastguard Worker bool only_package_name;
559*d57664e9SAndroid Build Coastguard Worker std::string package;
560*d57664e9SAndroid Build Coastguard Worker int32_t versionCode;
561*d57664e9SAndroid Build Coastguard Worker std::string versionName;
562*d57664e9SAndroid Build Coastguard Worker const std::string* split = nullptr;
563*d57664e9SAndroid Build Coastguard Worker const std::string* platformVersionName = nullptr;
564*d57664e9SAndroid Build Coastguard Worker const std::string* platformVersionCode = nullptr;
565*d57664e9SAndroid Build Coastguard Worker const int32_t* platformVersionNameInt = nullptr;
566*d57664e9SAndroid Build Coastguard Worker const int32_t* platformVersionCodeInt = nullptr;
567*d57664e9SAndroid Build Coastguard Worker const int32_t* compilesdkVersion = nullptr;
568*d57664e9SAndroid Build Coastguard Worker const std::string* compilesdkVersionCodename = nullptr;
569*d57664e9SAndroid Build Coastguard Worker const int32_t* installLocation = nullptr;
570*d57664e9SAndroid Build Coastguard Worker
Extract(xml::Element * manifest)571*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* manifest) override {
572*d57664e9SAndroid Build Coastguard Worker package = GetAttributeStringDefault(FindAttribute(manifest, {}, "package"), "");
573*d57664e9SAndroid Build Coastguard Worker versionCode = GetAttributeIntegerDefault(FindAttribute(manifest, VERSION_CODE_ATTR), 0);
574*d57664e9SAndroid Build Coastguard Worker versionName = GetAttributeStringDefault(FindAttribute(manifest, VERSION_NAME_ATTR), "");
575*d57664e9SAndroid Build Coastguard Worker split = GetAttributeString(FindAttribute(manifest, {}, "split"));
576*d57664e9SAndroid Build Coastguard Worker
577*d57664e9SAndroid Build Coastguard Worker // Extract the platform build info
578*d57664e9SAndroid Build Coastguard Worker platformVersionName = GetAttributeString(FindAttribute(manifest, {},
579*d57664e9SAndroid Build Coastguard Worker "platformBuildVersionName"));
580*d57664e9SAndroid Build Coastguard Worker platformVersionCode = GetAttributeString(FindAttribute(manifest, {},
581*d57664e9SAndroid Build Coastguard Worker "platformBuildVersionCode"));
582*d57664e9SAndroid Build Coastguard Worker platformVersionNameInt = GetAttributeInteger(FindAttribute(manifest, {},
583*d57664e9SAndroid Build Coastguard Worker "platformBuildVersionName"));
584*d57664e9SAndroid Build Coastguard Worker platformVersionCodeInt = GetAttributeInteger(FindAttribute(manifest, {},
585*d57664e9SAndroid Build Coastguard Worker "platformBuildVersionCode"));
586*d57664e9SAndroid Build Coastguard Worker
587*d57664e9SAndroid Build Coastguard Worker // Extract the compile sdk info
588*d57664e9SAndroid Build Coastguard Worker compilesdkVersion = GetAttributeInteger(FindAttribute(manifest, COMPILE_SDK_VERSION_ATTR));
589*d57664e9SAndroid Build Coastguard Worker compilesdkVersionCodename = GetAttributeString(
590*d57664e9SAndroid Build Coastguard Worker FindAttribute(manifest, COMPILE_SDK_VERSION_CODENAME_ATTR));
591*d57664e9SAndroid Build Coastguard Worker installLocation = GetAttributeInteger(FindAttribute(manifest, INSTALL_LOCATION_ATTR));
592*d57664e9SAndroid Build Coastguard Worker }
593*d57664e9SAndroid Build Coastguard Worker
ToProto(pb::Badging * out_badging)594*d57664e9SAndroid Build Coastguard Worker void ToProto(pb::Badging* out_badging) override {
595*d57664e9SAndroid Build Coastguard Worker auto out_package = out_badging->mutable_package();
596*d57664e9SAndroid Build Coastguard Worker out_package->set_package(package);
597*d57664e9SAndroid Build Coastguard Worker out_package->set_version_code(versionCode);
598*d57664e9SAndroid Build Coastguard Worker out_package->set_version_name(versionName);
599*d57664e9SAndroid Build Coastguard Worker if (compilesdkVersion) {
600*d57664e9SAndroid Build Coastguard Worker out_package->set_compile_sdk_version(*compilesdkVersion);
601*d57664e9SAndroid Build Coastguard Worker }
602*d57664e9SAndroid Build Coastguard Worker if (compilesdkVersionCodename) {
603*d57664e9SAndroid Build Coastguard Worker out_package->set_compile_sdk_version_codename(*compilesdkVersionCodename);
604*d57664e9SAndroid Build Coastguard Worker }
605*d57664e9SAndroid Build Coastguard Worker if (platformVersionName) {
606*d57664e9SAndroid Build Coastguard Worker out_package->set_platform_version_name(*platformVersionName);
607*d57664e9SAndroid Build Coastguard Worker } else if (platformVersionNameInt) {
608*d57664e9SAndroid Build Coastguard Worker out_package->set_platform_version_name(std::to_string(*platformVersionNameInt));
609*d57664e9SAndroid Build Coastguard Worker }
610*d57664e9SAndroid Build Coastguard Worker if (platformVersionCode) {
611*d57664e9SAndroid Build Coastguard Worker out_package->set_platform_version_code(*platformVersionCode);
612*d57664e9SAndroid Build Coastguard Worker } else if (platformVersionCodeInt) {
613*d57664e9SAndroid Build Coastguard Worker out_package->set_platform_version_code(std::to_string(*platformVersionCodeInt));
614*d57664e9SAndroid Build Coastguard Worker }
615*d57664e9SAndroid Build Coastguard Worker
616*d57664e9SAndroid Build Coastguard Worker if (installLocation) {
617*d57664e9SAndroid Build Coastguard Worker switch (*installLocation) {
618*d57664e9SAndroid Build Coastguard Worker case 0:
619*d57664e9SAndroid Build Coastguard Worker out_package->set_install_location(pb::PackageInfo_InstallLocation_AUTO);
620*d57664e9SAndroid Build Coastguard Worker break;
621*d57664e9SAndroid Build Coastguard Worker case 1:
622*d57664e9SAndroid Build Coastguard Worker out_package->set_install_location(pb::PackageInfo_InstallLocation_INTERNAL_ONLY);
623*d57664e9SAndroid Build Coastguard Worker break;
624*d57664e9SAndroid Build Coastguard Worker case 2:
625*d57664e9SAndroid Build Coastguard Worker out_package->set_install_location(pb::PackageInfo_InstallLocation_PREFER_EXTERNAL);
626*d57664e9SAndroid Build Coastguard Worker break;
627*d57664e9SAndroid Build Coastguard Worker default:
628*d57664e9SAndroid Build Coastguard Worker break;
629*d57664e9SAndroid Build Coastguard Worker }
630*d57664e9SAndroid Build Coastguard Worker }
631*d57664e9SAndroid Build Coastguard Worker }
632*d57664e9SAndroid Build Coastguard Worker
Print(text::Printer * printer)633*d57664e9SAndroid Build Coastguard Worker void Print(text::Printer* printer) override {
634*d57664e9SAndroid Build Coastguard Worker if (only_package_name) {
635*d57664e9SAndroid Build Coastguard Worker printer->Println(StringPrintf("package: %s", package.data()));
636*d57664e9SAndroid Build Coastguard Worker } else {
637*d57664e9SAndroid Build Coastguard Worker PrintFull(printer);
638*d57664e9SAndroid Build Coastguard Worker }
639*d57664e9SAndroid Build Coastguard Worker }
640*d57664e9SAndroid Build Coastguard Worker
PrintFull(text::Printer * printer)641*d57664e9SAndroid Build Coastguard Worker void PrintFull(text::Printer* printer) {
642*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("package: name='%s' ", package.data()));
643*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("versionCode='%s' ",
644*d57664e9SAndroid Build Coastguard Worker (versionCode > 0) ? std::to_string(versionCode).data() : ""));
645*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("versionName='%s'", versionName.data()));
646*d57664e9SAndroid Build Coastguard Worker
647*d57664e9SAndroid Build Coastguard Worker if (split) {
648*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" split='%s'", split->data()));
649*d57664e9SAndroid Build Coastguard Worker }
650*d57664e9SAndroid Build Coastguard Worker if (platformVersionName) {
651*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" platformBuildVersionName='%s'", platformVersionName->data()));
652*d57664e9SAndroid Build Coastguard Worker } else if (platformVersionNameInt) {
653*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" platformBuildVersionName='%d'", *platformVersionNameInt));
654*d57664e9SAndroid Build Coastguard Worker }
655*d57664e9SAndroid Build Coastguard Worker if (platformVersionCode) {
656*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" platformBuildVersionCode='%s'", platformVersionCode->data()));
657*d57664e9SAndroid Build Coastguard Worker } else if (platformVersionCodeInt) {
658*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" platformBuildVersionCode='%d'", *platformVersionCodeInt));
659*d57664e9SAndroid Build Coastguard Worker }
660*d57664e9SAndroid Build Coastguard Worker if (compilesdkVersion) {
661*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" compileSdkVersion='%d'", *compilesdkVersion));
662*d57664e9SAndroid Build Coastguard Worker }
663*d57664e9SAndroid Build Coastguard Worker if (compilesdkVersionCodename) {
664*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" compileSdkVersionCodename='%s'",
665*d57664e9SAndroid Build Coastguard Worker compilesdkVersionCodename->data()));
666*d57664e9SAndroid Build Coastguard Worker }
667*d57664e9SAndroid Build Coastguard Worker printer->Print("\n");
668*d57664e9SAndroid Build Coastguard Worker
669*d57664e9SAndroid Build Coastguard Worker if (installLocation) {
670*d57664e9SAndroid Build Coastguard Worker switch (*installLocation) {
671*d57664e9SAndroid Build Coastguard Worker case 0:
672*d57664e9SAndroid Build Coastguard Worker printer->Print("install-location:'auto'\n");
673*d57664e9SAndroid Build Coastguard Worker break;
674*d57664e9SAndroid Build Coastguard Worker case 1:
675*d57664e9SAndroid Build Coastguard Worker printer->Print("install-location:'internalOnly'\n");
676*d57664e9SAndroid Build Coastguard Worker break;
677*d57664e9SAndroid Build Coastguard Worker case 2:
678*d57664e9SAndroid Build Coastguard Worker printer->Print("install-location:'preferExternal'\n");
679*d57664e9SAndroid Build Coastguard Worker break;
680*d57664e9SAndroid Build Coastguard Worker default:
681*d57664e9SAndroid Build Coastguard Worker break;
682*d57664e9SAndroid Build Coastguard Worker }
683*d57664e9SAndroid Build Coastguard Worker }
684*d57664e9SAndroid Build Coastguard Worker }
685*d57664e9SAndroid Build Coastguard Worker };
686*d57664e9SAndroid Build Coastguard Worker
687*d57664e9SAndroid Build Coastguard Worker /** Represents <application> elements. **/
688*d57664e9SAndroid Build Coastguard Worker class Application : public ManifestExtractor::Element {
689*d57664e9SAndroid Build Coastguard Worker public:
690*d57664e9SAndroid Build Coastguard Worker Application() = default;
691*d57664e9SAndroid Build Coastguard Worker std::string label;
692*d57664e9SAndroid Build Coastguard Worker std::string icon;
693*d57664e9SAndroid Build Coastguard Worker std::string banner;
694*d57664e9SAndroid Build Coastguard Worker int32_t is_game;
695*d57664e9SAndroid Build Coastguard Worker int32_t debuggable;
696*d57664e9SAndroid Build Coastguard Worker int32_t test_only;
697*d57664e9SAndroid Build Coastguard Worker bool has_multi_arch;
698*d57664e9SAndroid Build Coastguard Worker
699*d57664e9SAndroid Build Coastguard Worker /** Mapping from locales to app names. */
700*d57664e9SAndroid Build Coastguard Worker std::map<std::string, std::string> locale_labels;
701*d57664e9SAndroid Build Coastguard Worker
702*d57664e9SAndroid Build Coastguard Worker /** Mapping from densities to app icons. */
703*d57664e9SAndroid Build Coastguard Worker std::map<uint16_t, std::string> density_icons;
704*d57664e9SAndroid Build Coastguard Worker
Extract(xml::Element * element)705*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* element) override {
706*d57664e9SAndroid Build Coastguard Worker label = GetAttributeStringDefault(FindAttribute(element, LABEL_ATTR), "");
707*d57664e9SAndroid Build Coastguard Worker icon = GetAttributeStringDefault(FindAttribute(element, ICON_ATTR), "");
708*d57664e9SAndroid Build Coastguard Worker test_only = GetAttributeIntegerDefault(FindAttribute(element, TEST_ONLY_ATTR), 0);
709*d57664e9SAndroid Build Coastguard Worker banner = GetAttributeStringDefault(FindAttribute(element, BANNER_ATTR), "");
710*d57664e9SAndroid Build Coastguard Worker is_game = GetAttributeIntegerDefault(FindAttribute(element, ISGAME_ATTR), 0);
711*d57664e9SAndroid Build Coastguard Worker debuggable = GetAttributeIntegerDefault(FindAttribute(element, DEBUGGABLE_ATTR), 0);
712*d57664e9SAndroid Build Coastguard Worker
713*d57664e9SAndroid Build Coastguard Worker // We must search by name because the multiArch flag hasn't been API
714*d57664e9SAndroid Build Coastguard Worker // frozen yet.
715*d57664e9SAndroid Build Coastguard Worker has_multi_arch = (GetAttributeIntegerDefault(
716*d57664e9SAndroid Build Coastguard Worker FindAttribute(element, kAndroidNamespace, "multiArch"), 0) != 0);
717*d57664e9SAndroid Build Coastguard Worker
718*d57664e9SAndroid Build Coastguard Worker // Retrieve the app names for every locale the app supports
719*d57664e9SAndroid Build Coastguard Worker auto attr = FindAttribute(element, LABEL_ATTR);
720*d57664e9SAndroid Build Coastguard Worker for (auto& config : extractor()->locales()) {
721*d57664e9SAndroid Build Coastguard Worker if (auto label = GetAttributeString(attr, config.second)) {
722*d57664e9SAndroid Build Coastguard Worker if (label) {
723*d57664e9SAndroid Build Coastguard Worker locale_labels.insert(std::make_pair(config.first, *label));
724*d57664e9SAndroid Build Coastguard Worker }
725*d57664e9SAndroid Build Coastguard Worker }
726*d57664e9SAndroid Build Coastguard Worker }
727*d57664e9SAndroid Build Coastguard Worker
728*d57664e9SAndroid Build Coastguard Worker // Retrieve the icons for the densities the app supports
729*d57664e9SAndroid Build Coastguard Worker attr = FindAttribute(element, ICON_ATTR);
730*d57664e9SAndroid Build Coastguard Worker for (auto& config : extractor()->densities()) {
731*d57664e9SAndroid Build Coastguard Worker if (auto resource = GetAttributeString(attr, config.second)) {
732*d57664e9SAndroid Build Coastguard Worker if (resource) {
733*d57664e9SAndroid Build Coastguard Worker density_icons.insert(std::make_pair(config.first, *resource));
734*d57664e9SAndroid Build Coastguard Worker }
735*d57664e9SAndroid Build Coastguard Worker }
736*d57664e9SAndroid Build Coastguard Worker }
737*d57664e9SAndroid Build Coastguard Worker }
738*d57664e9SAndroid Build Coastguard Worker
Print(text::Printer * printer)739*d57664e9SAndroid Build Coastguard Worker void Print(text::Printer* printer) override {
740*d57664e9SAndroid Build Coastguard Worker // Print the labels for every locale
741*d57664e9SAndroid Build Coastguard Worker for (auto p : locale_labels) {
742*d57664e9SAndroid Build Coastguard Worker if (p.first.empty()) {
743*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("application-label:'%s'\n",
744*d57664e9SAndroid Build Coastguard Worker android::ResTable::normalizeForOutput(p.second.data())
745*d57664e9SAndroid Build Coastguard Worker .c_str()));
746*d57664e9SAndroid Build Coastguard Worker } else {
747*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("application-label-%s:'%s'\n", p.first.data(),
748*d57664e9SAndroid Build Coastguard Worker android::ResTable::normalizeForOutput(p.second.data())
749*d57664e9SAndroid Build Coastguard Worker .c_str()));
750*d57664e9SAndroid Build Coastguard Worker }
751*d57664e9SAndroid Build Coastguard Worker }
752*d57664e9SAndroid Build Coastguard Worker
753*d57664e9SAndroid Build Coastguard Worker // Print the icon paths for every density
754*d57664e9SAndroid Build Coastguard Worker for (auto p : density_icons) {
755*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("application-icon-%d:'%s'\n", p.first, p.second.data()));
756*d57664e9SAndroid Build Coastguard Worker }
757*d57664e9SAndroid Build Coastguard Worker
758*d57664e9SAndroid Build Coastguard Worker // Print the application info
759*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("application: label='%s' ",
760*d57664e9SAndroid Build Coastguard Worker android::ResTable::normalizeForOutput(label.data()).c_str()));
761*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("icon='%s'", icon.data()));
762*d57664e9SAndroid Build Coastguard Worker if (!banner.empty()) {
763*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" banner='%s'", banner.data()));
764*d57664e9SAndroid Build Coastguard Worker }
765*d57664e9SAndroid Build Coastguard Worker printer->Print("\n");
766*d57664e9SAndroid Build Coastguard Worker
767*d57664e9SAndroid Build Coastguard Worker if (test_only != 0) {
768*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("testOnly='%d'\n", test_only));
769*d57664e9SAndroid Build Coastguard Worker }
770*d57664e9SAndroid Build Coastguard Worker if (is_game != 0) {
771*d57664e9SAndroid Build Coastguard Worker printer->Print("application-isGame\n");
772*d57664e9SAndroid Build Coastguard Worker }
773*d57664e9SAndroid Build Coastguard Worker if (debuggable != 0) {
774*d57664e9SAndroid Build Coastguard Worker printer->Print("application-debuggable\n");
775*d57664e9SAndroid Build Coastguard Worker }
776*d57664e9SAndroid Build Coastguard Worker }
777*d57664e9SAndroid Build Coastguard Worker
ToProto(pb::Badging * out_badging)778*d57664e9SAndroid Build Coastguard Worker void ToProto(pb::Badging* out_badging) override {
779*d57664e9SAndroid Build Coastguard Worker auto application = out_badging->mutable_application();
780*d57664e9SAndroid Build Coastguard Worker application->set_label(android::ResTable::normalizeForOutput(label.data()));
781*d57664e9SAndroid Build Coastguard Worker application->set_icon(icon);
782*d57664e9SAndroid Build Coastguard Worker application->set_banner(banner);
783*d57664e9SAndroid Build Coastguard Worker application->set_test_only(test_only != 0);
784*d57664e9SAndroid Build Coastguard Worker application->set_game(is_game != 0);
785*d57664e9SAndroid Build Coastguard Worker application->set_debuggable(debuggable != 0);
786*d57664e9SAndroid Build Coastguard Worker
787*d57664e9SAndroid Build Coastguard Worker auto out_locale_labels = application->mutable_locale_labels();
788*d57664e9SAndroid Build Coastguard Worker for (auto& p : locale_labels) {
789*d57664e9SAndroid Build Coastguard Worker if (!p.first.empty()) {
790*d57664e9SAndroid Build Coastguard Worker (*out_locale_labels)[p.first] = p.second;
791*d57664e9SAndroid Build Coastguard Worker }
792*d57664e9SAndroid Build Coastguard Worker }
793*d57664e9SAndroid Build Coastguard Worker auto out_density_icons = application->mutable_density_icons();
794*d57664e9SAndroid Build Coastguard Worker for (auto& p : density_icons) {
795*d57664e9SAndroid Build Coastguard Worker (*out_density_icons)[p.first] = p.second;
796*d57664e9SAndroid Build Coastguard Worker }
797*d57664e9SAndroid Build Coastguard Worker }
798*d57664e9SAndroid Build Coastguard Worker };
799*d57664e9SAndroid Build Coastguard Worker
800*d57664e9SAndroid Build Coastguard Worker /** Represents <uses-sdk> elements. **/
801*d57664e9SAndroid Build Coastguard Worker class UsesSdkBadging : public ManifestExtractor::Element {
802*d57664e9SAndroid Build Coastguard Worker public:
803*d57664e9SAndroid Build Coastguard Worker UsesSdkBadging() = default;
804*d57664e9SAndroid Build Coastguard Worker const int32_t* min_sdk = nullptr;
805*d57664e9SAndroid Build Coastguard Worker const std::string* min_sdk_name = nullptr;
806*d57664e9SAndroid Build Coastguard Worker const int32_t* max_sdk = nullptr;
807*d57664e9SAndroid Build Coastguard Worker const int32_t* target_sdk = nullptr;
808*d57664e9SAndroid Build Coastguard Worker const std::string* target_sdk_name = nullptr;
809*d57664e9SAndroid Build Coastguard Worker
Extract(xml::Element * element)810*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* element) override {
811*d57664e9SAndroid Build Coastguard Worker min_sdk = GetAttributeInteger(FindAttribute(element, MIN_SDK_VERSION_ATTR));
812*d57664e9SAndroid Build Coastguard Worker min_sdk_name = GetAttributeString(FindAttribute(element, MIN_SDK_VERSION_ATTR));
813*d57664e9SAndroid Build Coastguard Worker max_sdk = GetAttributeInteger(FindAttribute(element, MAX_SDK_VERSION_ATTR));
814*d57664e9SAndroid Build Coastguard Worker target_sdk = GetAttributeInteger(FindAttribute(element, TARGET_SDK_VERSION_ATTR));
815*d57664e9SAndroid Build Coastguard Worker target_sdk_name = GetAttributeString(FindAttribute(element, TARGET_SDK_VERSION_ATTR));
816*d57664e9SAndroid Build Coastguard Worker
817*d57664e9SAndroid Build Coastguard Worker // Resets target SDK first. This is required if APK contains multiple <uses-sdk> elements,
818*d57664e9SAndroid Build Coastguard Worker // we only need to take the latest values.
819*d57664e9SAndroid Build Coastguard Worker extractor()->ResetTargetSdk();
820*d57664e9SAndroid Build Coastguard Worker
821*d57664e9SAndroid Build Coastguard Worker // Detect the target sdk of the element
822*d57664e9SAndroid Build Coastguard Worker if ((min_sdk_name && *min_sdk_name == "Donut")
823*d57664e9SAndroid Build Coastguard Worker || (target_sdk_name && *target_sdk_name == "Donut")) {
824*d57664e9SAndroid Build Coastguard Worker extractor()->RaiseTargetSdk(SDK_DONUT);
825*d57664e9SAndroid Build Coastguard Worker }
826*d57664e9SAndroid Build Coastguard Worker if (min_sdk) {
827*d57664e9SAndroid Build Coastguard Worker extractor()->RaiseTargetSdk(*min_sdk);
828*d57664e9SAndroid Build Coastguard Worker }
829*d57664e9SAndroid Build Coastguard Worker if (target_sdk) {
830*d57664e9SAndroid Build Coastguard Worker extractor()->RaiseTargetSdk(*target_sdk);
831*d57664e9SAndroid Build Coastguard Worker } else if (target_sdk_name) {
832*d57664e9SAndroid Build Coastguard Worker extractor()->RaiseTargetSdk(SDK_CUR_DEVELOPMENT);
833*d57664e9SAndroid Build Coastguard Worker }
834*d57664e9SAndroid Build Coastguard Worker }
835*d57664e9SAndroid Build Coastguard Worker
Print(text::Printer * printer)836*d57664e9SAndroid Build Coastguard Worker void Print(text::Printer* printer) override {
837*d57664e9SAndroid Build Coastguard Worker if (min_sdk) {
838*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("minSdkVersion:'%d'\n", *min_sdk));
839*d57664e9SAndroid Build Coastguard Worker } else if (min_sdk_name) {
840*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("minSdkVersion:'%s'\n", min_sdk_name->data()));
841*d57664e9SAndroid Build Coastguard Worker }
842*d57664e9SAndroid Build Coastguard Worker if (max_sdk) {
843*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("maxSdkVersion:'%d'\n", *max_sdk));
844*d57664e9SAndroid Build Coastguard Worker }
845*d57664e9SAndroid Build Coastguard Worker if (target_sdk) {
846*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("targetSdkVersion:'%d'\n", *target_sdk));
847*d57664e9SAndroid Build Coastguard Worker } else if (target_sdk_name) {
848*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("targetSdkVersion:'%s'\n", target_sdk_name->data()));
849*d57664e9SAndroid Build Coastguard Worker }
850*d57664e9SAndroid Build Coastguard Worker }
851*d57664e9SAndroid Build Coastguard Worker
ToProto(pb::Badging * out_badging)852*d57664e9SAndroid Build Coastguard Worker void ToProto(pb::Badging* out_badging) override {
853*d57664e9SAndroid Build Coastguard Worker auto out_sdks = out_badging->mutable_uses_sdk();
854*d57664e9SAndroid Build Coastguard Worker if (min_sdk) {
855*d57664e9SAndroid Build Coastguard Worker out_sdks->set_min_sdk_version(*min_sdk);
856*d57664e9SAndroid Build Coastguard Worker } else if (min_sdk_name) {
857*d57664e9SAndroid Build Coastguard Worker out_sdks->set_min_sdk_version_name(*min_sdk_name);
858*d57664e9SAndroid Build Coastguard Worker }
859*d57664e9SAndroid Build Coastguard Worker if (max_sdk) {
860*d57664e9SAndroid Build Coastguard Worker out_sdks->set_max_sdk_version(*max_sdk);
861*d57664e9SAndroid Build Coastguard Worker }
862*d57664e9SAndroid Build Coastguard Worker if (target_sdk) {
863*d57664e9SAndroid Build Coastguard Worker out_sdks->set_target_sdk_version(*target_sdk);
864*d57664e9SAndroid Build Coastguard Worker } else if (target_sdk_name) {
865*d57664e9SAndroid Build Coastguard Worker out_sdks->set_target_sdk_version_name(*target_sdk_name);
866*d57664e9SAndroid Build Coastguard Worker }
867*d57664e9SAndroid Build Coastguard Worker }
868*d57664e9SAndroid Build Coastguard Worker };
869*d57664e9SAndroid Build Coastguard Worker
870*d57664e9SAndroid Build Coastguard Worker /** Represents <uses-configuration> elements. **/
871*d57664e9SAndroid Build Coastguard Worker class UsesConfiguarion : public ManifestExtractor::Element {
872*d57664e9SAndroid Build Coastguard Worker public:
873*d57664e9SAndroid Build Coastguard Worker UsesConfiguarion() = default;
874*d57664e9SAndroid Build Coastguard Worker int32_t req_touch_screen = 0;
875*d57664e9SAndroid Build Coastguard Worker int32_t req_keyboard_type = 0;
876*d57664e9SAndroid Build Coastguard Worker int32_t req_hard_keyboard = 0;
877*d57664e9SAndroid Build Coastguard Worker int32_t req_navigation = 0;
878*d57664e9SAndroid Build Coastguard Worker int32_t req_five_way_nav = 0;
879*d57664e9SAndroid Build Coastguard Worker
Extract(xml::Element * element)880*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* element) override {
881*d57664e9SAndroid Build Coastguard Worker req_touch_screen = GetAttributeIntegerDefault(
882*d57664e9SAndroid Build Coastguard Worker FindAttribute(element, REQ_TOUCH_SCREEN_ATTR), 0);
883*d57664e9SAndroid Build Coastguard Worker req_keyboard_type = GetAttributeIntegerDefault(
884*d57664e9SAndroid Build Coastguard Worker FindAttribute(element, REQ_KEYBOARD_TYPE_ATTR), 0);
885*d57664e9SAndroid Build Coastguard Worker req_hard_keyboard = GetAttributeIntegerDefault(
886*d57664e9SAndroid Build Coastguard Worker FindAttribute(element, REQ_HARD_KEYBOARD_ATTR), 0);
887*d57664e9SAndroid Build Coastguard Worker req_navigation = GetAttributeIntegerDefault(
888*d57664e9SAndroid Build Coastguard Worker FindAttribute(element, REQ_NAVIGATION_ATTR), 0);
889*d57664e9SAndroid Build Coastguard Worker req_five_way_nav = GetAttributeIntegerDefault(
890*d57664e9SAndroid Build Coastguard Worker FindAttribute(element, REQ_FIVE_WAY_NAV_ATTR), 0);
891*d57664e9SAndroid Build Coastguard Worker }
892*d57664e9SAndroid Build Coastguard Worker
Print(text::Printer * printer)893*d57664e9SAndroid Build Coastguard Worker void Print(text::Printer* printer) override {
894*d57664e9SAndroid Build Coastguard Worker printer->Print("uses-configuration:");
895*d57664e9SAndroid Build Coastguard Worker if (req_touch_screen != 0) {
896*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" reqTouchScreen='%d'", req_touch_screen));
897*d57664e9SAndroid Build Coastguard Worker }
898*d57664e9SAndroid Build Coastguard Worker if (req_keyboard_type != 0) {
899*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" reqKeyboardType='%d'", req_keyboard_type));
900*d57664e9SAndroid Build Coastguard Worker }
901*d57664e9SAndroid Build Coastguard Worker if (req_hard_keyboard != 0) {
902*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" reqHardKeyboard='%d'", req_hard_keyboard));
903*d57664e9SAndroid Build Coastguard Worker }
904*d57664e9SAndroid Build Coastguard Worker if (req_navigation != 0) {
905*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" reqNavigation='%d'", req_navigation));
906*d57664e9SAndroid Build Coastguard Worker }
907*d57664e9SAndroid Build Coastguard Worker if (req_five_way_nav != 0) {
908*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" reqFiveWayNav='%d'", req_five_way_nav));
909*d57664e9SAndroid Build Coastguard Worker }
910*d57664e9SAndroid Build Coastguard Worker printer->Print("\n");
911*d57664e9SAndroid Build Coastguard Worker }
912*d57664e9SAndroid Build Coastguard Worker
ToProto(pb::Badging * out_badging)913*d57664e9SAndroid Build Coastguard Worker void ToProto(pb::Badging* out_badging) override {
914*d57664e9SAndroid Build Coastguard Worker auto out_configuration = out_badging->add_uses_configurations();
915*d57664e9SAndroid Build Coastguard Worker out_configuration->set_req_touch_screen(req_touch_screen);
916*d57664e9SAndroid Build Coastguard Worker out_configuration->set_req_keyboard_type(req_keyboard_type);
917*d57664e9SAndroid Build Coastguard Worker out_configuration->set_req_hard_keyboard(req_hard_keyboard);
918*d57664e9SAndroid Build Coastguard Worker out_configuration->set_req_navigation(req_navigation);
919*d57664e9SAndroid Build Coastguard Worker out_configuration->set_req_five_way_nav(req_five_way_nav);
920*d57664e9SAndroid Build Coastguard Worker }
921*d57664e9SAndroid Build Coastguard Worker };
922*d57664e9SAndroid Build Coastguard Worker
923*d57664e9SAndroid Build Coastguard Worker /** Represents <supports-screen> elements. **/
924*d57664e9SAndroid Build Coastguard Worker class SupportsScreen : public ManifestExtractor::Element {
925*d57664e9SAndroid Build Coastguard Worker public:
926*d57664e9SAndroid Build Coastguard Worker SupportsScreen() = default;
927*d57664e9SAndroid Build Coastguard Worker int32_t small_screen = 1;
928*d57664e9SAndroid Build Coastguard Worker int32_t normal_screen = 1;
929*d57664e9SAndroid Build Coastguard Worker int32_t large_screen = 1;
930*d57664e9SAndroid Build Coastguard Worker int32_t xlarge_screen = 1;
931*d57664e9SAndroid Build Coastguard Worker int32_t any_density = 1;
932*d57664e9SAndroid Build Coastguard Worker int32_t requires_smallest_width_dp = 0;
933*d57664e9SAndroid Build Coastguard Worker int32_t compatible_width_limit_dp = 0;
934*d57664e9SAndroid Build Coastguard Worker int32_t largest_width_limit_dp = 0;
935*d57664e9SAndroid Build Coastguard Worker
Extract(xml::Element * element)936*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* element) override {
937*d57664e9SAndroid Build Coastguard Worker small_screen = GetAttributeIntegerDefault(FindAttribute(element, SMALL_SCREEN_ATTR), 1);
938*d57664e9SAndroid Build Coastguard Worker normal_screen = GetAttributeIntegerDefault(FindAttribute(element, NORMAL_SCREEN_ATTR), 1);
939*d57664e9SAndroid Build Coastguard Worker large_screen = GetAttributeIntegerDefault(FindAttribute(element, LARGE_SCREEN_ATTR), 1);
940*d57664e9SAndroid Build Coastguard Worker xlarge_screen = GetAttributeIntegerDefault(FindAttribute(element, XLARGE_SCREEN_ATTR), 1);
941*d57664e9SAndroid Build Coastguard Worker any_density = GetAttributeIntegerDefault(FindAttribute(element, ANY_DENSITY_ATTR), 1);
942*d57664e9SAndroid Build Coastguard Worker
943*d57664e9SAndroid Build Coastguard Worker requires_smallest_width_dp = GetAttributeIntegerDefault(
944*d57664e9SAndroid Build Coastguard Worker FindAttribute(element, REQUIRES_SMALLEST_WIDTH_DP_ATTR), 0);
945*d57664e9SAndroid Build Coastguard Worker compatible_width_limit_dp = GetAttributeIntegerDefault(
946*d57664e9SAndroid Build Coastguard Worker FindAttribute(element, COMPATIBLE_WIDTH_LIMIT_DP_ATTR), 0);
947*d57664e9SAndroid Build Coastguard Worker largest_width_limit_dp = GetAttributeIntegerDefault(
948*d57664e9SAndroid Build Coastguard Worker FindAttribute(element, LARGEST_WIDTH_LIMIT_DP_ATTR), 0);
949*d57664e9SAndroid Build Coastguard Worker
950*d57664e9SAndroid Build Coastguard Worker // For modern apps, if screen size buckets haven't been specified
951*d57664e9SAndroid Build Coastguard Worker // but the new width ranges have, then infer the buckets from them.
952*d57664e9SAndroid Build Coastguard Worker if (small_screen > 0 && normal_screen > 0 && large_screen > 0 && xlarge_screen > 0
953*d57664e9SAndroid Build Coastguard Worker && requires_smallest_width_dp > 0) {
954*d57664e9SAndroid Build Coastguard Worker int32_t compat_width = (compatible_width_limit_dp > 0) ? compatible_width_limit_dp
955*d57664e9SAndroid Build Coastguard Worker : requires_smallest_width_dp;
956*d57664e9SAndroid Build Coastguard Worker small_screen = (requires_smallest_width_dp <= 240 && compat_width >= 240) ? -1 : 0;
957*d57664e9SAndroid Build Coastguard Worker normal_screen = (requires_smallest_width_dp <= 320 && compat_width >= 320) ? -1 : 0;
958*d57664e9SAndroid Build Coastguard Worker large_screen = (requires_smallest_width_dp <= 480 && compat_width >= 480) ? -1 : 0;
959*d57664e9SAndroid Build Coastguard Worker xlarge_screen = (requires_smallest_width_dp <= 720 && compat_width >= 720) ? -1 : 0;
960*d57664e9SAndroid Build Coastguard Worker }
961*d57664e9SAndroid Build Coastguard Worker }
962*d57664e9SAndroid Build Coastguard Worker
PrintScreens(text::Printer * printer,int32_t target_sdk) const963*d57664e9SAndroid Build Coastguard Worker void PrintScreens(text::Printer* printer, int32_t target_sdk) const {
964*d57664e9SAndroid Build Coastguard Worker // Print the formatted screen info
965*d57664e9SAndroid Build Coastguard Worker printer->Print("supports-screens:");
966*d57664e9SAndroid Build Coastguard Worker if (IsSmallScreenSupported(target_sdk)) {
967*d57664e9SAndroid Build Coastguard Worker printer->Print(" 'small'");
968*d57664e9SAndroid Build Coastguard Worker }
969*d57664e9SAndroid Build Coastguard Worker if (normal_screen != 0) {
970*d57664e9SAndroid Build Coastguard Worker printer->Print(" 'normal'");
971*d57664e9SAndroid Build Coastguard Worker }
972*d57664e9SAndroid Build Coastguard Worker if (IsLargeScreenSupported(target_sdk)) {
973*d57664e9SAndroid Build Coastguard Worker printer->Print(" 'large'");
974*d57664e9SAndroid Build Coastguard Worker }
975*d57664e9SAndroid Build Coastguard Worker if (IsXLargeScreenSupported(target_sdk)) {
976*d57664e9SAndroid Build Coastguard Worker printer->Print(" 'xlarge'");
977*d57664e9SAndroid Build Coastguard Worker }
978*d57664e9SAndroid Build Coastguard Worker printer->Print("\n");
979*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("supports-any-density: '%s'\n",
980*d57664e9SAndroid Build Coastguard Worker (IsAnyDensitySupported(target_sdk)) ? "true" : "false"));
981*d57664e9SAndroid Build Coastguard Worker if (requires_smallest_width_dp > 0) {
982*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("requires-smallest-width:'%d'\n", requires_smallest_width_dp));
983*d57664e9SAndroid Build Coastguard Worker }
984*d57664e9SAndroid Build Coastguard Worker if (compatible_width_limit_dp > 0) {
985*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("compatible-width-limit:'%d'\n", compatible_width_limit_dp));
986*d57664e9SAndroid Build Coastguard Worker }
987*d57664e9SAndroid Build Coastguard Worker if (largest_width_limit_dp > 0) {
988*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("largest-width-limit:'%d'\n", largest_width_limit_dp));
989*d57664e9SAndroid Build Coastguard Worker }
990*d57664e9SAndroid Build Coastguard Worker }
991*d57664e9SAndroid Build Coastguard Worker
ToProtoScreens(pb::Badging * out_badging,int32_t target_sdk) const992*d57664e9SAndroid Build Coastguard Worker void ToProtoScreens(pb::Badging* out_badging, int32_t target_sdk) const {
993*d57664e9SAndroid Build Coastguard Worker auto supports_screen = out_badging->mutable_supports_screen();
994*d57664e9SAndroid Build Coastguard Worker if (IsSmallScreenSupported(target_sdk)) {
995*d57664e9SAndroid Build Coastguard Worker supports_screen->add_screens(pb::SupportsScreen_ScreenType_SMALL);
996*d57664e9SAndroid Build Coastguard Worker }
997*d57664e9SAndroid Build Coastguard Worker if (normal_screen != 0) {
998*d57664e9SAndroid Build Coastguard Worker supports_screen->add_screens(pb::SupportsScreen_ScreenType_NORMAL);
999*d57664e9SAndroid Build Coastguard Worker }
1000*d57664e9SAndroid Build Coastguard Worker if (IsLargeScreenSupported(target_sdk)) {
1001*d57664e9SAndroid Build Coastguard Worker supports_screen->add_screens(pb::SupportsScreen_ScreenType_LARGE);
1002*d57664e9SAndroid Build Coastguard Worker }
1003*d57664e9SAndroid Build Coastguard Worker if (IsXLargeScreenSupported(target_sdk)) {
1004*d57664e9SAndroid Build Coastguard Worker supports_screen->add_screens(pb::SupportsScreen_ScreenType_XLARGE);
1005*d57664e9SAndroid Build Coastguard Worker }
1006*d57664e9SAndroid Build Coastguard Worker supports_screen->set_supports_any_densities(IsAnyDensitySupported(target_sdk));
1007*d57664e9SAndroid Build Coastguard Worker supports_screen->set_requires_smallest_width_dp(requires_smallest_width_dp);
1008*d57664e9SAndroid Build Coastguard Worker supports_screen->set_compatible_width_limit_dp(compatible_width_limit_dp);
1009*d57664e9SAndroid Build Coastguard Worker supports_screen->set_largest_width_limit_dp(largest_width_limit_dp);
1010*d57664e9SAndroid Build Coastguard Worker }
1011*d57664e9SAndroid Build Coastguard Worker
1012*d57664e9SAndroid Build Coastguard Worker private:
1013*d57664e9SAndroid Build Coastguard Worker // Determine default values for any unspecified screen sizes,
1014*d57664e9SAndroid Build Coastguard Worker // based on the target SDK of the package. As of 4 (donut)
1015*d57664e9SAndroid Build Coastguard Worker // the screen size support was introduced, so all default to
1016*d57664e9SAndroid Build Coastguard Worker // enabled.
IsSmallScreenSupported(int32_t target_sdk) const1017*d57664e9SAndroid Build Coastguard Worker bool IsSmallScreenSupported(int32_t target_sdk) const {
1018*d57664e9SAndroid Build Coastguard Worker if (small_screen > 0) {
1019*d57664e9SAndroid Build Coastguard Worker return target_sdk >= SDK_DONUT;
1020*d57664e9SAndroid Build Coastguard Worker }
1021*d57664e9SAndroid Build Coastguard Worker return small_screen != 0;
1022*d57664e9SAndroid Build Coastguard Worker }
1023*d57664e9SAndroid Build Coastguard Worker
IsLargeScreenSupported(int32_t target_sdk) const1024*d57664e9SAndroid Build Coastguard Worker bool IsLargeScreenSupported(int32_t target_sdk) const {
1025*d57664e9SAndroid Build Coastguard Worker if (large_screen > 0) {
1026*d57664e9SAndroid Build Coastguard Worker return target_sdk >= SDK_DONUT;
1027*d57664e9SAndroid Build Coastguard Worker }
1028*d57664e9SAndroid Build Coastguard Worker return large_screen != 0;
1029*d57664e9SAndroid Build Coastguard Worker }
1030*d57664e9SAndroid Build Coastguard Worker
IsXLargeScreenSupported(int32_t target_sdk) const1031*d57664e9SAndroid Build Coastguard Worker bool IsXLargeScreenSupported(int32_t target_sdk) const {
1032*d57664e9SAndroid Build Coastguard Worker if (xlarge_screen > 0) {
1033*d57664e9SAndroid Build Coastguard Worker return target_sdk >= SDK_GINGERBREAD;
1034*d57664e9SAndroid Build Coastguard Worker }
1035*d57664e9SAndroid Build Coastguard Worker return xlarge_screen != 0;
1036*d57664e9SAndroid Build Coastguard Worker }
1037*d57664e9SAndroid Build Coastguard Worker
IsAnyDensitySupported(int32_t target_sdk) const1038*d57664e9SAndroid Build Coastguard Worker bool IsAnyDensitySupported(int32_t target_sdk) const {
1039*d57664e9SAndroid Build Coastguard Worker if (any_density > 0) {
1040*d57664e9SAndroid Build Coastguard Worker return target_sdk >= SDK_DONUT || requires_smallest_width_dp > 0 ||
1041*d57664e9SAndroid Build Coastguard Worker compatible_width_limit_dp > 0;
1042*d57664e9SAndroid Build Coastguard Worker }
1043*d57664e9SAndroid Build Coastguard Worker return any_density != 0;
1044*d57664e9SAndroid Build Coastguard Worker }
1045*d57664e9SAndroid Build Coastguard Worker };
1046*d57664e9SAndroid Build Coastguard Worker
1047*d57664e9SAndroid Build Coastguard Worker /** Represents <feature-group> elements. **/
1048*d57664e9SAndroid Build Coastguard Worker class FeatureGroup : public ManifestExtractor::Element {
1049*d57664e9SAndroid Build Coastguard Worker public:
1050*d57664e9SAndroid Build Coastguard Worker FeatureGroup() = default;
1051*d57664e9SAndroid Build Coastguard Worker std::string label;
1052*d57664e9SAndroid Build Coastguard Worker int32_t open_gles_version = 0;
1053*d57664e9SAndroid Build Coastguard Worker
Extract(xml::Element * element)1054*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* element) override {
1055*d57664e9SAndroid Build Coastguard Worker label = GetAttributeStringDefault(FindAttribute(element, LABEL_ATTR), "");
1056*d57664e9SAndroid Build Coastguard Worker }
1057*d57664e9SAndroid Build Coastguard Worker
PrintGroup(text::Printer * printer)1058*d57664e9SAndroid Build Coastguard Worker virtual void PrintGroup(text::Printer* printer) {
1059*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("feature-group: label='%s'\n", label.data()));
1060*d57664e9SAndroid Build Coastguard Worker if (open_gles_version > 0) {
1061*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" uses-gl-es: '0x%x'\n", open_gles_version));
1062*d57664e9SAndroid Build Coastguard Worker }
1063*d57664e9SAndroid Build Coastguard Worker
1064*d57664e9SAndroid Build Coastguard Worker for (auto feature : features_) {
1065*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" uses-feature%s: name='%s'",
1066*d57664e9SAndroid Build Coastguard Worker (feature.second.required ? "" : "-not-required"),
1067*d57664e9SAndroid Build Coastguard Worker feature.first.data()));
1068*d57664e9SAndroid Build Coastguard Worker if (feature.second.version > 0) {
1069*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" version='%d'", feature.second.version));
1070*d57664e9SAndroid Build Coastguard Worker }
1071*d57664e9SAndroid Build Coastguard Worker printer->Print("\n");
1072*d57664e9SAndroid Build Coastguard Worker }
1073*d57664e9SAndroid Build Coastguard Worker }
1074*d57664e9SAndroid Build Coastguard Worker
GroupToProto(pb::Badging * out_badging)1075*d57664e9SAndroid Build Coastguard Worker virtual void GroupToProto(pb::Badging* out_badging) {
1076*d57664e9SAndroid Build Coastguard Worker auto feature_group = out_badging->add_feature_groups();
1077*d57664e9SAndroid Build Coastguard Worker feature_group->set_label(label);
1078*d57664e9SAndroid Build Coastguard Worker feature_group->set_open_gles_version(open_gles_version);
1079*d57664e9SAndroid Build Coastguard Worker for (auto& feature : features_) {
1080*d57664e9SAndroid Build Coastguard Worker auto out_feature = feature_group->add_features();
1081*d57664e9SAndroid Build Coastguard Worker out_feature->set_name(feature.first);
1082*d57664e9SAndroid Build Coastguard Worker out_feature->set_required(feature.second.required);
1083*d57664e9SAndroid Build Coastguard Worker out_feature->set_version(feature.second.version);
1084*d57664e9SAndroid Build Coastguard Worker }
1085*d57664e9SAndroid Build Coastguard Worker }
1086*d57664e9SAndroid Build Coastguard Worker
1087*d57664e9SAndroid Build Coastguard Worker /** Adds a feature to the feature group. */
AddFeature(const std::string & name,bool required=true,int32_t version=-1)1088*d57664e9SAndroid Build Coastguard Worker void AddFeature(const std::string& name, bool required = true, int32_t version = -1) {
1089*d57664e9SAndroid Build Coastguard Worker features_.insert_or_assign(name, Feature{required, version});
1090*d57664e9SAndroid Build Coastguard Worker if (required) {
1091*d57664e9SAndroid Build Coastguard Worker if (name == "android.hardware.camera.autofocus" ||
1092*d57664e9SAndroid Build Coastguard Worker name == "android.hardware.camera.flash") {
1093*d57664e9SAndroid Build Coastguard Worker AddFeature("android.hardware.camera", true);
1094*d57664e9SAndroid Build Coastguard Worker } else if (name == "android.hardware.location.gps" ||
1095*d57664e9SAndroid Build Coastguard Worker name == "android.hardware.location.network") {
1096*d57664e9SAndroid Build Coastguard Worker AddFeature("android.hardware.location", true);
1097*d57664e9SAndroid Build Coastguard Worker } else if (name == "android.hardware.faketouch.multitouch") {
1098*d57664e9SAndroid Build Coastguard Worker AddFeature("android.hardware.faketouch", true);
1099*d57664e9SAndroid Build Coastguard Worker } else if (name == "android.hardware.faketouch.multitouch.distinct" ||
1100*d57664e9SAndroid Build Coastguard Worker name == "android.hardware.faketouch.multitouch.jazzhands") {
1101*d57664e9SAndroid Build Coastguard Worker AddFeature("android.hardware.faketouch.multitouch", true);
1102*d57664e9SAndroid Build Coastguard Worker AddFeature("android.hardware.faketouch", true);
1103*d57664e9SAndroid Build Coastguard Worker } else if (name == "android.hardware.touchscreen.multitouch") {
1104*d57664e9SAndroid Build Coastguard Worker AddFeature("android.hardware.touchscreen", true);
1105*d57664e9SAndroid Build Coastguard Worker } else if (name == "android.hardware.touchscreen.multitouch.distinct" ||
1106*d57664e9SAndroid Build Coastguard Worker name == "android.hardware.touchscreen.multitouch.jazzhands") {
1107*d57664e9SAndroid Build Coastguard Worker AddFeature("android.hardware.touchscreen.multitouch", true);
1108*d57664e9SAndroid Build Coastguard Worker AddFeature("android.hardware.touchscreen", true);
1109*d57664e9SAndroid Build Coastguard Worker } else if (name == "android.hardware.opengles.aep") {
1110*d57664e9SAndroid Build Coastguard Worker const int kOpenGLESVersion31 = 0x00030001;
1111*d57664e9SAndroid Build Coastguard Worker if (kOpenGLESVersion31 > open_gles_version) {
1112*d57664e9SAndroid Build Coastguard Worker open_gles_version = kOpenGLESVersion31;
1113*d57664e9SAndroid Build Coastguard Worker }
1114*d57664e9SAndroid Build Coastguard Worker }
1115*d57664e9SAndroid Build Coastguard Worker }
1116*d57664e9SAndroid Build Coastguard Worker }
1117*d57664e9SAndroid Build Coastguard Worker
1118*d57664e9SAndroid Build Coastguard Worker /** Returns true if the feature group has the given feature. */
HasFeature(const std::string & name)1119*d57664e9SAndroid Build Coastguard Worker virtual bool HasFeature(const std::string& name) {
1120*d57664e9SAndroid Build Coastguard Worker return features_.find(name) != features_.end();
1121*d57664e9SAndroid Build Coastguard Worker }
1122*d57664e9SAndroid Build Coastguard Worker
1123*d57664e9SAndroid Build Coastguard Worker /** Merges the features of another feature group into this group. */
Merge(FeatureGroup * group)1124*d57664e9SAndroid Build Coastguard Worker void Merge(FeatureGroup* group) {
1125*d57664e9SAndroid Build Coastguard Worker open_gles_version = std::max(open_gles_version, group->open_gles_version);
1126*d57664e9SAndroid Build Coastguard Worker for (auto& feature : group->features_) {
1127*d57664e9SAndroid Build Coastguard Worker features_.insert(feature);
1128*d57664e9SAndroid Build Coastguard Worker }
1129*d57664e9SAndroid Build Coastguard Worker }
1130*d57664e9SAndroid Build Coastguard Worker
1131*d57664e9SAndroid Build Coastguard Worker protected:
1132*d57664e9SAndroid Build Coastguard Worker struct Feature {
1133*d57664e9SAndroid Build Coastguard Worker public:
1134*d57664e9SAndroid Build Coastguard Worker bool required = false;
1135*d57664e9SAndroid Build Coastguard Worker int32_t version = -1;
1136*d57664e9SAndroid Build Coastguard Worker };
1137*d57664e9SAndroid Build Coastguard Worker
1138*d57664e9SAndroid Build Coastguard Worker /* Mapping of feature names to their properties. */
1139*d57664e9SAndroid Build Coastguard Worker std::map<std::string, Feature> features_;
1140*d57664e9SAndroid Build Coastguard Worker };
1141*d57664e9SAndroid Build Coastguard Worker
1142*d57664e9SAndroid Build Coastguard Worker /**
1143*d57664e9SAndroid Build Coastguard Worker * Represents the default feature group for the application if no <feature-group> elements are
1144*d57664e9SAndroid Build Coastguard Worker * present in the manifest.
1145*d57664e9SAndroid Build Coastguard Worker **/
1146*d57664e9SAndroid Build Coastguard Worker class CommonFeatureGroup : public FeatureGroup {
1147*d57664e9SAndroid Build Coastguard Worker public:
1148*d57664e9SAndroid Build Coastguard Worker CommonFeatureGroup() = default;
PrintGroup(text::Printer * printer)1149*d57664e9SAndroid Build Coastguard Worker void PrintGroup(text::Printer* printer) override {
1150*d57664e9SAndroid Build Coastguard Worker FeatureGroup::PrintGroup(printer);
1151*d57664e9SAndroid Build Coastguard Worker
1152*d57664e9SAndroid Build Coastguard Worker // Also print the implied features
1153*d57664e9SAndroid Build Coastguard Worker for (auto feature : implied_features_) {
1154*d57664e9SAndroid Build Coastguard Worker if (features_.find(feature.first) == features_.end()) {
1155*d57664e9SAndroid Build Coastguard Worker const char* sdk23 = feature.second.implied_from_sdk_k23 ? "-sdk-23" : "";
1156*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" uses-feature%s: name='%s'\n", sdk23, feature.first.data()));
1157*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" uses-implied-feature%s: name='%s' reason='", sdk23,
1158*d57664e9SAndroid Build Coastguard Worker feature.first.data()));
1159*d57664e9SAndroid Build Coastguard Worker
1160*d57664e9SAndroid Build Coastguard Worker // Print the reasons as a sentence
1161*d57664e9SAndroid Build Coastguard Worker size_t count = 0;
1162*d57664e9SAndroid Build Coastguard Worker for (auto reason : feature.second.reasons) {
1163*d57664e9SAndroid Build Coastguard Worker printer->Print(reason);
1164*d57664e9SAndroid Build Coastguard Worker if (count + 2 < feature.second.reasons.size()) {
1165*d57664e9SAndroid Build Coastguard Worker printer->Print(", ");
1166*d57664e9SAndroid Build Coastguard Worker } else if (count + 1 < feature.second.reasons.size()) {
1167*d57664e9SAndroid Build Coastguard Worker printer->Print(", and ");
1168*d57664e9SAndroid Build Coastguard Worker }
1169*d57664e9SAndroid Build Coastguard Worker count++;
1170*d57664e9SAndroid Build Coastguard Worker }
1171*d57664e9SAndroid Build Coastguard Worker printer->Print("'\n");
1172*d57664e9SAndroid Build Coastguard Worker }
1173*d57664e9SAndroid Build Coastguard Worker }
1174*d57664e9SAndroid Build Coastguard Worker }
1175*d57664e9SAndroid Build Coastguard Worker
GroupToProto(pb::Badging * out_badging)1176*d57664e9SAndroid Build Coastguard Worker virtual void GroupToProto(pb::Badging* out_badging) override {
1177*d57664e9SAndroid Build Coastguard Worker FeatureGroup::GroupToProto(out_badging);
1178*d57664e9SAndroid Build Coastguard Worker auto feature_group =
1179*d57664e9SAndroid Build Coastguard Worker out_badging->mutable_feature_groups(out_badging->feature_groups_size() - 1);
1180*d57664e9SAndroid Build Coastguard Worker for (auto& feature : implied_features_) {
1181*d57664e9SAndroid Build Coastguard Worker if (features_.find(feature.first) == features_.end()) {
1182*d57664e9SAndroid Build Coastguard Worker auto out_feature = feature_group->add_features();
1183*d57664e9SAndroid Build Coastguard Worker out_feature->set_name(feature.first);
1184*d57664e9SAndroid Build Coastguard Worker auto implied_data = out_feature->mutable_implied_data();
1185*d57664e9SAndroid Build Coastguard Worker implied_data->set_from_sdk_23_permission(feature.second.implied_from_sdk_k23);
1186*d57664e9SAndroid Build Coastguard Worker for (auto& reason : feature.second.reasons) {
1187*d57664e9SAndroid Build Coastguard Worker implied_data->add_reasons(reason);
1188*d57664e9SAndroid Build Coastguard Worker }
1189*d57664e9SAndroid Build Coastguard Worker }
1190*d57664e9SAndroid Build Coastguard Worker }
1191*d57664e9SAndroid Build Coastguard Worker }
1192*d57664e9SAndroid Build Coastguard Worker
1193*d57664e9SAndroid Build Coastguard Worker /** Returns true if the feature group has the given feature. */
HasFeature(const std::string & name)1194*d57664e9SAndroid Build Coastguard Worker bool HasFeature(const std::string& name) override {
1195*d57664e9SAndroid Build Coastguard Worker return FeatureGroup::HasFeature(name)
1196*d57664e9SAndroid Build Coastguard Worker || implied_features_.find(name) != implied_features_.end();
1197*d57664e9SAndroid Build Coastguard Worker }
1198*d57664e9SAndroid Build Coastguard Worker
1199*d57664e9SAndroid Build Coastguard Worker /** Adds a feature to a set of implied features not explicitly requested in the manifest. */
addImpliedFeature(const std::string & name,const std::string & reason,bool sdk23=false)1200*d57664e9SAndroid Build Coastguard Worker void addImpliedFeature(const std::string& name, const std::string& reason, bool sdk23 = false) {
1201*d57664e9SAndroid Build Coastguard Worker auto entry = implied_features_.find(name);
1202*d57664e9SAndroid Build Coastguard Worker if (entry == implied_features_.end()) {
1203*d57664e9SAndroid Build Coastguard Worker implied_features_.insert(std::make_pair(name, ImpliedFeature(sdk23)));
1204*d57664e9SAndroid Build Coastguard Worker entry = implied_features_.find(name);
1205*d57664e9SAndroid Build Coastguard Worker }
1206*d57664e9SAndroid Build Coastguard Worker
1207*d57664e9SAndroid Build Coastguard Worker // A non-sdk 23 implied feature takes precedence.
1208*d57664e9SAndroid Build Coastguard Worker if (entry->second.implied_from_sdk_k23 && !sdk23) {
1209*d57664e9SAndroid Build Coastguard Worker entry->second.implied_from_sdk_k23 = false;
1210*d57664e9SAndroid Build Coastguard Worker }
1211*d57664e9SAndroid Build Coastguard Worker
1212*d57664e9SAndroid Build Coastguard Worker entry->second.reasons.insert(reason);
1213*d57664e9SAndroid Build Coastguard Worker }
1214*d57664e9SAndroid Build Coastguard Worker
1215*d57664e9SAndroid Build Coastguard Worker /**
1216*d57664e9SAndroid Build Coastguard Worker * Adds a feature to a set of implied features for all features that are implied by the presence
1217*d57664e9SAndroid Build Coastguard Worker * of the permission.
1218*d57664e9SAndroid Build Coastguard Worker **/
addImpliedFeaturesForPermission(int32_t targetSdk,const std::string & name,bool sdk23)1219*d57664e9SAndroid Build Coastguard Worker void addImpliedFeaturesForPermission(int32_t targetSdk, const std::string& name, bool sdk23) {
1220*d57664e9SAndroid Build Coastguard Worker if (name == "android.permission.CAMERA") {
1221*d57664e9SAndroid Build Coastguard Worker addImpliedFeature("android.hardware.camera",
1222*d57664e9SAndroid Build Coastguard Worker StringPrintf("requested %s permission", name.data()),
1223*d57664e9SAndroid Build Coastguard Worker sdk23);
1224*d57664e9SAndroid Build Coastguard Worker
1225*d57664e9SAndroid Build Coastguard Worker } else if (name == "android.permission.ACCESS_FINE_LOCATION") {
1226*d57664e9SAndroid Build Coastguard Worker if (targetSdk < SDK_LOLLIPOP) {
1227*d57664e9SAndroid Build Coastguard Worker addImpliedFeature("android.hardware.location.gps",
1228*d57664e9SAndroid Build Coastguard Worker StringPrintf("requested %s permission", name.data()),
1229*d57664e9SAndroid Build Coastguard Worker sdk23);
1230*d57664e9SAndroid Build Coastguard Worker addImpliedFeature("android.hardware.location.gps",
1231*d57664e9SAndroid Build Coastguard Worker StringPrintf("targetSdkVersion < %d", SDK_LOLLIPOP),
1232*d57664e9SAndroid Build Coastguard Worker sdk23);
1233*d57664e9SAndroid Build Coastguard Worker }
1234*d57664e9SAndroid Build Coastguard Worker addImpliedFeature("android.hardware.location",
1235*d57664e9SAndroid Build Coastguard Worker StringPrintf("requested %s permission", name.data()),
1236*d57664e9SAndroid Build Coastguard Worker sdk23);
1237*d57664e9SAndroid Build Coastguard Worker
1238*d57664e9SAndroid Build Coastguard Worker } else if (name == "android.permission.ACCESS_COARSE_LOCATION") {
1239*d57664e9SAndroid Build Coastguard Worker if (targetSdk < SDK_LOLLIPOP) {
1240*d57664e9SAndroid Build Coastguard Worker addImpliedFeature("android.hardware.location.network",
1241*d57664e9SAndroid Build Coastguard Worker StringPrintf("requested %s permission", name.data()),
1242*d57664e9SAndroid Build Coastguard Worker sdk23);
1243*d57664e9SAndroid Build Coastguard Worker addImpliedFeature("android.hardware.location.network",
1244*d57664e9SAndroid Build Coastguard Worker StringPrintf("targetSdkVersion < %d", SDK_LOLLIPOP),
1245*d57664e9SAndroid Build Coastguard Worker sdk23);
1246*d57664e9SAndroid Build Coastguard Worker }
1247*d57664e9SAndroid Build Coastguard Worker addImpliedFeature("android.hardware.location",
1248*d57664e9SAndroid Build Coastguard Worker StringPrintf("requested %s permission", name.data()),
1249*d57664e9SAndroid Build Coastguard Worker sdk23);
1250*d57664e9SAndroid Build Coastguard Worker
1251*d57664e9SAndroid Build Coastguard Worker } else if (name == "android.permission.ACCESS_MOCK_LOCATION" ||
1252*d57664e9SAndroid Build Coastguard Worker name == "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" ||
1253*d57664e9SAndroid Build Coastguard Worker name == "android.permission.INSTALL_LOCATION_PROVIDER") {
1254*d57664e9SAndroid Build Coastguard Worker addImpliedFeature("android.hardware.location",
1255*d57664e9SAndroid Build Coastguard Worker StringPrintf("requested %s permission", name.data()),
1256*d57664e9SAndroid Build Coastguard Worker sdk23);
1257*d57664e9SAndroid Build Coastguard Worker
1258*d57664e9SAndroid Build Coastguard Worker } else if (name == "android.permission.BLUETOOTH" ||
1259*d57664e9SAndroid Build Coastguard Worker name == "android.permission.BLUETOOTH_ADMIN") {
1260*d57664e9SAndroid Build Coastguard Worker if (targetSdk > SDK_DONUT) {
1261*d57664e9SAndroid Build Coastguard Worker addImpliedFeature("android.hardware.bluetooth",
1262*d57664e9SAndroid Build Coastguard Worker StringPrintf("requested %s permission", name.data()),
1263*d57664e9SAndroid Build Coastguard Worker sdk23);
1264*d57664e9SAndroid Build Coastguard Worker addImpliedFeature("android.hardware.bluetooth",
1265*d57664e9SAndroid Build Coastguard Worker StringPrintf("targetSdkVersion > %d", SDK_DONUT),
1266*d57664e9SAndroid Build Coastguard Worker sdk23);
1267*d57664e9SAndroid Build Coastguard Worker }
1268*d57664e9SAndroid Build Coastguard Worker
1269*d57664e9SAndroid Build Coastguard Worker } else if (name == "android.permission.RECORD_AUDIO") {
1270*d57664e9SAndroid Build Coastguard Worker addImpliedFeature("android.hardware.microphone",
1271*d57664e9SAndroid Build Coastguard Worker StringPrintf("requested %s permission", name.data()),
1272*d57664e9SAndroid Build Coastguard Worker sdk23);
1273*d57664e9SAndroid Build Coastguard Worker
1274*d57664e9SAndroid Build Coastguard Worker } else if (name == "android.permission.ACCESS_WIFI_STATE" ||
1275*d57664e9SAndroid Build Coastguard Worker name == "android.permission.CHANGE_WIFI_STATE" ||
1276*d57664e9SAndroid Build Coastguard Worker name == "android.permission.CHANGE_WIFI_MULTICAST_STATE") {
1277*d57664e9SAndroid Build Coastguard Worker addImpliedFeature("android.hardware.wifi",
1278*d57664e9SAndroid Build Coastguard Worker StringPrintf("requested %s permission", name.data()),
1279*d57664e9SAndroid Build Coastguard Worker sdk23);
1280*d57664e9SAndroid Build Coastguard Worker
1281*d57664e9SAndroid Build Coastguard Worker } else if (name == "android.permission.CALL_PHONE" ||
1282*d57664e9SAndroid Build Coastguard Worker name == "android.permission.CALL_PRIVILEGED" ||
1283*d57664e9SAndroid Build Coastguard Worker name == "android.permission.MODIFY_PHONE_STATE" ||
1284*d57664e9SAndroid Build Coastguard Worker name == "android.permission.PROCESS_OUTGOING_CALLS" ||
1285*d57664e9SAndroid Build Coastguard Worker name == "android.permission.READ_SMS" ||
1286*d57664e9SAndroid Build Coastguard Worker name == "android.permission.RECEIVE_SMS" ||
1287*d57664e9SAndroid Build Coastguard Worker name == "android.permission.RECEIVE_MMS" ||
1288*d57664e9SAndroid Build Coastguard Worker name == "android.permission.RECEIVE_WAP_PUSH" ||
1289*d57664e9SAndroid Build Coastguard Worker name == "android.permission.SEND_SMS" ||
1290*d57664e9SAndroid Build Coastguard Worker name == "android.permission.WRITE_APN_SETTINGS" ||
1291*d57664e9SAndroid Build Coastguard Worker name == "android.permission.WRITE_SMS") {
1292*d57664e9SAndroid Build Coastguard Worker addImpliedFeature("android.hardware.telephony",
1293*d57664e9SAndroid Build Coastguard Worker "requested a telephony permission",
1294*d57664e9SAndroid Build Coastguard Worker sdk23);
1295*d57664e9SAndroid Build Coastguard Worker }
1296*d57664e9SAndroid Build Coastguard Worker }
1297*d57664e9SAndroid Build Coastguard Worker
1298*d57664e9SAndroid Build Coastguard Worker private:
1299*d57664e9SAndroid Build Coastguard Worker /**
1300*d57664e9SAndroid Build Coastguard Worker * Represents a feature that has been automatically added due to a pre-requisite or for some
1301*d57664e9SAndroid Build Coastguard Worker * other reason.
1302*d57664e9SAndroid Build Coastguard Worker */
1303*d57664e9SAndroid Build Coastguard Worker struct ImpliedFeature {
ImpliedFeatureaapt::CommonFeatureGroup::ImpliedFeature1304*d57664e9SAndroid Build Coastguard Worker explicit ImpliedFeature(bool sdk23 = false) : implied_from_sdk_k23(sdk23) {}
1305*d57664e9SAndroid Build Coastguard Worker
1306*d57664e9SAndroid Build Coastguard Worker /** List of human-readable reasons for why this feature was implied. */
1307*d57664e9SAndroid Build Coastguard Worker std::set<std::string> reasons;
1308*d57664e9SAndroid Build Coastguard Worker
1309*d57664e9SAndroid Build Coastguard Worker // Was this implied by a permission from SDK 23 (<uses-permission-sdk-23 />)
1310*d57664e9SAndroid Build Coastguard Worker bool implied_from_sdk_k23;
1311*d57664e9SAndroid Build Coastguard Worker };
1312*d57664e9SAndroid Build Coastguard Worker
1313*d57664e9SAndroid Build Coastguard Worker /* Mapping of implied feature names to their properties. */
1314*d57664e9SAndroid Build Coastguard Worker std::map<std::string, ImpliedFeature> implied_features_;
1315*d57664e9SAndroid Build Coastguard Worker };
1316*d57664e9SAndroid Build Coastguard Worker
1317*d57664e9SAndroid Build Coastguard Worker /** Represents <uses-feature> elements. **/
1318*d57664e9SAndroid Build Coastguard Worker class UsesFeature : public ManifestExtractor::Element {
1319*d57664e9SAndroid Build Coastguard Worker public:
1320*d57664e9SAndroid Build Coastguard Worker UsesFeature() = default;
Extract(xml::Element * element)1321*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* element) override {
1322*d57664e9SAndroid Build Coastguard Worker const std::string* name = GetAttributeString(FindAttribute(element, NAME_ATTR));
1323*d57664e9SAndroid Build Coastguard Worker int32_t* gl = GetAttributeInteger(FindAttribute(element, GL_ES_VERSION_ATTR));
1324*d57664e9SAndroid Build Coastguard Worker bool required = GetAttributeIntegerDefault(
1325*d57664e9SAndroid Build Coastguard Worker FindAttribute(element, REQUIRED_ATTR), true) != 0;
1326*d57664e9SAndroid Build Coastguard Worker int32_t version = GetAttributeIntegerDefault(
1327*d57664e9SAndroid Build Coastguard Worker FindAttribute(element, kAndroidNamespace, "version"), 0);
1328*d57664e9SAndroid Build Coastguard Worker
1329*d57664e9SAndroid Build Coastguard Worker // Add the feature to the parent feature group element if one exists; otherwise, add it to the
1330*d57664e9SAndroid Build Coastguard Worker // common feature group
1331*d57664e9SAndroid Build Coastguard Worker FeatureGroup* feature_group = ElementCast<FeatureGroup>(extractor()->parent_stack()[0]);
1332*d57664e9SAndroid Build Coastguard Worker if (!feature_group) {
1333*d57664e9SAndroid Build Coastguard Worker feature_group = extractor()->common_feature_group();
1334*d57664e9SAndroid Build Coastguard Worker } else {
1335*d57664e9SAndroid Build Coastguard Worker // All features in side of <feature-group> elements are required.
1336*d57664e9SAndroid Build Coastguard Worker required = true;
1337*d57664e9SAndroid Build Coastguard Worker }
1338*d57664e9SAndroid Build Coastguard Worker
1339*d57664e9SAndroid Build Coastguard Worker if (name) {
1340*d57664e9SAndroid Build Coastguard Worker feature_group->AddFeature(*name, required, version);
1341*d57664e9SAndroid Build Coastguard Worker } else if (gl) {
1342*d57664e9SAndroid Build Coastguard Worker feature_group->open_gles_version = std::max(feature_group->open_gles_version, *gl);
1343*d57664e9SAndroid Build Coastguard Worker }
1344*d57664e9SAndroid Build Coastguard Worker }
1345*d57664e9SAndroid Build Coastguard Worker };
1346*d57664e9SAndroid Build Coastguard Worker
1347*d57664e9SAndroid Build Coastguard Worker /** Represents <uses-permission> elements. **/
1348*d57664e9SAndroid Build Coastguard Worker class UsesPermission : public ManifestExtractor::Element {
1349*d57664e9SAndroid Build Coastguard Worker public:
1350*d57664e9SAndroid Build Coastguard Worker UsesPermission() = default;
1351*d57664e9SAndroid Build Coastguard Worker bool implied;
1352*d57664e9SAndroid Build Coastguard Worker std::string name;
1353*d57664e9SAndroid Build Coastguard Worker std::vector<std::string> requiredFeatures;
1354*d57664e9SAndroid Build Coastguard Worker std::vector<std::string> requiredNotFeatures;
1355*d57664e9SAndroid Build Coastguard Worker int32_t required = true;
1356*d57664e9SAndroid Build Coastguard Worker int32_t maxSdkVersion = -1;
1357*d57664e9SAndroid Build Coastguard Worker int32_t usesPermissionFlags = 0;
1358*d57664e9SAndroid Build Coastguard Worker std::string impliedReason;
1359*d57664e9SAndroid Build Coastguard Worker
Extract(xml::Element * element)1360*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* element) override {
1361*d57664e9SAndroid Build Coastguard Worker name = GetAttributeStringDefault(FindAttribute(element, NAME_ATTR), "");
1362*d57664e9SAndroid Build Coastguard Worker std::string feature =
1363*d57664e9SAndroid Build Coastguard Worker GetAttributeStringDefault(FindAttribute(element, REQUIRED_FEATURE_ATTR), "");
1364*d57664e9SAndroid Build Coastguard Worker if (!feature.empty()) {
1365*d57664e9SAndroid Build Coastguard Worker requiredFeatures.push_back(feature);
1366*d57664e9SAndroid Build Coastguard Worker }
1367*d57664e9SAndroid Build Coastguard Worker feature = GetAttributeStringDefault(FindAttribute(element, REQUIRED_NOT_FEATURE_ATTR), "");
1368*d57664e9SAndroid Build Coastguard Worker if (!feature.empty()) {
1369*d57664e9SAndroid Build Coastguard Worker requiredNotFeatures.push_back(feature);
1370*d57664e9SAndroid Build Coastguard Worker }
1371*d57664e9SAndroid Build Coastguard Worker
1372*d57664e9SAndroid Build Coastguard Worker required = GetAttributeIntegerDefault(FindAttribute(element, REQUIRED_ATTR), 1);
1373*d57664e9SAndroid Build Coastguard Worker maxSdkVersion = GetAttributeIntegerDefault(
1374*d57664e9SAndroid Build Coastguard Worker FindAttribute(element, MAX_SDK_VERSION_ATTR), -1);
1375*d57664e9SAndroid Build Coastguard Worker usesPermissionFlags = GetAttributeIntegerDefault(
1376*d57664e9SAndroid Build Coastguard Worker FindAttribute(element, USES_PERMISSION_FLAGS_ATTR), 0);
1377*d57664e9SAndroid Build Coastguard Worker
1378*d57664e9SAndroid Build Coastguard Worker if (!name.empty()) {
1379*d57664e9SAndroid Build Coastguard Worker CommonFeatureGroup* common = extractor()->common_feature_group();
1380*d57664e9SAndroid Build Coastguard Worker common->addImpliedFeaturesForPermission(extractor()->target_sdk(), name, false);
1381*d57664e9SAndroid Build Coastguard Worker }
1382*d57664e9SAndroid Build Coastguard Worker }
1383*d57664e9SAndroid Build Coastguard Worker
Print(text::Printer * printer)1384*d57664e9SAndroid Build Coastguard Worker void Print(text::Printer* printer) override {
1385*d57664e9SAndroid Build Coastguard Worker if (!name.empty()) {
1386*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("uses-permission: name='%s'", name.data()));
1387*d57664e9SAndroid Build Coastguard Worker if (maxSdkVersion >= 0) {
1388*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" maxSdkVersion='%d'", maxSdkVersion));
1389*d57664e9SAndroid Build Coastguard Worker }
1390*d57664e9SAndroid Build Coastguard Worker if ((usesPermissionFlags & kNeverForLocation) != 0) {
1391*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" usesPermissionFlags='neverForLocation'"));
1392*d57664e9SAndroid Build Coastguard Worker }
1393*d57664e9SAndroid Build Coastguard Worker printer->Print("\n");
1394*d57664e9SAndroid Build Coastguard Worker for (const std::string& requiredFeature : requiredFeatures) {
1395*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" required-feature='%s'\n", requiredFeature.data()));
1396*d57664e9SAndroid Build Coastguard Worker }
1397*d57664e9SAndroid Build Coastguard Worker for (const std::string& requiredNotFeature : requiredNotFeatures) {
1398*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" required-not-feature='%s'\n", requiredNotFeature.data()));
1399*d57664e9SAndroid Build Coastguard Worker }
1400*d57664e9SAndroid Build Coastguard Worker if (required == 0) {
1401*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("optional-permission: name='%s'", name.data()));
1402*d57664e9SAndroid Build Coastguard Worker if (maxSdkVersion >= 0) {
1403*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" maxSdkVersion='%d'", maxSdkVersion));
1404*d57664e9SAndroid Build Coastguard Worker }
1405*d57664e9SAndroid Build Coastguard Worker if ((usesPermissionFlags & kNeverForLocation) != 0) {
1406*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" usesPermissionFlags='neverForLocation'"));
1407*d57664e9SAndroid Build Coastguard Worker }
1408*d57664e9SAndroid Build Coastguard Worker printer->Print("\n");
1409*d57664e9SAndroid Build Coastguard Worker }
1410*d57664e9SAndroid Build Coastguard Worker }
1411*d57664e9SAndroid Build Coastguard Worker if (implied) {
1412*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("uses-implied-permission: name='%s'", name.data()));
1413*d57664e9SAndroid Build Coastguard Worker if (maxSdkVersion >= 0) {
1414*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" maxSdkVersion='%d'", maxSdkVersion));
1415*d57664e9SAndroid Build Coastguard Worker }
1416*d57664e9SAndroid Build Coastguard Worker if ((usesPermissionFlags & kNeverForLocation) != 0) {
1417*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" usesPermissionFlags='neverForLocation'"));
1418*d57664e9SAndroid Build Coastguard Worker }
1419*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" reason='%s'\n", impliedReason.data()));
1420*d57664e9SAndroid Build Coastguard Worker }
1421*d57664e9SAndroid Build Coastguard Worker }
1422*d57664e9SAndroid Build Coastguard Worker
ToProto(pb::Badging * out_badging)1423*d57664e9SAndroid Build Coastguard Worker void ToProto(pb::Badging* out_badging) override {
1424*d57664e9SAndroid Build Coastguard Worker if (!name.empty()) {
1425*d57664e9SAndroid Build Coastguard Worker auto permission = out_badging->add_uses_permissions();
1426*d57664e9SAndroid Build Coastguard Worker permission->set_name(name);
1427*d57664e9SAndroid Build Coastguard Worker if (maxSdkVersion > 0) {
1428*d57664e9SAndroid Build Coastguard Worker permission->set_max_sdk_version(maxSdkVersion);
1429*d57664e9SAndroid Build Coastguard Worker }
1430*d57664e9SAndroid Build Coastguard Worker if ((usesPermissionFlags & kNeverForLocation) != 0) {
1431*d57664e9SAndroid Build Coastguard Worker permission->mutable_permission_flags()->set_never_for_location(true);
1432*d57664e9SAndroid Build Coastguard Worker }
1433*d57664e9SAndroid Build Coastguard Worker for (auto& requiredFeature : requiredFeatures) {
1434*d57664e9SAndroid Build Coastguard Worker permission->add_required_features(requiredFeature);
1435*d57664e9SAndroid Build Coastguard Worker }
1436*d57664e9SAndroid Build Coastguard Worker for (auto& requiredNotFeature : requiredNotFeatures) {
1437*d57664e9SAndroid Build Coastguard Worker permission->add_required_not_features(requiredNotFeature);
1438*d57664e9SAndroid Build Coastguard Worker }
1439*d57664e9SAndroid Build Coastguard Worker permission->set_required(required != 0);
1440*d57664e9SAndroid Build Coastguard Worker permission->set_implied(implied);
1441*d57664e9SAndroid Build Coastguard Worker }
1442*d57664e9SAndroid Build Coastguard Worker }
1443*d57664e9SAndroid Build Coastguard Worker };
1444*d57664e9SAndroid Build Coastguard Worker
1445*d57664e9SAndroid Build Coastguard Worker /** Represents <required-feature> elements. **/
1446*d57664e9SAndroid Build Coastguard Worker class RequiredFeature : public ManifestExtractor::Element {
1447*d57664e9SAndroid Build Coastguard Worker public:
1448*d57664e9SAndroid Build Coastguard Worker RequiredFeature() = default;
1449*d57664e9SAndroid Build Coastguard Worker std::string name;
1450*d57664e9SAndroid Build Coastguard Worker
Extract(xml::Element * element)1451*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* element) override {
1452*d57664e9SAndroid Build Coastguard Worker name = GetAttributeStringDefault(FindAttribute(element, NAME_ATTR), "");
1453*d57664e9SAndroid Build Coastguard Worker auto parent_stack = extractor()->parent_stack();
1454*d57664e9SAndroid Build Coastguard Worker if (!name.empty() && ElementCast<UsesPermission>(parent_stack[0])) {
1455*d57664e9SAndroid Build Coastguard Worker UsesPermission* uses_permission = ElementCast<UsesPermission>(parent_stack[0]);
1456*d57664e9SAndroid Build Coastguard Worker uses_permission->requiredFeatures.push_back(name);
1457*d57664e9SAndroid Build Coastguard Worker }
1458*d57664e9SAndroid Build Coastguard Worker }
1459*d57664e9SAndroid Build Coastguard Worker };
1460*d57664e9SAndroid Build Coastguard Worker
1461*d57664e9SAndroid Build Coastguard Worker /** Represents <required-not-feature> elements. **/
1462*d57664e9SAndroid Build Coastguard Worker class RequiredNotFeature : public ManifestExtractor::Element {
1463*d57664e9SAndroid Build Coastguard Worker public:
1464*d57664e9SAndroid Build Coastguard Worker RequiredNotFeature() = default;
1465*d57664e9SAndroid Build Coastguard Worker std::string name;
1466*d57664e9SAndroid Build Coastguard Worker
Extract(xml::Element * element)1467*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* element) override {
1468*d57664e9SAndroid Build Coastguard Worker name = GetAttributeStringDefault(FindAttribute(element, NAME_ATTR), "");
1469*d57664e9SAndroid Build Coastguard Worker auto parent_stack = extractor()->parent_stack();
1470*d57664e9SAndroid Build Coastguard Worker if (!name.empty() && ElementCast<UsesPermission>(parent_stack[0])) {
1471*d57664e9SAndroid Build Coastguard Worker UsesPermission* uses_permission = ElementCast<UsesPermission>(parent_stack[0]);
1472*d57664e9SAndroid Build Coastguard Worker uses_permission->requiredNotFeatures.push_back(name);
1473*d57664e9SAndroid Build Coastguard Worker }
1474*d57664e9SAndroid Build Coastguard Worker }
1475*d57664e9SAndroid Build Coastguard Worker };
1476*d57664e9SAndroid Build Coastguard Worker
1477*d57664e9SAndroid Build Coastguard Worker /** Represents <uses-permission-sdk-23> elements. **/
1478*d57664e9SAndroid Build Coastguard Worker class UsesPermissionSdk23 : public ManifestExtractor::Element {
1479*d57664e9SAndroid Build Coastguard Worker public:
1480*d57664e9SAndroid Build Coastguard Worker UsesPermissionSdk23() = default;
1481*d57664e9SAndroid Build Coastguard Worker const std::string* name = nullptr;
1482*d57664e9SAndroid Build Coastguard Worker const int32_t* maxSdkVersion = nullptr;
1483*d57664e9SAndroid Build Coastguard Worker
Extract(xml::Element * element)1484*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* element) override {
1485*d57664e9SAndroid Build Coastguard Worker name = GetAttributeString(FindAttribute(element, NAME_ATTR));
1486*d57664e9SAndroid Build Coastguard Worker maxSdkVersion = GetAttributeInteger(FindAttribute(element, MAX_SDK_VERSION_ATTR));
1487*d57664e9SAndroid Build Coastguard Worker
1488*d57664e9SAndroid Build Coastguard Worker if (name) {
1489*d57664e9SAndroid Build Coastguard Worker CommonFeatureGroup* common = extractor()->common_feature_group();
1490*d57664e9SAndroid Build Coastguard Worker common->addImpliedFeaturesForPermission(extractor()->target_sdk(), *name, true);
1491*d57664e9SAndroid Build Coastguard Worker }
1492*d57664e9SAndroid Build Coastguard Worker }
1493*d57664e9SAndroid Build Coastguard Worker
Print(text::Printer * printer)1494*d57664e9SAndroid Build Coastguard Worker void Print(text::Printer* printer) override {
1495*d57664e9SAndroid Build Coastguard Worker if (name) {
1496*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("uses-permission-sdk-23: name='%s'", name->data()));
1497*d57664e9SAndroid Build Coastguard Worker if (maxSdkVersion) {
1498*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" maxSdkVersion='%d'", *maxSdkVersion));
1499*d57664e9SAndroid Build Coastguard Worker }
1500*d57664e9SAndroid Build Coastguard Worker printer->Print("\n");
1501*d57664e9SAndroid Build Coastguard Worker }
1502*d57664e9SAndroid Build Coastguard Worker }
1503*d57664e9SAndroid Build Coastguard Worker
ToProto(pb::Badging * out_badging)1504*d57664e9SAndroid Build Coastguard Worker void ToProto(pb::Badging* out_badging) override {
1505*d57664e9SAndroid Build Coastguard Worker if (name) {
1506*d57664e9SAndroid Build Coastguard Worker auto permission = out_badging->add_uses_permissions();
1507*d57664e9SAndroid Build Coastguard Worker permission->set_sdk23_and_above(true);
1508*d57664e9SAndroid Build Coastguard Worker permission->set_name(*name);
1509*d57664e9SAndroid Build Coastguard Worker if (maxSdkVersion) {
1510*d57664e9SAndroid Build Coastguard Worker permission->set_max_sdk_version(*maxSdkVersion);
1511*d57664e9SAndroid Build Coastguard Worker }
1512*d57664e9SAndroid Build Coastguard Worker }
1513*d57664e9SAndroid Build Coastguard Worker }
1514*d57664e9SAndroid Build Coastguard Worker };
1515*d57664e9SAndroid Build Coastguard Worker
1516*d57664e9SAndroid Build Coastguard Worker /** Represents <permission> elements. These elements are only printing when dumping permissions. **/
1517*d57664e9SAndroid Build Coastguard Worker class Permission : public ManifestExtractor::Element {
1518*d57664e9SAndroid Build Coastguard Worker public:
1519*d57664e9SAndroid Build Coastguard Worker Permission() = default;
1520*d57664e9SAndroid Build Coastguard Worker std::string name;
1521*d57664e9SAndroid Build Coastguard Worker
Extract(xml::Element * element)1522*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* element) override {
1523*d57664e9SAndroid Build Coastguard Worker name = GetAttributeStringDefault(FindAttribute(element, NAME_ATTR), "");
1524*d57664e9SAndroid Build Coastguard Worker }
1525*d57664e9SAndroid Build Coastguard Worker
Print(text::Printer * printer)1526*d57664e9SAndroid Build Coastguard Worker void Print(text::Printer* printer) override {
1527*d57664e9SAndroid Build Coastguard Worker if (extractor()->options_.only_permissions && !name.empty()) {
1528*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("permission: %s\n", name.data()));
1529*d57664e9SAndroid Build Coastguard Worker }
1530*d57664e9SAndroid Build Coastguard Worker }
1531*d57664e9SAndroid Build Coastguard Worker
ToProto(pb::Badging * out_badging)1532*d57664e9SAndroid Build Coastguard Worker void ToProto(pb::Badging* out_badging) override {
1533*d57664e9SAndroid Build Coastguard Worker if (!name.empty()) {
1534*d57664e9SAndroid Build Coastguard Worker out_badging->add_permissions()->set_name(name);
1535*d57664e9SAndroid Build Coastguard Worker }
1536*d57664e9SAndroid Build Coastguard Worker }
1537*d57664e9SAndroid Build Coastguard Worker };
1538*d57664e9SAndroid Build Coastguard Worker
1539*d57664e9SAndroid Build Coastguard Worker /** Represents <activity> elements. **/
1540*d57664e9SAndroid Build Coastguard Worker class Activity : public ManifestExtractor::Element {
1541*d57664e9SAndroid Build Coastguard Worker public:
1542*d57664e9SAndroid Build Coastguard Worker Activity() = default;
1543*d57664e9SAndroid Build Coastguard Worker std::string name;
1544*d57664e9SAndroid Build Coastguard Worker std::string icon;
1545*d57664e9SAndroid Build Coastguard Worker std::string label;
1546*d57664e9SAndroid Build Coastguard Worker std::string banner;
1547*d57664e9SAndroid Build Coastguard Worker
1548*d57664e9SAndroid Build Coastguard Worker bool has_component_ = false;
1549*d57664e9SAndroid Build Coastguard Worker bool has_launcher_category = false;
1550*d57664e9SAndroid Build Coastguard Worker bool has_leanback_launcher_category = false;
1551*d57664e9SAndroid Build Coastguard Worker bool has_main_action = false;
1552*d57664e9SAndroid Build Coastguard Worker
Extract(xml::Element * element)1553*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* element) override {
1554*d57664e9SAndroid Build Coastguard Worker name = GetAttributeStringDefault(FindAttribute(element, NAME_ATTR), "");
1555*d57664e9SAndroid Build Coastguard Worker label = GetAttributeStringDefault(FindAttribute(element, LABEL_ATTR), "");
1556*d57664e9SAndroid Build Coastguard Worker icon = GetAttributeStringDefault(FindAttribute(element, ICON_ATTR), "");
1557*d57664e9SAndroid Build Coastguard Worker banner = GetAttributeStringDefault(FindAttribute(element, BANNER_ATTR), "");
1558*d57664e9SAndroid Build Coastguard Worker
1559*d57664e9SAndroid Build Coastguard Worker // Retrieve the package name from the manifest
1560*d57664e9SAndroid Build Coastguard Worker std::string package;
1561*d57664e9SAndroid Build Coastguard Worker for (auto& parent : extractor()->parent_stack()) {
1562*d57664e9SAndroid Build Coastguard Worker if (auto manifest = ElementCast<Manifest>(parent)) {
1563*d57664e9SAndroid Build Coastguard Worker package = manifest->package;
1564*d57664e9SAndroid Build Coastguard Worker break;
1565*d57664e9SAndroid Build Coastguard Worker }
1566*d57664e9SAndroid Build Coastguard Worker }
1567*d57664e9SAndroid Build Coastguard Worker
1568*d57664e9SAndroid Build Coastguard Worker // Fully qualify the activity name
1569*d57664e9SAndroid Build Coastguard Worker ssize_t idx = name.find('.');
1570*d57664e9SAndroid Build Coastguard Worker if (idx == 0) {
1571*d57664e9SAndroid Build Coastguard Worker name = package + name;
1572*d57664e9SAndroid Build Coastguard Worker } else if (idx < 0) {
1573*d57664e9SAndroid Build Coastguard Worker name = package + "." + name;
1574*d57664e9SAndroid Build Coastguard Worker }
1575*d57664e9SAndroid Build Coastguard Worker
1576*d57664e9SAndroid Build Coastguard Worker auto orientation = GetAttributeInteger(FindAttribute(element, SCREEN_ORIENTATION_ATTR));
1577*d57664e9SAndroid Build Coastguard Worker if (orientation) {
1578*d57664e9SAndroid Build Coastguard Worker CommonFeatureGroup* common = extractor()->common_feature_group();
1579*d57664e9SAndroid Build Coastguard Worker int orien = *orientation;
1580*d57664e9SAndroid Build Coastguard Worker if (orien == 0 || orien == 6 || orien == 8) {
1581*d57664e9SAndroid Build Coastguard Worker // Requests landscape, sensorLandscape, or reverseLandscape.
1582*d57664e9SAndroid Build Coastguard Worker common->addImpliedFeature("android.hardware.screen.landscape",
1583*d57664e9SAndroid Build Coastguard Worker "one or more activities have specified a landscape orientation",
1584*d57664e9SAndroid Build Coastguard Worker false);
1585*d57664e9SAndroid Build Coastguard Worker } else if (orien == 1 || orien == 7 || orien == 9) {
1586*d57664e9SAndroid Build Coastguard Worker // Requests portrait, sensorPortrait, or reversePortrait.
1587*d57664e9SAndroid Build Coastguard Worker common->addImpliedFeature("android.hardware.screen.portrait",
1588*d57664e9SAndroid Build Coastguard Worker "one or more activities have specified a portrait orientation",
1589*d57664e9SAndroid Build Coastguard Worker false);
1590*d57664e9SAndroid Build Coastguard Worker }
1591*d57664e9SAndroid Build Coastguard Worker }
1592*d57664e9SAndroid Build Coastguard Worker }
1593*d57664e9SAndroid Build Coastguard Worker
Print(text::Printer * printer)1594*d57664e9SAndroid Build Coastguard Worker void Print(text::Printer* printer) override {
1595*d57664e9SAndroid Build Coastguard Worker // Print whether the activity has the HOME category and a the MAIN action
1596*d57664e9SAndroid Build Coastguard Worker if (has_main_action && has_launcher_category) {
1597*d57664e9SAndroid Build Coastguard Worker printer->Print("launchable-activity:");
1598*d57664e9SAndroid Build Coastguard Worker if (!name.empty()) {
1599*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" name='%s' ", name.data()));
1600*d57664e9SAndroid Build Coastguard Worker }
1601*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" label='%s' icon='%s'\n",
1602*d57664e9SAndroid Build Coastguard Worker android::ResTable::normalizeForOutput(label.data()).c_str(),
1603*d57664e9SAndroid Build Coastguard Worker icon.data()));
1604*d57664e9SAndroid Build Coastguard Worker }
1605*d57664e9SAndroid Build Coastguard Worker
1606*d57664e9SAndroid Build Coastguard Worker // Print wether the activity has the HOME category and a the MAIN action
1607*d57664e9SAndroid Build Coastguard Worker if (has_leanback_launcher_category) {
1608*d57664e9SAndroid Build Coastguard Worker printer->Print("leanback-launchable-activity:");
1609*d57664e9SAndroid Build Coastguard Worker if (!name.empty()) {
1610*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" name='%s' ", name.data()));
1611*d57664e9SAndroid Build Coastguard Worker }
1612*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" label='%s' icon='%s' banner='%s'\n",
1613*d57664e9SAndroid Build Coastguard Worker android::ResTable::normalizeForOutput(label.data()).c_str(),
1614*d57664e9SAndroid Build Coastguard Worker icon.data(), banner.data()));
1615*d57664e9SAndroid Build Coastguard Worker }
1616*d57664e9SAndroid Build Coastguard Worker }
1617*d57664e9SAndroid Build Coastguard Worker
ToProto(pb::Badging * out_badging)1618*d57664e9SAndroid Build Coastguard Worker void ToProto(pb::Badging* out_badging) override {
1619*d57664e9SAndroid Build Coastguard Worker if (has_main_action && has_launcher_category) {
1620*d57664e9SAndroid Build Coastguard Worker auto activity = out_badging->mutable_launchable_activity();
1621*d57664e9SAndroid Build Coastguard Worker activity->set_name(name);
1622*d57664e9SAndroid Build Coastguard Worker activity->set_label(android::ResTable::normalizeForOutput(label.data()));
1623*d57664e9SAndroid Build Coastguard Worker activity->set_icon(icon);
1624*d57664e9SAndroid Build Coastguard Worker }
1625*d57664e9SAndroid Build Coastguard Worker if (has_leanback_launcher_category) {
1626*d57664e9SAndroid Build Coastguard Worker auto activity = out_badging->mutable_leanback_launchable_activity();
1627*d57664e9SAndroid Build Coastguard Worker activity->set_name(name);
1628*d57664e9SAndroid Build Coastguard Worker activity->set_label(android::ResTable::normalizeForOutput(label.data()));
1629*d57664e9SAndroid Build Coastguard Worker activity->set_icon(icon);
1630*d57664e9SAndroid Build Coastguard Worker activity->set_banner(banner);
1631*d57664e9SAndroid Build Coastguard Worker }
1632*d57664e9SAndroid Build Coastguard Worker }
1633*d57664e9SAndroid Build Coastguard Worker };
1634*d57664e9SAndroid Build Coastguard Worker
1635*d57664e9SAndroid Build Coastguard Worker /** Represents <intent-filter> elements. */
1636*d57664e9SAndroid Build Coastguard Worker class IntentFilter : public ManifestExtractor::Element {
1637*d57664e9SAndroid Build Coastguard Worker public:
1638*d57664e9SAndroid Build Coastguard Worker IntentFilter() = default;
1639*d57664e9SAndroid Build Coastguard Worker };
1640*d57664e9SAndroid Build Coastguard Worker
1641*d57664e9SAndroid Build Coastguard Worker /** Represents <category> elements. */
1642*d57664e9SAndroid Build Coastguard Worker class Category : public ManifestExtractor::Element {
1643*d57664e9SAndroid Build Coastguard Worker public:
1644*d57664e9SAndroid Build Coastguard Worker Category() = default;
1645*d57664e9SAndroid Build Coastguard Worker std::string component = "";
1646*d57664e9SAndroid Build Coastguard Worker
Extract(xml::Element * element)1647*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* element) override {
1648*d57664e9SAndroid Build Coastguard Worker const std::string* category = GetAttributeString(FindAttribute(element, NAME_ATTR));
1649*d57664e9SAndroid Build Coastguard Worker
1650*d57664e9SAndroid Build Coastguard Worker auto parent_stack = extractor()->parent_stack();
1651*d57664e9SAndroid Build Coastguard Worker if (category && ElementCast<IntentFilter>(parent_stack[0])
1652*d57664e9SAndroid Build Coastguard Worker && ElementCast<Activity>(parent_stack[1])) {
1653*d57664e9SAndroid Build Coastguard Worker Activity* activity = ElementCast<Activity>(parent_stack[1]);
1654*d57664e9SAndroid Build Coastguard Worker
1655*d57664e9SAndroid Build Coastguard Worker if (*category == "android.intent.category.LAUNCHER") {
1656*d57664e9SAndroid Build Coastguard Worker activity->has_launcher_category = true;
1657*d57664e9SAndroid Build Coastguard Worker } else if (*category == "android.intent.category.LEANBACK_LAUNCHER") {
1658*d57664e9SAndroid Build Coastguard Worker activity->has_leanback_launcher_category = true;
1659*d57664e9SAndroid Build Coastguard Worker } else if (*category == "android.intent.category.HOME") {
1660*d57664e9SAndroid Build Coastguard Worker component = "launcher";
1661*d57664e9SAndroid Build Coastguard Worker }
1662*d57664e9SAndroid Build Coastguard Worker }
1663*d57664e9SAndroid Build Coastguard Worker }
1664*d57664e9SAndroid Build Coastguard Worker };
1665*d57664e9SAndroid Build Coastguard Worker
1666*d57664e9SAndroid Build Coastguard Worker /**
1667*d57664e9SAndroid Build Coastguard Worker * Represents <provider> elements. The elements may have an <intent-filter> which may have <action>
1668*d57664e9SAndroid Build Coastguard Worker * elements nested within.
1669*d57664e9SAndroid Build Coastguard Worker **/
1670*d57664e9SAndroid Build Coastguard Worker class Provider : public ManifestExtractor::Element {
1671*d57664e9SAndroid Build Coastguard Worker public:
1672*d57664e9SAndroid Build Coastguard Worker Provider() = default;
1673*d57664e9SAndroid Build Coastguard Worker bool has_required_saf_attributes = false;
1674*d57664e9SAndroid Build Coastguard Worker
Extract(xml::Element * element)1675*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* element) override {
1676*d57664e9SAndroid Build Coastguard Worker const int32_t* exported = GetAttributeInteger(FindAttribute(element, EXPORTED_ATTR));
1677*d57664e9SAndroid Build Coastguard Worker const int32_t* grant_uri_permissions = GetAttributeInteger(
1678*d57664e9SAndroid Build Coastguard Worker FindAttribute(element, GRANT_URI_PERMISSIONS_ATTR));
1679*d57664e9SAndroid Build Coastguard Worker const std::string* permission = GetAttributeString(
1680*d57664e9SAndroid Build Coastguard Worker FindAttribute(element, PERMISSION_ATTR));
1681*d57664e9SAndroid Build Coastguard Worker
1682*d57664e9SAndroid Build Coastguard Worker has_required_saf_attributes = ((exported && *exported != 0)
1683*d57664e9SAndroid Build Coastguard Worker && (grant_uri_permissions && *grant_uri_permissions != 0)
1684*d57664e9SAndroid Build Coastguard Worker && (permission && *permission == "android.permission.MANAGE_DOCUMENTS"));
1685*d57664e9SAndroid Build Coastguard Worker }
1686*d57664e9SAndroid Build Coastguard Worker };
1687*d57664e9SAndroid Build Coastguard Worker
1688*d57664e9SAndroid Build Coastguard Worker /** Represents <receiver> elements. **/
1689*d57664e9SAndroid Build Coastguard Worker class Receiver : public ManifestExtractor::Element {
1690*d57664e9SAndroid Build Coastguard Worker public:
1691*d57664e9SAndroid Build Coastguard Worker Receiver() = default;
1692*d57664e9SAndroid Build Coastguard Worker const std::string* permission = nullptr;
1693*d57664e9SAndroid Build Coastguard Worker bool has_component = false;
1694*d57664e9SAndroid Build Coastguard Worker
Extract(xml::Element * element)1695*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* element) override {
1696*d57664e9SAndroid Build Coastguard Worker permission = GetAttributeString(FindAttribute(element, PERMISSION_ATTR));
1697*d57664e9SAndroid Build Coastguard Worker }
1698*d57664e9SAndroid Build Coastguard Worker };
1699*d57664e9SAndroid Build Coastguard Worker
1700*d57664e9SAndroid Build Coastguard Worker /**Represents <service> elements. **/
1701*d57664e9SAndroid Build Coastguard Worker class Service : public ManifestExtractor::Element {
1702*d57664e9SAndroid Build Coastguard Worker public:
1703*d57664e9SAndroid Build Coastguard Worker Service() = default;
1704*d57664e9SAndroid Build Coastguard Worker const std::string* permission = nullptr;
1705*d57664e9SAndroid Build Coastguard Worker bool has_component = false;
1706*d57664e9SAndroid Build Coastguard Worker
Extract(xml::Element * element)1707*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* element) override {
1708*d57664e9SAndroid Build Coastguard Worker permission = GetAttributeString(FindAttribute(element, PERMISSION_ATTR));
1709*d57664e9SAndroid Build Coastguard Worker }
1710*d57664e9SAndroid Build Coastguard Worker };
1711*d57664e9SAndroid Build Coastguard Worker
1712*d57664e9SAndroid Build Coastguard Worker /** Represents <uses-library> elements. **/
1713*d57664e9SAndroid Build Coastguard Worker class UsesLibrary : public ManifestExtractor::Element {
1714*d57664e9SAndroid Build Coastguard Worker public:
1715*d57664e9SAndroid Build Coastguard Worker UsesLibrary() = default;
1716*d57664e9SAndroid Build Coastguard Worker std::string name;
1717*d57664e9SAndroid Build Coastguard Worker int required;
1718*d57664e9SAndroid Build Coastguard Worker
Extract(xml::Element * element)1719*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* element) override {
1720*d57664e9SAndroid Build Coastguard Worker name = GetAttributeStringDefault(FindAttribute(element, NAME_ATTR), "");
1721*d57664e9SAndroid Build Coastguard Worker required = GetAttributeIntegerDefault(FindAttribute(element, REQUIRED_ATTR), 1);
1722*d57664e9SAndroid Build Coastguard Worker }
1723*d57664e9SAndroid Build Coastguard Worker
Print(text::Printer * printer)1724*d57664e9SAndroid Build Coastguard Worker void Print(text::Printer* printer) override {
1725*d57664e9SAndroid Build Coastguard Worker if (!name.empty()) {
1726*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("uses-library%s:'%s'\n",
1727*d57664e9SAndroid Build Coastguard Worker (required == 0) ? "-not-required" : "", name.data()));
1728*d57664e9SAndroid Build Coastguard Worker }
1729*d57664e9SAndroid Build Coastguard Worker }
1730*d57664e9SAndroid Build Coastguard Worker
ToProto(pb::Badging * out_badging)1731*d57664e9SAndroid Build Coastguard Worker void ToProto(pb::Badging* out_badging) override {
1732*d57664e9SAndroid Build Coastguard Worker if (!name.empty()) {
1733*d57664e9SAndroid Build Coastguard Worker auto uses_library = out_badging->add_uses_libraries();
1734*d57664e9SAndroid Build Coastguard Worker uses_library->set_name(name);
1735*d57664e9SAndroid Build Coastguard Worker uses_library->set_required(required != 0);
1736*d57664e9SAndroid Build Coastguard Worker }
1737*d57664e9SAndroid Build Coastguard Worker }
1738*d57664e9SAndroid Build Coastguard Worker };
1739*d57664e9SAndroid Build Coastguard Worker
1740*d57664e9SAndroid Build Coastguard Worker /** Represents <static-library> elements. **/
1741*d57664e9SAndroid Build Coastguard Worker class StaticLibrary : public ManifestExtractor::Element {
1742*d57664e9SAndroid Build Coastguard Worker public:
1743*d57664e9SAndroid Build Coastguard Worker StaticLibrary() = default;
1744*d57664e9SAndroid Build Coastguard Worker std::string name;
1745*d57664e9SAndroid Build Coastguard Worker int version;
1746*d57664e9SAndroid Build Coastguard Worker int versionMajor;
1747*d57664e9SAndroid Build Coastguard Worker
Extract(xml::Element * element)1748*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* element) override {
1749*d57664e9SAndroid Build Coastguard Worker name = GetAttributeStringDefault(FindAttribute(element, NAME_ATTR), "");
1750*d57664e9SAndroid Build Coastguard Worker version = GetAttributeIntegerDefault(FindAttribute(element, VERSION_ATTR), 0);
1751*d57664e9SAndroid Build Coastguard Worker versionMajor = GetAttributeIntegerDefault(FindAttribute(element, VERSION_MAJOR_ATTR), 0);
1752*d57664e9SAndroid Build Coastguard Worker }
1753*d57664e9SAndroid Build Coastguard Worker
Print(text::Printer * printer)1754*d57664e9SAndroid Build Coastguard Worker void Print(text::Printer* printer) override {
1755*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(
1756*d57664e9SAndroid Build Coastguard Worker "static-library: name='%s' version='%d' versionMajor='%d'\n",
1757*d57664e9SAndroid Build Coastguard Worker name.data(), version, versionMajor));
1758*d57664e9SAndroid Build Coastguard Worker }
1759*d57664e9SAndroid Build Coastguard Worker
ToProto(pb::Badging * out_badging)1760*d57664e9SAndroid Build Coastguard Worker void ToProto(pb::Badging* out_badging) override {
1761*d57664e9SAndroid Build Coastguard Worker auto static_library = out_badging->mutable_static_library();
1762*d57664e9SAndroid Build Coastguard Worker static_library->set_name(name);
1763*d57664e9SAndroid Build Coastguard Worker static_library->set_version(version);
1764*d57664e9SAndroid Build Coastguard Worker static_library->set_version_major(versionMajor);
1765*d57664e9SAndroid Build Coastguard Worker }
1766*d57664e9SAndroid Build Coastguard Worker };
1767*d57664e9SAndroid Build Coastguard Worker
1768*d57664e9SAndroid Build Coastguard Worker /** Represents <uses-static-library> elements. **/
1769*d57664e9SAndroid Build Coastguard Worker class UsesStaticLibrary : public ManifestExtractor::Element {
1770*d57664e9SAndroid Build Coastguard Worker public:
1771*d57664e9SAndroid Build Coastguard Worker UsesStaticLibrary() = default;
1772*d57664e9SAndroid Build Coastguard Worker std::string name;
1773*d57664e9SAndroid Build Coastguard Worker int version;
1774*d57664e9SAndroid Build Coastguard Worker int versionMajor;
1775*d57664e9SAndroid Build Coastguard Worker std::vector<std::string> certDigests;
1776*d57664e9SAndroid Build Coastguard Worker
Extract(xml::Element * element)1777*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* element) override {
1778*d57664e9SAndroid Build Coastguard Worker name = GetAttributeStringDefault(FindAttribute(element, NAME_ATTR), "");
1779*d57664e9SAndroid Build Coastguard Worker version = GetAttributeIntegerDefault(FindAttribute(element, VERSION_ATTR), 0);
1780*d57664e9SAndroid Build Coastguard Worker versionMajor = GetAttributeIntegerDefault(FindAttribute(element, VERSION_MAJOR_ATTR), 0);
1781*d57664e9SAndroid Build Coastguard Worker AddCertDigest(element);
1782*d57664e9SAndroid Build Coastguard Worker }
1783*d57664e9SAndroid Build Coastguard Worker
AddCertDigest(xml::Element * element)1784*d57664e9SAndroid Build Coastguard Worker void AddCertDigest(xml::Element* element) {
1785*d57664e9SAndroid Build Coastguard Worker std::string digest = GetAttributeStringDefault(FindAttribute(element, CERT_DIGEST_ATTR), "");
1786*d57664e9SAndroid Build Coastguard Worker // We allow ":" delimiters in the SHA declaration as this is the format
1787*d57664e9SAndroid Build Coastguard Worker // emitted by the certtool making it easy for developers to copy/paste.
1788*d57664e9SAndroid Build Coastguard Worker digest.erase(std::remove(digest.begin(), digest.end(), ':'), digest.end());
1789*d57664e9SAndroid Build Coastguard Worker if (!digest.empty()) {
1790*d57664e9SAndroid Build Coastguard Worker certDigests.push_back(digest);
1791*d57664e9SAndroid Build Coastguard Worker }
1792*d57664e9SAndroid Build Coastguard Worker }
1793*d57664e9SAndroid Build Coastguard Worker
Print(text::Printer * printer)1794*d57664e9SAndroid Build Coastguard Worker void Print(text::Printer* printer) override {
1795*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(
1796*d57664e9SAndroid Build Coastguard Worker "uses-static-library: name='%s' version='%d' versionMajor='%d'",
1797*d57664e9SAndroid Build Coastguard Worker name.data(), version, versionMajor));
1798*d57664e9SAndroid Build Coastguard Worker for (size_t i = 0; i < certDigests.size(); i++) {
1799*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" certDigest='%s'", certDigests[i].data()));
1800*d57664e9SAndroid Build Coastguard Worker }
1801*d57664e9SAndroid Build Coastguard Worker printer->Print("\n");
1802*d57664e9SAndroid Build Coastguard Worker }
1803*d57664e9SAndroid Build Coastguard Worker
ToProto(pb::Badging * out_badging)1804*d57664e9SAndroid Build Coastguard Worker void ToProto(pb::Badging* out_badging) override {
1805*d57664e9SAndroid Build Coastguard Worker auto uses_static_library = out_badging->add_uses_static_libraries();
1806*d57664e9SAndroid Build Coastguard Worker uses_static_library->set_name(name);
1807*d57664e9SAndroid Build Coastguard Worker uses_static_library->set_version(version);
1808*d57664e9SAndroid Build Coastguard Worker uses_static_library->set_version_major(versionMajor);
1809*d57664e9SAndroid Build Coastguard Worker for (auto& cert : certDigests) {
1810*d57664e9SAndroid Build Coastguard Worker uses_static_library->add_certificates(cert);
1811*d57664e9SAndroid Build Coastguard Worker }
1812*d57664e9SAndroid Build Coastguard Worker }
1813*d57664e9SAndroid Build Coastguard Worker };
1814*d57664e9SAndroid Build Coastguard Worker
1815*d57664e9SAndroid Build Coastguard Worker /** Represents <sdk-library> elements. **/
1816*d57664e9SAndroid Build Coastguard Worker class SdkLibrary : public ManifestExtractor::Element {
1817*d57664e9SAndroid Build Coastguard Worker public:
1818*d57664e9SAndroid Build Coastguard Worker SdkLibrary() = default;
1819*d57664e9SAndroid Build Coastguard Worker std::string name;
1820*d57664e9SAndroid Build Coastguard Worker int versionMajor;
1821*d57664e9SAndroid Build Coastguard Worker
Extract(xml::Element * element)1822*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* element) override {
1823*d57664e9SAndroid Build Coastguard Worker name = GetAttributeStringDefault(FindAttribute(element, NAME_ATTR), "");
1824*d57664e9SAndroid Build Coastguard Worker versionMajor = GetAttributeIntegerDefault(FindAttribute(element, VERSION_MAJOR_ATTR), 0);
1825*d57664e9SAndroid Build Coastguard Worker }
1826*d57664e9SAndroid Build Coastguard Worker
Print(text::Printer * printer)1827*d57664e9SAndroid Build Coastguard Worker void Print(text::Printer* printer) override {
1828*d57664e9SAndroid Build Coastguard Worker printer->Print(
1829*d57664e9SAndroid Build Coastguard Worker StringPrintf("sdk-library: name='%s' versionMajor='%d'\n", name.data(), versionMajor));
1830*d57664e9SAndroid Build Coastguard Worker }
1831*d57664e9SAndroid Build Coastguard Worker
ToProto(pb::Badging * out_badging)1832*d57664e9SAndroid Build Coastguard Worker void ToProto(pb::Badging* out_badging) override {
1833*d57664e9SAndroid Build Coastguard Worker auto sdk_library = out_badging->mutable_sdk_library();
1834*d57664e9SAndroid Build Coastguard Worker sdk_library->set_name(name);
1835*d57664e9SAndroid Build Coastguard Worker sdk_library->set_version_major(versionMajor);
1836*d57664e9SAndroid Build Coastguard Worker }
1837*d57664e9SAndroid Build Coastguard Worker };
1838*d57664e9SAndroid Build Coastguard Worker
1839*d57664e9SAndroid Build Coastguard Worker /** Represents <uses-sdk-library> elements. **/
1840*d57664e9SAndroid Build Coastguard Worker class UsesSdkLibrary : public ManifestExtractor::Element {
1841*d57664e9SAndroid Build Coastguard Worker public:
1842*d57664e9SAndroid Build Coastguard Worker UsesSdkLibrary() = default;
1843*d57664e9SAndroid Build Coastguard Worker std::string name;
1844*d57664e9SAndroid Build Coastguard Worker int versionMajor;
1845*d57664e9SAndroid Build Coastguard Worker std::vector<std::string> certDigests;
1846*d57664e9SAndroid Build Coastguard Worker
Extract(xml::Element * element)1847*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* element) override {
1848*d57664e9SAndroid Build Coastguard Worker name = GetAttributeStringDefault(FindAttribute(element, NAME_ATTR), "");
1849*d57664e9SAndroid Build Coastguard Worker versionMajor = GetAttributeIntegerDefault(FindAttribute(element, VERSION_MAJOR_ATTR), 0);
1850*d57664e9SAndroid Build Coastguard Worker AddCertDigest(element);
1851*d57664e9SAndroid Build Coastguard Worker }
1852*d57664e9SAndroid Build Coastguard Worker
AddCertDigest(xml::Element * element)1853*d57664e9SAndroid Build Coastguard Worker void AddCertDigest(xml::Element* element) {
1854*d57664e9SAndroid Build Coastguard Worker std::string digest = GetAttributeStringDefault(FindAttribute(element, CERT_DIGEST_ATTR), "");
1855*d57664e9SAndroid Build Coastguard Worker // We allow ":" delimiters in the SHA declaration as this is the format
1856*d57664e9SAndroid Build Coastguard Worker // emitted by the certtool making it easy for developers to copy/paste.
1857*d57664e9SAndroid Build Coastguard Worker digest.erase(std::remove(digest.begin(), digest.end(), ':'), digest.end());
1858*d57664e9SAndroid Build Coastguard Worker if (!digest.empty()) {
1859*d57664e9SAndroid Build Coastguard Worker certDigests.push_back(digest);
1860*d57664e9SAndroid Build Coastguard Worker }
1861*d57664e9SAndroid Build Coastguard Worker }
1862*d57664e9SAndroid Build Coastguard Worker
Print(text::Printer * printer)1863*d57664e9SAndroid Build Coastguard Worker void Print(text::Printer* printer) override {
1864*d57664e9SAndroid Build Coastguard Worker printer->Print(
1865*d57664e9SAndroid Build Coastguard Worker StringPrintf("uses-sdk-library: name='%s' versionMajor='%d'", name.data(), versionMajor));
1866*d57664e9SAndroid Build Coastguard Worker for (size_t i = 0; i < certDigests.size(); i++) {
1867*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" certDigest='%s'", certDigests[i].data()));
1868*d57664e9SAndroid Build Coastguard Worker }
1869*d57664e9SAndroid Build Coastguard Worker printer->Print("\n");
1870*d57664e9SAndroid Build Coastguard Worker }
1871*d57664e9SAndroid Build Coastguard Worker
ToProto(pb::Badging * out_badging)1872*d57664e9SAndroid Build Coastguard Worker void ToProto(pb::Badging* out_badging) override {
1873*d57664e9SAndroid Build Coastguard Worker auto uses_sdk_library = out_badging->add_uses_sdk_libraries();
1874*d57664e9SAndroid Build Coastguard Worker uses_sdk_library->set_name(name);
1875*d57664e9SAndroid Build Coastguard Worker uses_sdk_library->set_version_major(versionMajor);
1876*d57664e9SAndroid Build Coastguard Worker for (auto& cert : certDigests) {
1877*d57664e9SAndroid Build Coastguard Worker uses_sdk_library->add_certificates(cert);
1878*d57664e9SAndroid Build Coastguard Worker }
1879*d57664e9SAndroid Build Coastguard Worker }
1880*d57664e9SAndroid Build Coastguard Worker };
1881*d57664e9SAndroid Build Coastguard Worker
1882*d57664e9SAndroid Build Coastguard Worker /** Represents <uses-native-library> elements. **/
1883*d57664e9SAndroid Build Coastguard Worker class UsesNativeLibrary : public ManifestExtractor::Element {
1884*d57664e9SAndroid Build Coastguard Worker public:
1885*d57664e9SAndroid Build Coastguard Worker UsesNativeLibrary() = default;
1886*d57664e9SAndroid Build Coastguard Worker std::string name;
1887*d57664e9SAndroid Build Coastguard Worker int required;
1888*d57664e9SAndroid Build Coastguard Worker
Extract(xml::Element * element)1889*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* element) override {
1890*d57664e9SAndroid Build Coastguard Worker name = GetAttributeStringDefault(FindAttribute(element, NAME_ATTR), "");
1891*d57664e9SAndroid Build Coastguard Worker required = GetAttributeIntegerDefault(FindAttribute(element, REQUIRED_ATTR), 1);
1892*d57664e9SAndroid Build Coastguard Worker }
1893*d57664e9SAndroid Build Coastguard Worker
Print(text::Printer * printer)1894*d57664e9SAndroid Build Coastguard Worker void Print(text::Printer* printer) override {
1895*d57664e9SAndroid Build Coastguard Worker if (!name.empty()) {
1896*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("uses-native-library%s:'%s'\n",
1897*d57664e9SAndroid Build Coastguard Worker (required == 0) ? "-not-required" : "", name.data()));
1898*d57664e9SAndroid Build Coastguard Worker }
1899*d57664e9SAndroid Build Coastguard Worker }
1900*d57664e9SAndroid Build Coastguard Worker
ToProto(pb::Badging * out_badging)1901*d57664e9SAndroid Build Coastguard Worker void ToProto(pb::Badging* out_badging) override {
1902*d57664e9SAndroid Build Coastguard Worker if (!name.empty()) {
1903*d57664e9SAndroid Build Coastguard Worker auto uses_native_library = out_badging->add_uses_native_libraries();
1904*d57664e9SAndroid Build Coastguard Worker uses_native_library->set_name(name);
1905*d57664e9SAndroid Build Coastguard Worker uses_native_library->set_required(required != 0);
1906*d57664e9SAndroid Build Coastguard Worker }
1907*d57664e9SAndroid Build Coastguard Worker }
1908*d57664e9SAndroid Build Coastguard Worker };
1909*d57664e9SAndroid Build Coastguard Worker
1910*d57664e9SAndroid Build Coastguard Worker /**
1911*d57664e9SAndroid Build Coastguard Worker * Represents <meta-data> elements. These tags are only printed when a flag is passed in to
1912*d57664e9SAndroid Build Coastguard Worker * explicitly enable meta data printing.
1913*d57664e9SAndroid Build Coastguard Worker **/
1914*d57664e9SAndroid Build Coastguard Worker class MetaData : public ManifestExtractor::Element {
1915*d57664e9SAndroid Build Coastguard Worker public:
1916*d57664e9SAndroid Build Coastguard Worker MetaData() = default;
1917*d57664e9SAndroid Build Coastguard Worker std::string name;
1918*d57664e9SAndroid Build Coastguard Worker std::string value;
1919*d57664e9SAndroid Build Coastguard Worker const int* value_int;
1920*d57664e9SAndroid Build Coastguard Worker std::string resource;
1921*d57664e9SAndroid Build Coastguard Worker const int* resource_int;
1922*d57664e9SAndroid Build Coastguard Worker
Extract(xml::Element * element)1923*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* element) override {
1924*d57664e9SAndroid Build Coastguard Worker name = GetAttributeStringDefault(FindAttribute(element, NAME_ATTR), "");
1925*d57664e9SAndroid Build Coastguard Worker value = GetAttributeStringDefault(FindAttribute(element, VALUE_ATTR), "");
1926*d57664e9SAndroid Build Coastguard Worker value_int = GetAttributeInteger(FindAttribute(element, VALUE_ATTR));
1927*d57664e9SAndroid Build Coastguard Worker resource = GetAttributeStringDefault(FindAttribute(element, RESOURCE_ATTR), "");
1928*d57664e9SAndroid Build Coastguard Worker resource_int = GetAttributeInteger(FindAttribute(element, RESOURCE_ATTR));
1929*d57664e9SAndroid Build Coastguard Worker }
1930*d57664e9SAndroid Build Coastguard Worker
Print(text::Printer * printer)1931*d57664e9SAndroid Build Coastguard Worker void Print(text::Printer* printer) override {
1932*d57664e9SAndroid Build Coastguard Worker if (extractor()->options_.include_meta_data && !name.empty()) {
1933*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("meta-data: name='%s'", name.data()));
1934*d57664e9SAndroid Build Coastguard Worker if (!value.empty()) {
1935*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" value='%s'", value.data()));
1936*d57664e9SAndroid Build Coastguard Worker } else if (value_int) {
1937*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" value='%d'", *value_int));
1938*d57664e9SAndroid Build Coastguard Worker } else {
1939*d57664e9SAndroid Build Coastguard Worker if (!resource.empty()) {
1940*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" resource='%s'", resource.data()));
1941*d57664e9SAndroid Build Coastguard Worker } else if (resource_int) {
1942*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" resource='%d'", *resource_int));
1943*d57664e9SAndroid Build Coastguard Worker }
1944*d57664e9SAndroid Build Coastguard Worker }
1945*d57664e9SAndroid Build Coastguard Worker printer->Print("\n");
1946*d57664e9SAndroid Build Coastguard Worker }
1947*d57664e9SAndroid Build Coastguard Worker }
1948*d57664e9SAndroid Build Coastguard Worker
ToProto(pb::Badging * out_badging)1949*d57664e9SAndroid Build Coastguard Worker void ToProto(pb::Badging* out_badging) override {
1950*d57664e9SAndroid Build Coastguard Worker if (!name.empty()) {
1951*d57664e9SAndroid Build Coastguard Worker auto metadata = out_badging->add_metadata();
1952*d57664e9SAndroid Build Coastguard Worker metadata->set_name(name);
1953*d57664e9SAndroid Build Coastguard Worker if (!value.empty()) {
1954*d57664e9SAndroid Build Coastguard Worker metadata->set_value_string(value);
1955*d57664e9SAndroid Build Coastguard Worker } else if (value_int) {
1956*d57664e9SAndroid Build Coastguard Worker metadata->set_value_int(*value_int);
1957*d57664e9SAndroid Build Coastguard Worker } else {
1958*d57664e9SAndroid Build Coastguard Worker if (!resource.empty()) {
1959*d57664e9SAndroid Build Coastguard Worker metadata->set_resource_string(resource);
1960*d57664e9SAndroid Build Coastguard Worker } else if (resource_int) {
1961*d57664e9SAndroid Build Coastguard Worker metadata->set_resource_int(*resource_int);
1962*d57664e9SAndroid Build Coastguard Worker }
1963*d57664e9SAndroid Build Coastguard Worker }
1964*d57664e9SAndroid Build Coastguard Worker }
1965*d57664e9SAndroid Build Coastguard Worker }
1966*d57664e9SAndroid Build Coastguard Worker };
1967*d57664e9SAndroid Build Coastguard Worker
1968*d57664e9SAndroid Build Coastguard Worker /**
1969*d57664e9SAndroid Build Coastguard Worker * Represents <action> elements. Detects the presence of certain activity, provider, receiver, and
1970*d57664e9SAndroid Build Coastguard Worker * service components.
1971*d57664e9SAndroid Build Coastguard Worker **/
1972*d57664e9SAndroid Build Coastguard Worker class Action : public ManifestExtractor::Element {
1973*d57664e9SAndroid Build Coastguard Worker public:
1974*d57664e9SAndroid Build Coastguard Worker Action() = default;
1975*d57664e9SAndroid Build Coastguard Worker std::string component = "";
1976*d57664e9SAndroid Build Coastguard Worker
Extract(xml::Element * element)1977*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* element) override {
1978*d57664e9SAndroid Build Coastguard Worker auto parent_stack = extractor()->parent_stack();
1979*d57664e9SAndroid Build Coastguard Worker std::string action = GetAttributeStringDefault(FindAttribute(element, NAME_ATTR), "");
1980*d57664e9SAndroid Build Coastguard Worker
1981*d57664e9SAndroid Build Coastguard Worker if (ElementCast<IntentFilter>(parent_stack[0])) {
1982*d57664e9SAndroid Build Coastguard Worker if (ElementCast<Activity>(parent_stack[1])) {
1983*d57664e9SAndroid Build Coastguard Worker // Detects the presence of a particular type of activity.
1984*d57664e9SAndroid Build Coastguard Worker Activity* activity = ElementCast<Activity>(parent_stack[1]);
1985*d57664e9SAndroid Build Coastguard Worker static const auto map = std::map<std::string, std::string>({
1986*d57664e9SAndroid Build Coastguard Worker {"android.intent.action.MAIN", "main"},
1987*d57664e9SAndroid Build Coastguard Worker {"android.media.action.VIDEO_CAMERA", "camera"},
1988*d57664e9SAndroid Build Coastguard Worker {"android.media.action.STILL_IMAGE_CAMERA", "camera"},
1989*d57664e9SAndroid Build Coastguard Worker {"android.media.action.STILL_IMAGE_CAMERA_SECURE", "camera-secure"},
1990*d57664e9SAndroid Build Coastguard Worker });
1991*d57664e9SAndroid Build Coastguard Worker
1992*d57664e9SAndroid Build Coastguard Worker auto entry = map.find(action);
1993*d57664e9SAndroid Build Coastguard Worker if (entry != map.end()) {
1994*d57664e9SAndroid Build Coastguard Worker component = entry->second;
1995*d57664e9SAndroid Build Coastguard Worker activity->has_component_ = true;
1996*d57664e9SAndroid Build Coastguard Worker }
1997*d57664e9SAndroid Build Coastguard Worker
1998*d57664e9SAndroid Build Coastguard Worker if (action == "android.intent.action.MAIN") {
1999*d57664e9SAndroid Build Coastguard Worker activity->has_main_action = true;
2000*d57664e9SAndroid Build Coastguard Worker }
2001*d57664e9SAndroid Build Coastguard Worker
2002*d57664e9SAndroid Build Coastguard Worker } else if (ElementCast<Receiver>(parent_stack[1])) {
2003*d57664e9SAndroid Build Coastguard Worker // Detects the presence of a particular type of receiver. If the action requires a
2004*d57664e9SAndroid Build Coastguard Worker // permission, then the receiver element is checked for the permission.
2005*d57664e9SAndroid Build Coastguard Worker Receiver* receiver = ElementCast<Receiver>(parent_stack[1]);
2006*d57664e9SAndroid Build Coastguard Worker auto map = std::map<std::string, std::string>({
2007*d57664e9SAndroid Build Coastguard Worker { "android.appwidget.action.APPWIDGET_UPDATE" , "app-widget" },
2008*d57664e9SAndroid Build Coastguard Worker { "android.app.action.DEVICE_ADMIN_ENABLED" , "device-admin" },
2009*d57664e9SAndroid Build Coastguard Worker });
2010*d57664e9SAndroid Build Coastguard Worker
2011*d57664e9SAndroid Build Coastguard Worker auto permissions = std::map<std::string, std::string>({
2012*d57664e9SAndroid Build Coastguard Worker { "android.app.action.DEVICE_ADMIN_ENABLED" , "android.permission.BIND_DEVICE_ADMIN" },
2013*d57664e9SAndroid Build Coastguard Worker });
2014*d57664e9SAndroid Build Coastguard Worker
2015*d57664e9SAndroid Build Coastguard Worker auto entry = map.find(action);
2016*d57664e9SAndroid Build Coastguard Worker auto permission = permissions.find(action);
2017*d57664e9SAndroid Build Coastguard Worker if (entry != map.end() && (permission == permissions.end()
2018*d57664e9SAndroid Build Coastguard Worker || (receiver->permission && permission->second == *receiver->permission))) {
2019*d57664e9SAndroid Build Coastguard Worker receiver->has_component = true;
2020*d57664e9SAndroid Build Coastguard Worker component = entry->second;
2021*d57664e9SAndroid Build Coastguard Worker }
2022*d57664e9SAndroid Build Coastguard Worker
2023*d57664e9SAndroid Build Coastguard Worker } else if (ElementCast<Service>(parent_stack[1])) {
2024*d57664e9SAndroid Build Coastguard Worker // Detects the presence of a particular type of service. If the action requires a
2025*d57664e9SAndroid Build Coastguard Worker // permission, then the service element is checked for the permission.
2026*d57664e9SAndroid Build Coastguard Worker Service* service = ElementCast<Service>(parent_stack[1]);
2027*d57664e9SAndroid Build Coastguard Worker auto map = std::map<std::string, std::string>({
2028*d57664e9SAndroid Build Coastguard Worker { "android.view.InputMethod" , "ime" },
2029*d57664e9SAndroid Build Coastguard Worker { "android.service.wallpaper.WallpaperService" , "wallpaper" },
2030*d57664e9SAndroid Build Coastguard Worker { "android.accessibilityservice.AccessibilityService" , "accessibility" },
2031*d57664e9SAndroid Build Coastguard Worker { "android.printservice.PrintService" , "print-service" },
2032*d57664e9SAndroid Build Coastguard Worker { "android.nfc.cardemulation.action.HOST_APDU_SERVICE" , "host-apdu" },
2033*d57664e9SAndroid Build Coastguard Worker { "android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE" , "offhost-apdu" },
2034*d57664e9SAndroid Build Coastguard Worker { "android.service.notification.NotificationListenerService" ,"notification-listener" },
2035*d57664e9SAndroid Build Coastguard Worker { "android.service.dreams.DreamService" , "dream" },
2036*d57664e9SAndroid Build Coastguard Worker });
2037*d57664e9SAndroid Build Coastguard Worker
2038*d57664e9SAndroid Build Coastguard Worker auto permissions = std::map<std::string, std::string>({
2039*d57664e9SAndroid Build Coastguard Worker { "android.accessibilityservice.AccessibilityService" ,
2040*d57664e9SAndroid Build Coastguard Worker "android.permission.BIND_ACCESSIBILITY_SERVICE" },
2041*d57664e9SAndroid Build Coastguard Worker { "android.printservice.PrintService" , "android.permission.BIND_PRINT_SERVICE" },
2042*d57664e9SAndroid Build Coastguard Worker { "android.nfc.cardemulation.action.HOST_APDU_SERVICE" ,
2043*d57664e9SAndroid Build Coastguard Worker "android.permission.BIND_NFC_SERVICE" },
2044*d57664e9SAndroid Build Coastguard Worker { "android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE" ,
2045*d57664e9SAndroid Build Coastguard Worker "android.permission.BIND_NFC_SERVICE" },
2046*d57664e9SAndroid Build Coastguard Worker { "android.service.notification.NotificationListenerService" ,
2047*d57664e9SAndroid Build Coastguard Worker "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" },
2048*d57664e9SAndroid Build Coastguard Worker { "android.service.dreams.DreamService" , "android.permission.BIND_DREAM_SERVICE" },
2049*d57664e9SAndroid Build Coastguard Worker });
2050*d57664e9SAndroid Build Coastguard Worker
2051*d57664e9SAndroid Build Coastguard Worker auto entry = map.find(action);
2052*d57664e9SAndroid Build Coastguard Worker auto permission = permissions.find(action);
2053*d57664e9SAndroid Build Coastguard Worker if (entry != map.end() && (permission == permissions.end()
2054*d57664e9SAndroid Build Coastguard Worker || (service->permission && permission->second == *service->permission))) {
2055*d57664e9SAndroid Build Coastguard Worker service->has_component= true;
2056*d57664e9SAndroid Build Coastguard Worker component = entry->second;
2057*d57664e9SAndroid Build Coastguard Worker }
2058*d57664e9SAndroid Build Coastguard Worker
2059*d57664e9SAndroid Build Coastguard Worker } else if (ElementCast<Provider>(parent_stack[1])) {
2060*d57664e9SAndroid Build Coastguard Worker // Detects the presence of a particular type of receiver. If the provider requires a
2061*d57664e9SAndroid Build Coastguard Worker // permission, then the provider element is checked for the permission.
2062*d57664e9SAndroid Build Coastguard Worker // Detect whether this action
2063*d57664e9SAndroid Build Coastguard Worker Provider* provider = ElementCast<Provider>(parent_stack[1]);
2064*d57664e9SAndroid Build Coastguard Worker if (action == "android.content.action.DOCUMENTS_PROVIDER"
2065*d57664e9SAndroid Build Coastguard Worker && provider->has_required_saf_attributes) {
2066*d57664e9SAndroid Build Coastguard Worker component = "document-provider";
2067*d57664e9SAndroid Build Coastguard Worker }
2068*d57664e9SAndroid Build Coastguard Worker }
2069*d57664e9SAndroid Build Coastguard Worker }
2070*d57664e9SAndroid Build Coastguard Worker
2071*d57664e9SAndroid Build Coastguard Worker // Represents a searchable interface
2072*d57664e9SAndroid Build Coastguard Worker if (action == "android.intent.action.SEARCH") {
2073*d57664e9SAndroid Build Coastguard Worker component = "search";
2074*d57664e9SAndroid Build Coastguard Worker }
2075*d57664e9SAndroid Build Coastguard Worker }
2076*d57664e9SAndroid Build Coastguard Worker };
2077*d57664e9SAndroid Build Coastguard Worker
2078*d57664e9SAndroid Build Coastguard Worker /**
2079*d57664e9SAndroid Build Coastguard Worker * Represents <supports-input> elements. The element may have <input-type> elements nested within.
2080*d57664e9SAndroid Build Coastguard Worker **/
2081*d57664e9SAndroid Build Coastguard Worker class SupportsInput : public ManifestExtractor::Element {
2082*d57664e9SAndroid Build Coastguard Worker public:
2083*d57664e9SAndroid Build Coastguard Worker SupportsInput() = default;
2084*d57664e9SAndroid Build Coastguard Worker std::vector<std::string> inputs;
2085*d57664e9SAndroid Build Coastguard Worker
Print(text::Printer * printer)2086*d57664e9SAndroid Build Coastguard Worker void Print(text::Printer* printer) override {
2087*d57664e9SAndroid Build Coastguard Worker const size_t size = inputs.size();
2088*d57664e9SAndroid Build Coastguard Worker if (size > 0) {
2089*d57664e9SAndroid Build Coastguard Worker printer->Print("supports-input: '");
2090*d57664e9SAndroid Build Coastguard Worker for (size_t i = 0; i < size; i++) {
2091*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("value='%s' ", inputs[i].data()));
2092*d57664e9SAndroid Build Coastguard Worker }
2093*d57664e9SAndroid Build Coastguard Worker printer->Print("\n");
2094*d57664e9SAndroid Build Coastguard Worker }
2095*d57664e9SAndroid Build Coastguard Worker }
2096*d57664e9SAndroid Build Coastguard Worker
ToProto(pb::Badging * out_badging)2097*d57664e9SAndroid Build Coastguard Worker void ToProto(pb::Badging* out_badging) override {
2098*d57664e9SAndroid Build Coastguard Worker auto supports_input = out_badging->mutable_supports_input();
2099*d57664e9SAndroid Build Coastguard Worker for (auto& input : inputs) {
2100*d57664e9SAndroid Build Coastguard Worker supports_input->add_inputs(input);
2101*d57664e9SAndroid Build Coastguard Worker }
2102*d57664e9SAndroid Build Coastguard Worker }
2103*d57664e9SAndroid Build Coastguard Worker };
2104*d57664e9SAndroid Build Coastguard Worker
2105*d57664e9SAndroid Build Coastguard Worker /** Represents <input-type> elements. **/
2106*d57664e9SAndroid Build Coastguard Worker class InputType : public ManifestExtractor::Element {
2107*d57664e9SAndroid Build Coastguard Worker public:
2108*d57664e9SAndroid Build Coastguard Worker InputType() = default;
Extract(xml::Element * element)2109*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* element) override {
2110*d57664e9SAndroid Build Coastguard Worker auto name = GetAttributeString(FindAttribute(element, NAME_ATTR));
2111*d57664e9SAndroid Build Coastguard Worker auto parent_stack = extractor()->parent_stack();
2112*d57664e9SAndroid Build Coastguard Worker
2113*d57664e9SAndroid Build Coastguard Worker // Add the input to the set of supported inputs
2114*d57664e9SAndroid Build Coastguard Worker if (name && ElementCast<SupportsInput>(parent_stack[0])) {
2115*d57664e9SAndroid Build Coastguard Worker SupportsInput* supports = ElementCast<SupportsInput>(parent_stack[0]);
2116*d57664e9SAndroid Build Coastguard Worker supports->inputs.push_back(*name);
2117*d57664e9SAndroid Build Coastguard Worker }
2118*d57664e9SAndroid Build Coastguard Worker }
2119*d57664e9SAndroid Build Coastguard Worker };
2120*d57664e9SAndroid Build Coastguard Worker
2121*d57664e9SAndroid Build Coastguard Worker /** Represents <install-constraints> elements. **/
2122*d57664e9SAndroid Build Coastguard Worker class InstallConstraints : public ManifestExtractor::Element {
2123*d57664e9SAndroid Build Coastguard Worker public:
2124*d57664e9SAndroid Build Coastguard Worker InstallConstraints() = default;
2125*d57664e9SAndroid Build Coastguard Worker std::vector<std::string> fingerprint_prefixes;
2126*d57664e9SAndroid Build Coastguard Worker
Extract(xml::Element * element)2127*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* element) override {
2128*d57664e9SAndroid Build Coastguard Worker for (xml::Element* child : element->GetChildElements()) {
2129*d57664e9SAndroid Build Coastguard Worker if (child->name == "fingerprint-prefix") {
2130*d57664e9SAndroid Build Coastguard Worker xml::Attribute* attr = child->FindAttribute(kAndroidNamespace, "value");
2131*d57664e9SAndroid Build Coastguard Worker if (attr) {
2132*d57664e9SAndroid Build Coastguard Worker fingerprint_prefixes.push_back(attr->value);
2133*d57664e9SAndroid Build Coastguard Worker }
2134*d57664e9SAndroid Build Coastguard Worker }
2135*d57664e9SAndroid Build Coastguard Worker }
2136*d57664e9SAndroid Build Coastguard Worker }
2137*d57664e9SAndroid Build Coastguard Worker
Print(text::Printer * printer)2138*d57664e9SAndroid Build Coastguard Worker void Print(text::Printer* printer) override {
2139*d57664e9SAndroid Build Coastguard Worker if (!fingerprint_prefixes.empty()) {
2140*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("install-constraints:\n"));
2141*d57664e9SAndroid Build Coastguard Worker for (const auto& prefix : fingerprint_prefixes) {
2142*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" fingerprint-prefix='%s'\n", prefix.c_str()));
2143*d57664e9SAndroid Build Coastguard Worker }
2144*d57664e9SAndroid Build Coastguard Worker }
2145*d57664e9SAndroid Build Coastguard Worker }
2146*d57664e9SAndroid Build Coastguard Worker };
2147*d57664e9SAndroid Build Coastguard Worker
2148*d57664e9SAndroid Build Coastguard Worker /** Represents <original-package> elements. **/
2149*d57664e9SAndroid Build Coastguard Worker class OriginalPackage : public ManifestExtractor::Element {
2150*d57664e9SAndroid Build Coastguard Worker public:
2151*d57664e9SAndroid Build Coastguard Worker OriginalPackage() = default;
2152*d57664e9SAndroid Build Coastguard Worker const std::string* name = nullptr;
2153*d57664e9SAndroid Build Coastguard Worker
Extract(xml::Element * element)2154*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* element) override {
2155*d57664e9SAndroid Build Coastguard Worker name = GetAttributeString(FindAttribute(element, NAME_ATTR));
2156*d57664e9SAndroid Build Coastguard Worker }
2157*d57664e9SAndroid Build Coastguard Worker
Print(text::Printer * printer)2158*d57664e9SAndroid Build Coastguard Worker void Print(text::Printer* printer) override {
2159*d57664e9SAndroid Build Coastguard Worker if (name) {
2160*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("original-package:'%s'\n", name->data()));
2161*d57664e9SAndroid Build Coastguard Worker }
2162*d57664e9SAndroid Build Coastguard Worker }
2163*d57664e9SAndroid Build Coastguard Worker
ToProto(pb::Badging * out_badging)2164*d57664e9SAndroid Build Coastguard Worker void ToProto(pb::Badging* out_badging) override {
2165*d57664e9SAndroid Build Coastguard Worker if (name) {
2166*d57664e9SAndroid Build Coastguard Worker out_badging->mutable_package()->set_original_package(*name);
2167*d57664e9SAndroid Build Coastguard Worker }
2168*d57664e9SAndroid Build Coastguard Worker }
2169*d57664e9SAndroid Build Coastguard Worker };
2170*d57664e9SAndroid Build Coastguard Worker
2171*d57664e9SAndroid Build Coastguard Worker
2172*d57664e9SAndroid Build Coastguard Worker /** Represents <overlay> elements. **/
2173*d57664e9SAndroid Build Coastguard Worker class Overlay : public ManifestExtractor::Element {
2174*d57664e9SAndroid Build Coastguard Worker public:
2175*d57664e9SAndroid Build Coastguard Worker Overlay() = default;
2176*d57664e9SAndroid Build Coastguard Worker const std::string* target_package = nullptr;
2177*d57664e9SAndroid Build Coastguard Worker int priority;
2178*d57664e9SAndroid Build Coastguard Worker bool is_static;
2179*d57664e9SAndroid Build Coastguard Worker const std::string* required_property_name = nullptr;
2180*d57664e9SAndroid Build Coastguard Worker const std::string* required_property_value = nullptr;
2181*d57664e9SAndroid Build Coastguard Worker
Extract(xml::Element * element)2182*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* element) override {
2183*d57664e9SAndroid Build Coastguard Worker target_package = GetAttributeString(FindAttribute(element, TARGET_PACKAGE_ATTR));
2184*d57664e9SAndroid Build Coastguard Worker priority = GetAttributeIntegerDefault(FindAttribute(element, PRIORITY_ATTR), 0);
2185*d57664e9SAndroid Build Coastguard Worker is_static = GetAttributeIntegerDefault(FindAttribute(element, IS_STATIC_ATTR), false) != 0;
2186*d57664e9SAndroid Build Coastguard Worker required_property_name = GetAttributeString(
2187*d57664e9SAndroid Build Coastguard Worker FindAttribute(element, REQUIRED_SYSTEM_PROPERTY_NAME_ATTR));
2188*d57664e9SAndroid Build Coastguard Worker required_property_value = GetAttributeString(
2189*d57664e9SAndroid Build Coastguard Worker FindAttribute(element, REQUIRED_SYSTEM_PROPERTY_VALUE_ATTR));
2190*d57664e9SAndroid Build Coastguard Worker }
2191*d57664e9SAndroid Build Coastguard Worker
Print(text::Printer * printer)2192*d57664e9SAndroid Build Coastguard Worker void Print(text::Printer* printer) override {
2193*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("overlay:"));
2194*d57664e9SAndroid Build Coastguard Worker if (target_package) {
2195*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" targetPackage='%s'", target_package->c_str()));
2196*d57664e9SAndroid Build Coastguard Worker }
2197*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" priority='%d'", priority));
2198*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" isStatic='%s'", is_static ? "true" : "false"));
2199*d57664e9SAndroid Build Coastguard Worker if (required_property_name) {
2200*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" requiredPropertyName='%s'", required_property_name->c_str()));
2201*d57664e9SAndroid Build Coastguard Worker }
2202*d57664e9SAndroid Build Coastguard Worker if (required_property_value) {
2203*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" requiredPropertyValue='%s'", required_property_value->c_str()));
2204*d57664e9SAndroid Build Coastguard Worker }
2205*d57664e9SAndroid Build Coastguard Worker printer->Print("\n");
2206*d57664e9SAndroid Build Coastguard Worker }
2207*d57664e9SAndroid Build Coastguard Worker
ToProto(pb::Badging * out_badging)2208*d57664e9SAndroid Build Coastguard Worker void ToProto(pb::Badging* out_badging) override {
2209*d57664e9SAndroid Build Coastguard Worker auto overlay = out_badging->mutable_overlay();
2210*d57664e9SAndroid Build Coastguard Worker if (target_package) {
2211*d57664e9SAndroid Build Coastguard Worker overlay->set_target_package(*target_package);
2212*d57664e9SAndroid Build Coastguard Worker }
2213*d57664e9SAndroid Build Coastguard Worker overlay->set_priority(priority);
2214*d57664e9SAndroid Build Coastguard Worker overlay->set_static_(is_static);
2215*d57664e9SAndroid Build Coastguard Worker if (required_property_name) {
2216*d57664e9SAndroid Build Coastguard Worker overlay->set_required_property_name(*required_property_name);
2217*d57664e9SAndroid Build Coastguard Worker }
2218*d57664e9SAndroid Build Coastguard Worker if (required_property_value) {
2219*d57664e9SAndroid Build Coastguard Worker overlay->set_required_property_value(*required_property_value);
2220*d57664e9SAndroid Build Coastguard Worker }
2221*d57664e9SAndroid Build Coastguard Worker }
2222*d57664e9SAndroid Build Coastguard Worker };
2223*d57664e9SAndroid Build Coastguard Worker
2224*d57664e9SAndroid Build Coastguard Worker /** * Represents <package-verifier> elements. **/
2225*d57664e9SAndroid Build Coastguard Worker class PackageVerifier : public ManifestExtractor::Element {
2226*d57664e9SAndroid Build Coastguard Worker public:
2227*d57664e9SAndroid Build Coastguard Worker PackageVerifier() = default;
2228*d57664e9SAndroid Build Coastguard Worker const std::string* name = nullptr;
2229*d57664e9SAndroid Build Coastguard Worker const std::string* public_key = nullptr;
2230*d57664e9SAndroid Build Coastguard Worker
Extract(xml::Element * element)2231*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* element) override {
2232*d57664e9SAndroid Build Coastguard Worker name = GetAttributeString(FindAttribute(element, NAME_ATTR));
2233*d57664e9SAndroid Build Coastguard Worker public_key = GetAttributeString(FindAttribute(element, PUBLIC_KEY_ATTR));
2234*d57664e9SAndroid Build Coastguard Worker }
2235*d57664e9SAndroid Build Coastguard Worker
Print(text::Printer * printer)2236*d57664e9SAndroid Build Coastguard Worker void Print(text::Printer* printer) override {
2237*d57664e9SAndroid Build Coastguard Worker if (name && public_key) {
2238*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("package-verifier: name='%s' publicKey='%s'\n",
2239*d57664e9SAndroid Build Coastguard Worker name->data(), public_key->data()));
2240*d57664e9SAndroid Build Coastguard Worker }
2241*d57664e9SAndroid Build Coastguard Worker }
2242*d57664e9SAndroid Build Coastguard Worker
ToProto(pb::Badging * out_badging)2243*d57664e9SAndroid Build Coastguard Worker void ToProto(pb::Badging* out_badging) override {
2244*d57664e9SAndroid Build Coastguard Worker auto package_verifier = out_badging->mutable_package_verifier();
2245*d57664e9SAndroid Build Coastguard Worker if (name && public_key) {
2246*d57664e9SAndroid Build Coastguard Worker package_verifier->set_name(*name);
2247*d57664e9SAndroid Build Coastguard Worker package_verifier->set_public_key(*public_key);
2248*d57664e9SAndroid Build Coastguard Worker }
2249*d57664e9SAndroid Build Coastguard Worker }
2250*d57664e9SAndroid Build Coastguard Worker };
2251*d57664e9SAndroid Build Coastguard Worker
2252*d57664e9SAndroid Build Coastguard Worker /** Represents <uses-package> elements. **/
2253*d57664e9SAndroid Build Coastguard Worker class UsesPackage : public ManifestExtractor::Element {
2254*d57664e9SAndroid Build Coastguard Worker public:
2255*d57664e9SAndroid Build Coastguard Worker UsesPackage() = default;
2256*d57664e9SAndroid Build Coastguard Worker const std::string* packageType = nullptr;
2257*d57664e9SAndroid Build Coastguard Worker const std::string* name = nullptr;
2258*d57664e9SAndroid Build Coastguard Worker int version;
2259*d57664e9SAndroid Build Coastguard Worker int versionMajor;
2260*d57664e9SAndroid Build Coastguard Worker std::vector<std::string> certDigests;
2261*d57664e9SAndroid Build Coastguard Worker
Extract(xml::Element * element)2262*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* element) override {
2263*d57664e9SAndroid Build Coastguard Worker packageType = GetAttributeString(FindAttribute(element, PACKAGE_TYPE_ATTR));
2264*d57664e9SAndroid Build Coastguard Worker name = GetAttributeString(FindAttribute(element, NAME_ATTR));
2265*d57664e9SAndroid Build Coastguard Worker version = GetAttributeIntegerDefault(FindAttribute(element, VERSION_ATTR), 0);
2266*d57664e9SAndroid Build Coastguard Worker versionMajor = GetAttributeIntegerDefault(FindAttribute(element, VERSION_MAJOR_ATTR), 0);
2267*d57664e9SAndroid Build Coastguard Worker AddCertDigest(element);
2268*d57664e9SAndroid Build Coastguard Worker }
2269*d57664e9SAndroid Build Coastguard Worker
AddCertDigest(xml::Element * element)2270*d57664e9SAndroid Build Coastguard Worker void AddCertDigest(xml::Element* element) {
2271*d57664e9SAndroid Build Coastguard Worker std::string digest = GetAttributeStringDefault(FindAttribute(element, CERT_DIGEST_ATTR), "");
2272*d57664e9SAndroid Build Coastguard Worker // We allow ":" delimiters in the SHA declaration as this is the format
2273*d57664e9SAndroid Build Coastguard Worker // emitted by the certtool making it easy for developers to copy/paste.
2274*d57664e9SAndroid Build Coastguard Worker digest.erase(std::remove(digest.begin(), digest.end(), ':'), digest.end());
2275*d57664e9SAndroid Build Coastguard Worker if (!digest.empty()) {
2276*d57664e9SAndroid Build Coastguard Worker certDigests.push_back(digest);
2277*d57664e9SAndroid Build Coastguard Worker }
2278*d57664e9SAndroid Build Coastguard Worker }
2279*d57664e9SAndroid Build Coastguard Worker
Print(text::Printer * printer)2280*d57664e9SAndroid Build Coastguard Worker void Print(text::Printer* printer) override {
2281*d57664e9SAndroid Build Coastguard Worker if (name) {
2282*d57664e9SAndroid Build Coastguard Worker if (packageType) {
2283*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(
2284*d57664e9SAndroid Build Coastguard Worker "uses-typed-package: type='%s' name='%s' version='%d' versionMajor='%d'",
2285*d57664e9SAndroid Build Coastguard Worker packageType->data(), name->data(), version, versionMajor));
2286*d57664e9SAndroid Build Coastguard Worker for (size_t i = 0; i < certDigests.size(); i++) {
2287*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" certDigest='%s'", certDigests[i].data()));
2288*d57664e9SAndroid Build Coastguard Worker }
2289*d57664e9SAndroid Build Coastguard Worker printer->Print("\n");
2290*d57664e9SAndroid Build Coastguard Worker } else {
2291*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("uses-package:'%s'\n", name->data()));
2292*d57664e9SAndroid Build Coastguard Worker }
2293*d57664e9SAndroid Build Coastguard Worker }
2294*d57664e9SAndroid Build Coastguard Worker }
2295*d57664e9SAndroid Build Coastguard Worker
ToProto(pb::Badging * out_badging)2296*d57664e9SAndroid Build Coastguard Worker void ToProto(pb::Badging* out_badging) override {
2297*d57664e9SAndroid Build Coastguard Worker if (name) {
2298*d57664e9SAndroid Build Coastguard Worker auto uses_package = out_badging->add_uses_packages();
2299*d57664e9SAndroid Build Coastguard Worker uses_package->set_name(*name);
2300*d57664e9SAndroid Build Coastguard Worker if (packageType) {
2301*d57664e9SAndroid Build Coastguard Worker uses_package->set_package_type(*packageType);
2302*d57664e9SAndroid Build Coastguard Worker uses_package->set_version(version);
2303*d57664e9SAndroid Build Coastguard Worker uses_package->set_version_major(versionMajor);
2304*d57664e9SAndroid Build Coastguard Worker for (auto& cert : certDigests) {
2305*d57664e9SAndroid Build Coastguard Worker uses_package->add_certificates(cert);
2306*d57664e9SAndroid Build Coastguard Worker }
2307*d57664e9SAndroid Build Coastguard Worker }
2308*d57664e9SAndroid Build Coastguard Worker }
2309*d57664e9SAndroid Build Coastguard Worker }
2310*d57664e9SAndroid Build Coastguard Worker };
2311*d57664e9SAndroid Build Coastguard Worker
2312*d57664e9SAndroid Build Coastguard Worker /** Represents <additional-certificate> elements. **/
2313*d57664e9SAndroid Build Coastguard Worker class AdditionalCertificate : public ManifestExtractor::Element {
2314*d57664e9SAndroid Build Coastguard Worker public:
2315*d57664e9SAndroid Build Coastguard Worker AdditionalCertificate() = default;
2316*d57664e9SAndroid Build Coastguard Worker
Extract(xml::Element * element)2317*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* element) override {
2318*d57664e9SAndroid Build Coastguard Worker auto parent_stack = extractor()->parent_stack();
2319*d57664e9SAndroid Build Coastguard Worker if (parent_stack.size() > 0) {
2320*d57664e9SAndroid Build Coastguard Worker if (ElementCast<UsesPackage>(parent_stack[0])) {
2321*d57664e9SAndroid Build Coastguard Worker UsesPackage* uses = ElementCast<UsesPackage>(parent_stack[0]);
2322*d57664e9SAndroid Build Coastguard Worker uses->AddCertDigest(element);
2323*d57664e9SAndroid Build Coastguard Worker } else if (ElementCast<UsesStaticLibrary>(parent_stack[0])) {
2324*d57664e9SAndroid Build Coastguard Worker UsesStaticLibrary* uses = ElementCast<UsesStaticLibrary>(parent_stack[0]);
2325*d57664e9SAndroid Build Coastguard Worker uses->AddCertDigest(element);
2326*d57664e9SAndroid Build Coastguard Worker }
2327*d57664e9SAndroid Build Coastguard Worker }
2328*d57664e9SAndroid Build Coastguard Worker }
2329*d57664e9SAndroid Build Coastguard Worker };
2330*d57664e9SAndroid Build Coastguard Worker
2331*d57664e9SAndroid Build Coastguard Worker /** Represents <screen> elements found in <compatible-screens> elements. */
2332*d57664e9SAndroid Build Coastguard Worker class Screen : public ManifestExtractor::Element {
2333*d57664e9SAndroid Build Coastguard Worker public:
2334*d57664e9SAndroid Build Coastguard Worker Screen() = default;
2335*d57664e9SAndroid Build Coastguard Worker const int32_t* size = nullptr;
2336*d57664e9SAndroid Build Coastguard Worker const int32_t* density = nullptr;
2337*d57664e9SAndroid Build Coastguard Worker
Extract(xml::Element * element)2338*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* element) override {
2339*d57664e9SAndroid Build Coastguard Worker size = GetAttributeInteger(FindAttribute(element, SCREEN_SIZE_ATTR));
2340*d57664e9SAndroid Build Coastguard Worker density = GetAttributeInteger(FindAttribute(element, SCREEN_DENSITY_ATTR));
2341*d57664e9SAndroid Build Coastguard Worker }
2342*d57664e9SAndroid Build Coastguard Worker
ToProto(pb::Badging * out_badging)2343*d57664e9SAndroid Build Coastguard Worker void ToProto(pb::Badging* out_badging) override {
2344*d57664e9SAndroid Build Coastguard Worker if (size && density) {
2345*d57664e9SAndroid Build Coastguard Worker auto screen = out_badging->mutable_compatible_screens()->add_screens();
2346*d57664e9SAndroid Build Coastguard Worker screen->set_density(*density);
2347*d57664e9SAndroid Build Coastguard Worker screen->set_size(*size);
2348*d57664e9SAndroid Build Coastguard Worker }
2349*d57664e9SAndroid Build Coastguard Worker }
2350*d57664e9SAndroid Build Coastguard Worker };
2351*d57664e9SAndroid Build Coastguard Worker
2352*d57664e9SAndroid Build Coastguard Worker /**
2353*d57664e9SAndroid Build Coastguard Worker * Represents <compatible-screens> elements. These elements have <screen> elements nested within
2354*d57664e9SAndroid Build Coastguard Worker * that each denote a supported screen size and screen density.
2355*d57664e9SAndroid Build Coastguard Worker **/
2356*d57664e9SAndroid Build Coastguard Worker class CompatibleScreens : public ManifestExtractor::Element {
2357*d57664e9SAndroid Build Coastguard Worker public:
2358*d57664e9SAndroid Build Coastguard Worker CompatibleScreens() = default;
Print(text::Printer * printer)2359*d57664e9SAndroid Build Coastguard Worker void Print(text::Printer* printer) override {
2360*d57664e9SAndroid Build Coastguard Worker printer->Print("compatible-screens:");
2361*d57664e9SAndroid Build Coastguard Worker
2362*d57664e9SAndroid Build Coastguard Worker bool first = true;
2363*d57664e9SAndroid Build Coastguard Worker ForEachChild(this, [&printer, &first](ManifestExtractor::Element* el){
2364*d57664e9SAndroid Build Coastguard Worker if (auto screen = ElementCast<Screen>(el)) {
2365*d57664e9SAndroid Build Coastguard Worker if (first) {
2366*d57664e9SAndroid Build Coastguard Worker first = false;
2367*d57664e9SAndroid Build Coastguard Worker } else {
2368*d57664e9SAndroid Build Coastguard Worker printer->Print(",");
2369*d57664e9SAndroid Build Coastguard Worker }
2370*d57664e9SAndroid Build Coastguard Worker
2371*d57664e9SAndroid Build Coastguard Worker if (screen->size && screen->density) {
2372*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("'%d/%d'", *screen->size, *screen->density));
2373*d57664e9SAndroid Build Coastguard Worker }
2374*d57664e9SAndroid Build Coastguard Worker }
2375*d57664e9SAndroid Build Coastguard Worker });
2376*d57664e9SAndroid Build Coastguard Worker printer->Print("\n");
2377*d57664e9SAndroid Build Coastguard Worker }
2378*d57664e9SAndroid Build Coastguard Worker };
2379*d57664e9SAndroid Build Coastguard Worker
2380*d57664e9SAndroid Build Coastguard Worker /** Represents <supports-gl-texture> elements. **/
2381*d57664e9SAndroid Build Coastguard Worker class SupportsGlTexture : public ManifestExtractor::Element {
2382*d57664e9SAndroid Build Coastguard Worker public:
2383*d57664e9SAndroid Build Coastguard Worker SupportsGlTexture() = default;
2384*d57664e9SAndroid Build Coastguard Worker const std::string* name = nullptr;
2385*d57664e9SAndroid Build Coastguard Worker
Extract(xml::Element * element)2386*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* element) override {
2387*d57664e9SAndroid Build Coastguard Worker name = GetAttributeString(FindAttribute(element, NAME_ATTR));
2388*d57664e9SAndroid Build Coastguard Worker }
2389*d57664e9SAndroid Build Coastguard Worker
Print(text::Printer * printer)2390*d57664e9SAndroid Build Coastguard Worker void Print(text::Printer* printer) override {
2391*d57664e9SAndroid Build Coastguard Worker if (name) {
2392*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("supports-gl-texture:'%s'\n", name->data()));
2393*d57664e9SAndroid Build Coastguard Worker }
2394*d57664e9SAndroid Build Coastguard Worker }
2395*d57664e9SAndroid Build Coastguard Worker
ToProto(pb::Badging * out_badging)2396*d57664e9SAndroid Build Coastguard Worker void ToProto(pb::Badging* out_badging) override {
2397*d57664e9SAndroid Build Coastguard Worker if (name) {
2398*d57664e9SAndroid Build Coastguard Worker out_badging->mutable_supports_gl_texture()->add_name(*name);
2399*d57664e9SAndroid Build Coastguard Worker }
2400*d57664e9SAndroid Build Coastguard Worker }
2401*d57664e9SAndroid Build Coastguard Worker };
2402*d57664e9SAndroid Build Coastguard Worker
2403*d57664e9SAndroid Build Coastguard Worker /** Represents <property> elements. **/
2404*d57664e9SAndroid Build Coastguard Worker class Property : public ManifestExtractor::Element {
2405*d57664e9SAndroid Build Coastguard Worker public:
2406*d57664e9SAndroid Build Coastguard Worker Property() = default;
2407*d57664e9SAndroid Build Coastguard Worker std::string name;
2408*d57664e9SAndroid Build Coastguard Worker std::string value;
2409*d57664e9SAndroid Build Coastguard Worker const int* value_int;
2410*d57664e9SAndroid Build Coastguard Worker std::string resource;
2411*d57664e9SAndroid Build Coastguard Worker const int* resource_int;
2412*d57664e9SAndroid Build Coastguard Worker
Extract(xml::Element * element)2413*d57664e9SAndroid Build Coastguard Worker void Extract(xml::Element* element) override {
2414*d57664e9SAndroid Build Coastguard Worker name = GetAttributeStringDefault(FindAttribute(element, NAME_ATTR), "");
2415*d57664e9SAndroid Build Coastguard Worker value = GetAttributeStringDefault(FindAttribute(element, VALUE_ATTR), "");
2416*d57664e9SAndroid Build Coastguard Worker value_int = GetAttributeInteger(FindAttribute(element, VALUE_ATTR));
2417*d57664e9SAndroid Build Coastguard Worker resource = GetAttributeStringDefault(FindAttribute(element, RESOURCE_ATTR), "");
2418*d57664e9SAndroid Build Coastguard Worker resource_int = GetAttributeInteger(FindAttribute(element, RESOURCE_ATTR));
2419*d57664e9SAndroid Build Coastguard Worker }
2420*d57664e9SAndroid Build Coastguard Worker
Print(text::Printer * printer)2421*d57664e9SAndroid Build Coastguard Worker void Print(text::Printer* printer) override {
2422*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("property: name='%s' ", name.data()));
2423*d57664e9SAndroid Build Coastguard Worker if (!value.empty()) {
2424*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("value='%s' ", value.data()));
2425*d57664e9SAndroid Build Coastguard Worker } else if (value_int) {
2426*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("value='%d' ", *value_int));
2427*d57664e9SAndroid Build Coastguard Worker } else {
2428*d57664e9SAndroid Build Coastguard Worker if (!resource.empty()) {
2429*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("resource='%s' ", resource.data()));
2430*d57664e9SAndroid Build Coastguard Worker } else if (resource_int) {
2431*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf("resource='%d' ", *resource_int));
2432*d57664e9SAndroid Build Coastguard Worker }
2433*d57664e9SAndroid Build Coastguard Worker }
2434*d57664e9SAndroid Build Coastguard Worker printer->Print("\n");
2435*d57664e9SAndroid Build Coastguard Worker }
2436*d57664e9SAndroid Build Coastguard Worker
ToProto(pb::Badging * out_badging)2437*d57664e9SAndroid Build Coastguard Worker void ToProto(pb::Badging* out_badging) override {
2438*d57664e9SAndroid Build Coastguard Worker if (!name.empty()) {
2439*d57664e9SAndroid Build Coastguard Worker auto property = out_badging->add_properties();
2440*d57664e9SAndroid Build Coastguard Worker property->set_name(name);
2441*d57664e9SAndroid Build Coastguard Worker if (!value.empty()) {
2442*d57664e9SAndroid Build Coastguard Worker property->set_value_string(value);
2443*d57664e9SAndroid Build Coastguard Worker } else if (value_int) {
2444*d57664e9SAndroid Build Coastguard Worker property->set_value_int(*value_int);
2445*d57664e9SAndroid Build Coastguard Worker } else {
2446*d57664e9SAndroid Build Coastguard Worker if (!resource.empty()) {
2447*d57664e9SAndroid Build Coastguard Worker property->set_resource_string(resource);
2448*d57664e9SAndroid Build Coastguard Worker } else if (resource_int) {
2449*d57664e9SAndroid Build Coastguard Worker property->set_resource_int(*resource_int);
2450*d57664e9SAndroid Build Coastguard Worker }
2451*d57664e9SAndroid Build Coastguard Worker }
2452*d57664e9SAndroid Build Coastguard Worker }
2453*d57664e9SAndroid Build Coastguard Worker }
2454*d57664e9SAndroid Build Coastguard Worker };
2455*d57664e9SAndroid Build Coastguard Worker
2456*d57664e9SAndroid Build Coastguard Worker /** Recursively prints the extracted badging element. */
Print(ManifestExtractor::Element * el,text::Printer * printer)2457*d57664e9SAndroid Build Coastguard Worker static void Print(ManifestExtractor::Element* el, text::Printer* printer) {
2458*d57664e9SAndroid Build Coastguard Worker el->Print(printer);
2459*d57664e9SAndroid Build Coastguard Worker for (auto &child : el->children()) {
2460*d57664e9SAndroid Build Coastguard Worker Print(child.get(), printer);
2461*d57664e9SAndroid Build Coastguard Worker }
2462*d57664e9SAndroid Build Coastguard Worker }
2463*d57664e9SAndroid Build Coastguard Worker
2464*d57664e9SAndroid Build Coastguard Worker /** Recursively serializes extracted badging elements to proto. */
ToProto(ManifestExtractor::Element * el,pb::Badging * out_badging)2465*d57664e9SAndroid Build Coastguard Worker static void ToProto(ManifestExtractor::Element* el, pb::Badging* out_badging) {
2466*d57664e9SAndroid Build Coastguard Worker el->ToProto(out_badging);
2467*d57664e9SAndroid Build Coastguard Worker for (auto& child : el->children()) {
2468*d57664e9SAndroid Build Coastguard Worker ToProto(child.get(), out_badging);
2469*d57664e9SAndroid Build Coastguard Worker }
2470*d57664e9SAndroid Build Coastguard Worker }
2471*d57664e9SAndroid Build Coastguard Worker
2472*d57664e9SAndroid Build Coastguard Worker // Define this constructor after the CommonFeatureGroup class definition to avoid errors with using
2473*d57664e9SAndroid Build Coastguard Worker // std::unique_ptr on an incomplete type.
ManifestExtractor(LoadedApk * apk,DumpManifestOptions & options)2474*d57664e9SAndroid Build Coastguard Worker ManifestExtractor::ManifestExtractor(LoadedApk* apk, DumpManifestOptions& options)
2475*d57664e9SAndroid Build Coastguard Worker : apk_(apk), options_(options), commonFeatureGroup_(util::make_unique<CommonFeatureGroup>()) {
2476*d57664e9SAndroid Build Coastguard Worker }
2477*d57664e9SAndroid Build Coastguard Worker
Extract(android::IDiagnostics * diag)2478*d57664e9SAndroid Build Coastguard Worker bool ManifestExtractor::Extract(android::IDiagnostics* diag) {
2479*d57664e9SAndroid Build Coastguard Worker // Load the manifest
2480*d57664e9SAndroid Build Coastguard Worker doc_ = apk_->LoadXml("AndroidManifest.xml", diag);
2481*d57664e9SAndroid Build Coastguard Worker if (doc_ == nullptr) {
2482*d57664e9SAndroid Build Coastguard Worker diag->Error(android::DiagMessage() << "failed to find AndroidManifest.xml");
2483*d57664e9SAndroid Build Coastguard Worker return false;
2484*d57664e9SAndroid Build Coastguard Worker }
2485*d57664e9SAndroid Build Coastguard Worker
2486*d57664e9SAndroid Build Coastguard Worker xml::Element* element = doc_->root.get();
2487*d57664e9SAndroid Build Coastguard Worker if (element->name != "manifest") {
2488*d57664e9SAndroid Build Coastguard Worker diag->Error(android::DiagMessage() << "manifest does not start with <manifest> tag");
2489*d57664e9SAndroid Build Coastguard Worker return false;
2490*d57664e9SAndroid Build Coastguard Worker }
2491*d57664e9SAndroid Build Coastguard Worker
2492*d57664e9SAndroid Build Coastguard Worker // Print only the <uses-permission>, <uses-permission-sdk23>, and <permission> elements if
2493*d57664e9SAndroid Build Coastguard Worker // printing only permission elements is requested
2494*d57664e9SAndroid Build Coastguard Worker if (options_.only_permissions) {
2495*d57664e9SAndroid Build Coastguard Worker root_element_ = ManifestExtractor::Element::Inflate(this, element, "");
2496*d57664e9SAndroid Build Coastguard Worker
2497*d57664e9SAndroid Build Coastguard Worker if (auto manifest = ElementCast<Manifest>(root_element_.get())) {
2498*d57664e9SAndroid Build Coastguard Worker manifest->only_package_name = true;
2499*d57664e9SAndroid Build Coastguard Worker
2500*d57664e9SAndroid Build Coastguard Worker for (xml::Element* child : element->GetChildElements()) {
2501*d57664e9SAndroid Build Coastguard Worker if (child->name == "uses-permission" || child->name == "uses-permission-sdk-23"
2502*d57664e9SAndroid Build Coastguard Worker || child->name == "permission") {
2503*d57664e9SAndroid Build Coastguard Worker // Inflate the element and its descendants
2504*d57664e9SAndroid Build Coastguard Worker auto permission_element = Visit(child, "manifest");
2505*d57664e9SAndroid Build Coastguard Worker manifest->AddChild(permission_element);
2506*d57664e9SAndroid Build Coastguard Worker }
2507*d57664e9SAndroid Build Coastguard Worker }
2508*d57664e9SAndroid Build Coastguard Worker return true;
2509*d57664e9SAndroid Build Coastguard Worker }
2510*d57664e9SAndroid Build Coastguard Worker return false;
2511*d57664e9SAndroid Build Coastguard Worker }
2512*d57664e9SAndroid Build Coastguard Worker
2513*d57664e9SAndroid Build Coastguard Worker // Collect information about the resource configurations
2514*d57664e9SAndroid Build Coastguard Worker if (apk_->GetResourceTable()) {
2515*d57664e9SAndroid Build Coastguard Worker for (auto &package : apk_->GetResourceTable()->packages) {
2516*d57664e9SAndroid Build Coastguard Worker for (auto &type : package->types) {
2517*d57664e9SAndroid Build Coastguard Worker for (auto &entry : type->entries) {
2518*d57664e9SAndroid Build Coastguard Worker for (auto &value : entry->values) {
2519*d57664e9SAndroid Build Coastguard Worker std::string locale_str = value->config.GetBcp47LanguageTag();
2520*d57664e9SAndroid Build Coastguard Worker
2521*d57664e9SAndroid Build Coastguard Worker // Collect all the unique locales of the apk
2522*d57664e9SAndroid Build Coastguard Worker if (locales_.find(locale_str) == locales_.end()) {
2523*d57664e9SAndroid Build Coastguard Worker ConfigDescription config = ManifestExtractor::DefaultConfig();
2524*d57664e9SAndroid Build Coastguard Worker config.setBcp47Locale(locale_str.data());
2525*d57664e9SAndroid Build Coastguard Worker locales_.insert(std::make_pair(locale_str, config));
2526*d57664e9SAndroid Build Coastguard Worker }
2527*d57664e9SAndroid Build Coastguard Worker
2528*d57664e9SAndroid Build Coastguard Worker // Collect all the unique density of the apk
2529*d57664e9SAndroid Build Coastguard Worker uint16_t density = (value->config.density == 0) ? (uint16_t) 160
2530*d57664e9SAndroid Build Coastguard Worker : value->config.density;
2531*d57664e9SAndroid Build Coastguard Worker if (densities_.find(density) == densities_.end()) {
2532*d57664e9SAndroid Build Coastguard Worker ConfigDescription config = ManifestExtractor::DefaultConfig();
2533*d57664e9SAndroid Build Coastguard Worker config.density = density;
2534*d57664e9SAndroid Build Coastguard Worker densities_.insert(std::make_pair(density, config));
2535*d57664e9SAndroid Build Coastguard Worker }
2536*d57664e9SAndroid Build Coastguard Worker }
2537*d57664e9SAndroid Build Coastguard Worker }
2538*d57664e9SAndroid Build Coastguard Worker }
2539*d57664e9SAndroid Build Coastguard Worker }
2540*d57664e9SAndroid Build Coastguard Worker }
2541*d57664e9SAndroid Build Coastguard Worker
2542*d57664e9SAndroid Build Coastguard Worker // Extract badging information
2543*d57664e9SAndroid Build Coastguard Worker root_element_ = Visit(element, "");
2544*d57664e9SAndroid Build Coastguard Worker
2545*d57664e9SAndroid Build Coastguard Worker // Filter out all "uses-sdk" tags besides the very last tag. The android runtime only uses the
2546*d57664e9SAndroid Build Coastguard Worker // attribute values from the last defined tag.
2547*d57664e9SAndroid Build Coastguard Worker std::vector<UsesSdkBadging*> filtered_uses_sdk_tags;
2548*d57664e9SAndroid Build Coastguard Worker for (const auto& child : root_element_->children()) {
2549*d57664e9SAndroid Build Coastguard Worker if (auto uses_sdk = ElementCast<UsesSdkBadging>(child.get())) {
2550*d57664e9SAndroid Build Coastguard Worker filtered_uses_sdk_tags.emplace_back(uses_sdk);
2551*d57664e9SAndroid Build Coastguard Worker }
2552*d57664e9SAndroid Build Coastguard Worker }
2553*d57664e9SAndroid Build Coastguard Worker if (filtered_uses_sdk_tags.size() >= 2U) {
2554*d57664e9SAndroid Build Coastguard Worker filtered_uses_sdk_tags.pop_back();
2555*d57664e9SAndroid Build Coastguard Worker root_element_->Filter([&](const ManifestExtractor::Element* e) {
2556*d57664e9SAndroid Build Coastguard Worker return std::find(filtered_uses_sdk_tags.begin(), filtered_uses_sdk_tags.end(), e) !=
2557*d57664e9SAndroid Build Coastguard Worker filtered_uses_sdk_tags.end();
2558*d57664e9SAndroid Build Coastguard Worker });
2559*d57664e9SAndroid Build Coastguard Worker }
2560*d57664e9SAndroid Build Coastguard Worker
2561*d57664e9SAndroid Build Coastguard Worker /** Recursively checks the extracted elements for the specified permission. **/
2562*d57664e9SAndroid Build Coastguard Worker auto FindPermission = [&](ManifestExtractor::Element* root,
2563*d57664e9SAndroid Build Coastguard Worker const std::string& name) -> ManifestExtractor::Element* {
2564*d57664e9SAndroid Build Coastguard Worker return FindElement(root, [&](ManifestExtractor::Element* el) -> bool {
2565*d57664e9SAndroid Build Coastguard Worker if (UsesPermission* permission = ElementCast<UsesPermission>(el)) {
2566*d57664e9SAndroid Build Coastguard Worker return permission->name == name;
2567*d57664e9SAndroid Build Coastguard Worker }
2568*d57664e9SAndroid Build Coastguard Worker return false;
2569*d57664e9SAndroid Build Coastguard Worker });
2570*d57664e9SAndroid Build Coastguard Worker };
2571*d57664e9SAndroid Build Coastguard Worker
2572*d57664e9SAndroid Build Coastguard Worker auto AddImpliedPermission = [&](const std::string& name, const std::string& reason,
2573*d57664e9SAndroid Build Coastguard Worker int32_t max_sdk_version) -> void {
2574*d57664e9SAndroid Build Coastguard Worker auto permission = util::make_unique<UsesPermission>();
2575*d57664e9SAndroid Build Coastguard Worker permission->name = name;
2576*d57664e9SAndroid Build Coastguard Worker permission->maxSdkVersion = max_sdk_version;
2577*d57664e9SAndroid Build Coastguard Worker permission->implied = true;
2578*d57664e9SAndroid Build Coastguard Worker permission->impliedReason = reason;
2579*d57664e9SAndroid Build Coastguard Worker implied_permissions_.push_back(std::move(permission));
2580*d57664e9SAndroid Build Coastguard Worker };
2581*d57664e9SAndroid Build Coastguard Worker
2582*d57664e9SAndroid Build Coastguard Worker // Implied permissions
2583*d57664e9SAndroid Build Coastguard Worker // Pre-1.6 implicitly granted permission compatibility logic
2584*d57664e9SAndroid Build Coastguard Worker bool insert_write_external = false;
2585*d57664e9SAndroid Build Coastguard Worker auto write_external_permission = ElementCast<UsesPermission>(
2586*d57664e9SAndroid Build Coastguard Worker FindPermission(root_element_.get(), "android.permission.WRITE_EXTERNAL_STORAGE"));
2587*d57664e9SAndroid Build Coastguard Worker
2588*d57664e9SAndroid Build Coastguard Worker if (target_sdk() < SDK_DONUT) {
2589*d57664e9SAndroid Build Coastguard Worker if (!write_external_permission) {
2590*d57664e9SAndroid Build Coastguard Worker AddImpliedPermission("android.permission.WRITE_EXTERNAL_STORAGE", "targetSdkVersion < 4", -1);
2591*d57664e9SAndroid Build Coastguard Worker insert_write_external = true;
2592*d57664e9SAndroid Build Coastguard Worker }
2593*d57664e9SAndroid Build Coastguard Worker
2594*d57664e9SAndroid Build Coastguard Worker if (!FindPermission(root_element_.get(), "android.permission.READ_PHONE_STATE")) {
2595*d57664e9SAndroid Build Coastguard Worker AddImpliedPermission("android.permission.READ_PHONE_STATE", "targetSdkVersion < 4", -1);
2596*d57664e9SAndroid Build Coastguard Worker }
2597*d57664e9SAndroid Build Coastguard Worker }
2598*d57664e9SAndroid Build Coastguard Worker
2599*d57664e9SAndroid Build Coastguard Worker // If the application has requested WRITE_EXTERNAL_STORAGE, we will
2600*d57664e9SAndroid Build Coastguard Worker // force them to always take READ_EXTERNAL_STORAGE as well. We always
2601*d57664e9SAndroid Build Coastguard Worker // do this (regardless of target API version) because we can't have
2602*d57664e9SAndroid Build Coastguard Worker // an app with write permission but not read permission.
2603*d57664e9SAndroid Build Coastguard Worker auto read_external =
2604*d57664e9SAndroid Build Coastguard Worker FindPermission(root_element_.get(), "android.permission.READ_EXTERNAL_STORAGE");
2605*d57664e9SAndroid Build Coastguard Worker if (!read_external && (insert_write_external || write_external_permission)) {
2606*d57664e9SAndroid Build Coastguard Worker AddImpliedPermission(
2607*d57664e9SAndroid Build Coastguard Worker "android.permission.READ_EXTERNAL_STORAGE", "requested WRITE_EXTERNAL_STORAGE",
2608*d57664e9SAndroid Build Coastguard Worker (write_external_permission) ? write_external_permission->maxSdkVersion : -1);
2609*d57664e9SAndroid Build Coastguard Worker }
2610*d57664e9SAndroid Build Coastguard Worker
2611*d57664e9SAndroid Build Coastguard Worker // Pre-JellyBean call log permission compatibility.
2612*d57664e9SAndroid Build Coastguard Worker if (target_sdk() < SDK_JELLY_BEAN) {
2613*d57664e9SAndroid Build Coastguard Worker if (!FindPermission(root_element_.get(), "android.permission.READ_CALL_LOG") &&
2614*d57664e9SAndroid Build Coastguard Worker FindPermission(root_element_.get(), "android.permission.READ_CONTACTS")) {
2615*d57664e9SAndroid Build Coastguard Worker AddImpliedPermission("android.permission.READ_CALL_LOG",
2616*d57664e9SAndroid Build Coastguard Worker "targetSdkVersion < 16 and requested READ_CONTACTS", -1);
2617*d57664e9SAndroid Build Coastguard Worker }
2618*d57664e9SAndroid Build Coastguard Worker
2619*d57664e9SAndroid Build Coastguard Worker if (!FindPermission(root_element_.get(), "android.permission.WRITE_CALL_LOG") &&
2620*d57664e9SAndroid Build Coastguard Worker FindPermission(root_element_.get(), "android.permission.WRITE_CONTACTS")) {
2621*d57664e9SAndroid Build Coastguard Worker AddImpliedPermission("android.permission.WRITE_CALL_LOG",
2622*d57664e9SAndroid Build Coastguard Worker "targetSdkVersion < 16 and requested WRITE_CONTACTS", -1);
2623*d57664e9SAndroid Build Coastguard Worker }
2624*d57664e9SAndroid Build Coastguard Worker }
2625*d57664e9SAndroid Build Coastguard Worker
2626*d57664e9SAndroid Build Coastguard Worker // If the app hasn't declared the touchscreen as a feature requirement (either
2627*d57664e9SAndroid Build Coastguard Worker // directly or implied, required or not), then the faketouch feature is implied.
2628*d57664e9SAndroid Build Coastguard Worker if (!common_feature_group()->HasFeature("android.hardware.touchscreen")) {
2629*d57664e9SAndroid Build Coastguard Worker common_feature_group()->addImpliedFeature("android.hardware.faketouch",
2630*d57664e9SAndroid Build Coastguard Worker "default feature for all apps", false);
2631*d57664e9SAndroid Build Coastguard Worker }
2632*d57664e9SAndroid Build Coastguard Worker
2633*d57664e9SAndroid Build Coastguard Worker // Only print the common feature group if no feature group is defined
2634*d57664e9SAndroid Build Coastguard Worker std::vector<FeatureGroup*> feature_groups;
2635*d57664e9SAndroid Build Coastguard Worker ForEachChild(root_element_.get(), [&feature_groups](ManifestExtractor::Element* el) -> void {
2636*d57664e9SAndroid Build Coastguard Worker if (auto feature_group = ElementCast<FeatureGroup>(el)) {
2637*d57664e9SAndroid Build Coastguard Worker feature_groups.push_back(feature_group);
2638*d57664e9SAndroid Build Coastguard Worker }
2639*d57664e9SAndroid Build Coastguard Worker });
2640*d57664e9SAndroid Build Coastguard Worker
2641*d57664e9SAndroid Build Coastguard Worker if (feature_groups.empty()) {
2642*d57664e9SAndroid Build Coastguard Worker feature_groups_.push_back(common_feature_group());
2643*d57664e9SAndroid Build Coastguard Worker } else {
2644*d57664e9SAndroid Build Coastguard Worker // Merge the common feature group into the feature group
2645*d57664e9SAndroid Build Coastguard Worker for (auto& feature_group : feature_groups) {
2646*d57664e9SAndroid Build Coastguard Worker feature_group->Merge(common_feature_group());
2647*d57664e9SAndroid Build Coastguard Worker feature_groups_.push_back(feature_group);
2648*d57664e9SAndroid Build Coastguard Worker }
2649*d57664e9SAndroid Build Coastguard Worker };
2650*d57664e9SAndroid Build Coastguard Worker
2651*d57664e9SAndroid Build Coastguard Worker // Collect the component types of the application
2652*d57664e9SAndroid Build Coastguard Worker ForEachChild(root_element_.get(), [&](ManifestExtractor::Element* el) -> void {
2653*d57664e9SAndroid Build Coastguard Worker if (ElementCast<Action>(el)) {
2654*d57664e9SAndroid Build Coastguard Worker auto action = ElementCast<Action>(el);
2655*d57664e9SAndroid Build Coastguard Worker if (!action->component.empty()) {
2656*d57664e9SAndroid Build Coastguard Worker components_.discovered_components.insert(action->component);
2657*d57664e9SAndroid Build Coastguard Worker return;
2658*d57664e9SAndroid Build Coastguard Worker }
2659*d57664e9SAndroid Build Coastguard Worker }
2660*d57664e9SAndroid Build Coastguard Worker
2661*d57664e9SAndroid Build Coastguard Worker if (ElementCast<Category>(el)) {
2662*d57664e9SAndroid Build Coastguard Worker auto category = ElementCast<Category>(el);
2663*d57664e9SAndroid Build Coastguard Worker if (!category->component.empty()) {
2664*d57664e9SAndroid Build Coastguard Worker components_.discovered_components.insert(category->component);
2665*d57664e9SAndroid Build Coastguard Worker return;
2666*d57664e9SAndroid Build Coastguard Worker }
2667*d57664e9SAndroid Build Coastguard Worker }
2668*d57664e9SAndroid Build Coastguard Worker });
2669*d57664e9SAndroid Build Coastguard Worker
2670*d57664e9SAndroid Build Coastguard Worker // Check for the payment component
2671*d57664e9SAndroid Build Coastguard Worker ForEachChild(root_element_.get(), [this, &diag](ManifestExtractor::Element* el) -> void {
2672*d57664e9SAndroid Build Coastguard Worker if (auto service = ElementCast<Service>(el)) {
2673*d57664e9SAndroid Build Coastguard Worker auto host_apdu_action = ElementCast<Action>(FindElement(service,
2674*d57664e9SAndroid Build Coastguard Worker [&](ManifestExtractor::Element* el) -> bool {
2675*d57664e9SAndroid Build Coastguard Worker if (auto action = ElementCast<Action>(el)) {
2676*d57664e9SAndroid Build Coastguard Worker return (action->component == "host-apdu");
2677*d57664e9SAndroid Build Coastguard Worker }
2678*d57664e9SAndroid Build Coastguard Worker return false;
2679*d57664e9SAndroid Build Coastguard Worker }));
2680*d57664e9SAndroid Build Coastguard Worker
2681*d57664e9SAndroid Build Coastguard Worker auto offhost_apdu_action = ElementCast<Action>(FindElement(service,
2682*d57664e9SAndroid Build Coastguard Worker [&](ManifestExtractor::Element* el) -> bool {
2683*d57664e9SAndroid Build Coastguard Worker if (auto action = ElementCast<Action>(el)) {
2684*d57664e9SAndroid Build Coastguard Worker return (action->component == "offhost-apdu");
2685*d57664e9SAndroid Build Coastguard Worker }
2686*d57664e9SAndroid Build Coastguard Worker return false;
2687*d57664e9SAndroid Build Coastguard Worker }));
2688*d57664e9SAndroid Build Coastguard Worker
2689*d57664e9SAndroid Build Coastguard Worker ForEachChild(service,
2690*d57664e9SAndroid Build Coastguard Worker [this, &diag, &host_apdu_action,
2691*d57664e9SAndroid Build Coastguard Worker &offhost_apdu_action](ManifestExtractor::Element* el) -> void {
2692*d57664e9SAndroid Build Coastguard Worker if (auto meta_data = ElementCast<MetaData>(el)) {
2693*d57664e9SAndroid Build Coastguard Worker if ((meta_data->name == "android.nfc.cardemulation.host_apdu_service" &&
2694*d57664e9SAndroid Build Coastguard Worker host_apdu_action) ||
2695*d57664e9SAndroid Build Coastguard Worker (meta_data->name == "android.nfc.cardemulation.off_host_apdu_service" &&
2696*d57664e9SAndroid Build Coastguard Worker offhost_apdu_action)) {
2697*d57664e9SAndroid Build Coastguard Worker // Attempt to load the resource file
2698*d57664e9SAndroid Build Coastguard Worker if (meta_data->resource.empty()) {
2699*d57664e9SAndroid Build Coastguard Worker return;
2700*d57664e9SAndroid Build Coastguard Worker }
2701*d57664e9SAndroid Build Coastguard Worker auto resource = this->apk_->LoadXml(meta_data->resource, diag);
2702*d57664e9SAndroid Build Coastguard Worker if (!resource) {
2703*d57664e9SAndroid Build Coastguard Worker return;
2704*d57664e9SAndroid Build Coastguard Worker }
2705*d57664e9SAndroid Build Coastguard Worker
2706*d57664e9SAndroid Build Coastguard Worker // Look for the payment category on an <aid-group> element
2707*d57664e9SAndroid Build Coastguard Worker auto& root = resource.get()->root;
2708*d57664e9SAndroid Build Coastguard Worker if ((host_apdu_action && root->name == "host-apdu-service") ||
2709*d57664e9SAndroid Build Coastguard Worker (offhost_apdu_action && root->name == "offhost-apdu-service")) {
2710*d57664e9SAndroid Build Coastguard Worker for (auto& child : root->GetChildElements()) {
2711*d57664e9SAndroid Build Coastguard Worker if (child->name == "aid-group") {
2712*d57664e9SAndroid Build Coastguard Worker auto category = FindAttribute(child, CATEGORY_ATTR);
2713*d57664e9SAndroid Build Coastguard Worker if (category && category->value == "payment") {
2714*d57664e9SAndroid Build Coastguard Worker this->components_.discovered_components.insert("payment");
2715*d57664e9SAndroid Build Coastguard Worker return;
2716*d57664e9SAndroid Build Coastguard Worker }
2717*d57664e9SAndroid Build Coastguard Worker }
2718*d57664e9SAndroid Build Coastguard Worker }
2719*d57664e9SAndroid Build Coastguard Worker }
2720*d57664e9SAndroid Build Coastguard Worker }
2721*d57664e9SAndroid Build Coastguard Worker }
2722*d57664e9SAndroid Build Coastguard Worker });
2723*d57664e9SAndroid Build Coastguard Worker }
2724*d57664e9SAndroid Build Coastguard Worker });
2725*d57664e9SAndroid Build Coastguard Worker
2726*d57664e9SAndroid Build Coastguard Worker // Print presence of activities, receivers, and services with no special components
2727*d57664e9SAndroid Build Coastguard Worker FindElement(root_element_.get(), [&](ManifestExtractor::Element* el) -> bool {
2728*d57664e9SAndroid Build Coastguard Worker if (auto activity = ElementCast<Activity>(el)) {
2729*d57664e9SAndroid Build Coastguard Worker if (!activity->has_component_) {
2730*d57664e9SAndroid Build Coastguard Worker components_.other_activities = true;
2731*d57664e9SAndroid Build Coastguard Worker return true;
2732*d57664e9SAndroid Build Coastguard Worker }
2733*d57664e9SAndroid Build Coastguard Worker }
2734*d57664e9SAndroid Build Coastguard Worker return false;
2735*d57664e9SAndroid Build Coastguard Worker });
2736*d57664e9SAndroid Build Coastguard Worker
2737*d57664e9SAndroid Build Coastguard Worker FindElement(root_element_.get(), [&](ManifestExtractor::Element* el) -> bool {
2738*d57664e9SAndroid Build Coastguard Worker if (auto receiver = ElementCast<Receiver>(el)) {
2739*d57664e9SAndroid Build Coastguard Worker if (!receiver->has_component) {
2740*d57664e9SAndroid Build Coastguard Worker components_.other_receivers = true;
2741*d57664e9SAndroid Build Coastguard Worker return true;
2742*d57664e9SAndroid Build Coastguard Worker }
2743*d57664e9SAndroid Build Coastguard Worker }
2744*d57664e9SAndroid Build Coastguard Worker return false;
2745*d57664e9SAndroid Build Coastguard Worker });
2746*d57664e9SAndroid Build Coastguard Worker
2747*d57664e9SAndroid Build Coastguard Worker FindElement(root_element_.get(), [&](ManifestExtractor::Element* el) -> bool {
2748*d57664e9SAndroid Build Coastguard Worker if (auto service = ElementCast<Service>(el)) {
2749*d57664e9SAndroid Build Coastguard Worker if (!service->has_component) {
2750*d57664e9SAndroid Build Coastguard Worker components_.other_services = true;
2751*d57664e9SAndroid Build Coastguard Worker return true;
2752*d57664e9SAndroid Build Coastguard Worker }
2753*d57664e9SAndroid Build Coastguard Worker }
2754*d57664e9SAndroid Build Coastguard Worker return false;
2755*d57664e9SAndroid Build Coastguard Worker });
2756*d57664e9SAndroid Build Coastguard Worker
2757*d57664e9SAndroid Build Coastguard Worker // Gather the supported screens
2758*d57664e9SAndroid Build Coastguard Worker const static SupportsScreen default_screens{};
2759*d57664e9SAndroid Build Coastguard Worker SupportsScreen* screen = ElementCast<SupportsScreen>(
2760*d57664e9SAndroid Build Coastguard Worker FindElement(root_element_.get(), [&](ManifestExtractor::Element* el) -> bool {
2761*d57664e9SAndroid Build Coastguard Worker return ElementCast<SupportsScreen>(el) != nullptr;
2762*d57664e9SAndroid Build Coastguard Worker }));
2763*d57664e9SAndroid Build Coastguard Worker supports_screen_ = screen ? screen : &default_screens;
2764*d57664e9SAndroid Build Coastguard Worker
2765*d57664e9SAndroid Build Coastguard Worker bool has_renderscript_bitcode = false;
2766*d57664e9SAndroid Build Coastguard Worker auto it = apk_->GetFileCollection()->Iterator();
2767*d57664e9SAndroid Build Coastguard Worker while (it->HasNext()) {
2768*d57664e9SAndroid Build Coastguard Worker if (it->Next()->GetSource().path.ends_with(".bc")) {
2769*d57664e9SAndroid Build Coastguard Worker has_renderscript_bitcode = true;
2770*d57664e9SAndroid Build Coastguard Worker break;
2771*d57664e9SAndroid Build Coastguard Worker }
2772*d57664e9SAndroid Build Coastguard Worker }
2773*d57664e9SAndroid Build Coastguard Worker
2774*d57664e9SAndroid Build Coastguard Worker // Gather the supported architectures_ of the app
2775*d57664e9SAndroid Build Coastguard Worker std::set<std::string> architectures_from_apk;
2776*d57664e9SAndroid Build Coastguard Worker it = apk_->GetFileCollection()->Iterator();
2777*d57664e9SAndroid Build Coastguard Worker while (it->HasNext()) {
2778*d57664e9SAndroid Build Coastguard Worker auto file_path = it->Next()->GetSource().path.c_str();
2779*d57664e9SAndroid Build Coastguard Worker
2780*d57664e9SAndroid Build Coastguard Worker const char* last_slash =
2781*d57664e9SAndroid Build Coastguard Worker android::util::ValidLibraryPathLastSlash(file_path, has_renderscript_bitcode, false);
2782*d57664e9SAndroid Build Coastguard Worker if (last_slash) {
2783*d57664e9SAndroid Build Coastguard Worker architectures_from_apk.insert(std::string(file_path + APK_LIB_LEN, last_slash));
2784*d57664e9SAndroid Build Coastguard Worker }
2785*d57664e9SAndroid Build Coastguard Worker }
2786*d57664e9SAndroid Build Coastguard Worker
2787*d57664e9SAndroid Build Coastguard Worker // Determine if the application has multiArch supports
2788*d57664e9SAndroid Build Coastguard Worker auto has_multi_arch =
2789*d57664e9SAndroid Build Coastguard Worker FindElement(root_element_.get(), [&](ManifestExtractor::Element* el) -> bool {
2790*d57664e9SAndroid Build Coastguard Worker if (auto application = ElementCast<Application>(el)) {
2791*d57664e9SAndroid Build Coastguard Worker return application->has_multi_arch;
2792*d57664e9SAndroid Build Coastguard Worker }
2793*d57664e9SAndroid Build Coastguard Worker return false;
2794*d57664e9SAndroid Build Coastguard Worker });
2795*d57664e9SAndroid Build Coastguard Worker
2796*d57664e9SAndroid Build Coastguard Worker bool output_alt_native_code = false;
2797*d57664e9SAndroid Build Coastguard Worker // A multiArch package is one that contains 64-bit and
2798*d57664e9SAndroid Build Coastguard Worker // 32-bit versions of native code and expects 3rd-party
2799*d57664e9SAndroid Build Coastguard Worker // apps to load these native code libraries. Since most
2800*d57664e9SAndroid Build Coastguard Worker // 64-bit systems also support 32-bit apps, the apps
2801*d57664e9SAndroid Build Coastguard Worker // loading this multiArch package's code may be either
2802*d57664e9SAndroid Build Coastguard Worker if (has_multi_arch) {
2803*d57664e9SAndroid Build Coastguard Worker // If this is a multiArch package, report the 64-bit
2804*d57664e9SAndroid Build Coastguard Worker // version only. Then as a separate entry, report the
2805*d57664e9SAndroid Build Coastguard Worker // rest.
2806*d57664e9SAndroid Build Coastguard Worker //
2807*d57664e9SAndroid Build Coastguard Worker // If we report the 32-bit architecture, this APK will
2808*d57664e9SAndroid Build Coastguard Worker // be installed on a 32-bit device, causing a large waste
2809*d57664e9SAndroid Build Coastguard Worker // of bandwidth and disk space. This assumes that
2810*d57664e9SAndroid Build Coastguard Worker // the developer of the multiArch package has also
2811*d57664e9SAndroid Build Coastguard Worker // made a version that is 32-bit only.
2812*d57664e9SAndroid Build Coastguard Worker const std::string kIntel64 = "x86_64";
2813*d57664e9SAndroid Build Coastguard Worker const std::string kArm64 = "arm64-v8a";
2814*d57664e9SAndroid Build Coastguard Worker
2815*d57664e9SAndroid Build Coastguard Worker auto arch = architectures_from_apk.find(kIntel64);
2816*d57664e9SAndroid Build Coastguard Worker if (arch == architectures_from_apk.end()) {
2817*d57664e9SAndroid Build Coastguard Worker arch = architectures_from_apk.find(kArm64);
2818*d57664e9SAndroid Build Coastguard Worker }
2819*d57664e9SAndroid Build Coastguard Worker
2820*d57664e9SAndroid Build Coastguard Worker if (arch != architectures_from_apk.end()) {
2821*d57664e9SAndroid Build Coastguard Worker architectures_.architectures.insert(*arch);
2822*d57664e9SAndroid Build Coastguard Worker architectures_from_apk.erase(arch);
2823*d57664e9SAndroid Build Coastguard Worker output_alt_native_code = true;
2824*d57664e9SAndroid Build Coastguard Worker }
2825*d57664e9SAndroid Build Coastguard Worker }
2826*d57664e9SAndroid Build Coastguard Worker for (auto& arch : architectures_from_apk) {
2827*d57664e9SAndroid Build Coastguard Worker if (output_alt_native_code) {
2828*d57664e9SAndroid Build Coastguard Worker architectures_.alt_architectures.insert(arch);
2829*d57664e9SAndroid Build Coastguard Worker } else {
2830*d57664e9SAndroid Build Coastguard Worker architectures_.architectures.insert(arch);
2831*d57664e9SAndroid Build Coastguard Worker }
2832*d57664e9SAndroid Build Coastguard Worker }
2833*d57664e9SAndroid Build Coastguard Worker return true;
2834*d57664e9SAndroid Build Coastguard Worker }
2835*d57664e9SAndroid Build Coastguard Worker
Dump(text::Printer * printer)2836*d57664e9SAndroid Build Coastguard Worker bool ManifestExtractor::Dump(text::Printer* printer) {
2837*d57664e9SAndroid Build Coastguard Worker Print(root_element_.get(), printer);
2838*d57664e9SAndroid Build Coastguard Worker if (options_.only_permissions) {
2839*d57664e9SAndroid Build Coastguard Worker return true;
2840*d57664e9SAndroid Build Coastguard Worker }
2841*d57664e9SAndroid Build Coastguard Worker
2842*d57664e9SAndroid Build Coastguard Worker for (auto& implied_permission : implied_permissions_) {
2843*d57664e9SAndroid Build Coastguard Worker implied_permission->Print(printer);
2844*d57664e9SAndroid Build Coastguard Worker }
2845*d57664e9SAndroid Build Coastguard Worker for (auto& feature_group : feature_groups_) {
2846*d57664e9SAndroid Build Coastguard Worker feature_group->PrintGroup(printer);
2847*d57664e9SAndroid Build Coastguard Worker }
2848*d57664e9SAndroid Build Coastguard Worker components_.Print(printer);
2849*d57664e9SAndroid Build Coastguard Worker supports_screen_->PrintScreens(printer, target_sdk_);
2850*d57664e9SAndroid Build Coastguard Worker
2851*d57664e9SAndroid Build Coastguard Worker // Print all the unique locales of the apk
2852*d57664e9SAndroid Build Coastguard Worker printer->Print("locales:");
2853*d57664e9SAndroid Build Coastguard Worker for (auto& config : locales_) {
2854*d57664e9SAndroid Build Coastguard Worker if (config.first.empty()) {
2855*d57664e9SAndroid Build Coastguard Worker printer->Print(" '--_--'");
2856*d57664e9SAndroid Build Coastguard Worker } else {
2857*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" '%s'", config.first.data()));
2858*d57664e9SAndroid Build Coastguard Worker }
2859*d57664e9SAndroid Build Coastguard Worker }
2860*d57664e9SAndroid Build Coastguard Worker printer->Print("\n");
2861*d57664e9SAndroid Build Coastguard Worker
2862*d57664e9SAndroid Build Coastguard Worker // Print all the densities locales of the apk
2863*d57664e9SAndroid Build Coastguard Worker printer->Print("densities:");
2864*d57664e9SAndroid Build Coastguard Worker for (auto& config : densities_) {
2865*d57664e9SAndroid Build Coastguard Worker printer->Print(StringPrintf(" '%d'", config.first));
2866*d57664e9SAndroid Build Coastguard Worker }
2867*d57664e9SAndroid Build Coastguard Worker printer->Print("\n");
2868*d57664e9SAndroid Build Coastguard Worker
2869*d57664e9SAndroid Build Coastguard Worker architectures_.Print(printer);
2870*d57664e9SAndroid Build Coastguard Worker return true;
2871*d57664e9SAndroid Build Coastguard Worker }
2872*d57664e9SAndroid Build Coastguard Worker
DumpProto(pb::Badging * out_badging)2873*d57664e9SAndroid Build Coastguard Worker bool ManifestExtractor::DumpProto(pb::Badging* out_badging) {
2874*d57664e9SAndroid Build Coastguard Worker ToProto(root_element_.get(), out_badging);
2875*d57664e9SAndroid Build Coastguard Worker for (auto& implied_permission : implied_permissions_) {
2876*d57664e9SAndroid Build Coastguard Worker implied_permission->ToProto(out_badging);
2877*d57664e9SAndroid Build Coastguard Worker }
2878*d57664e9SAndroid Build Coastguard Worker for (auto& feature_group : feature_groups_) {
2879*d57664e9SAndroid Build Coastguard Worker feature_group->GroupToProto(out_badging);
2880*d57664e9SAndroid Build Coastguard Worker }
2881*d57664e9SAndroid Build Coastguard Worker components_.ToProto(out_badging);
2882*d57664e9SAndroid Build Coastguard Worker supports_screen_->ToProtoScreens(out_badging, target_sdk_);
2883*d57664e9SAndroid Build Coastguard Worker
2884*d57664e9SAndroid Build Coastguard Worker for (auto& config : locales_) {
2885*d57664e9SAndroid Build Coastguard Worker if (config.first.empty()) {
2886*d57664e9SAndroid Build Coastguard Worker out_badging->add_locales("--_--");
2887*d57664e9SAndroid Build Coastguard Worker } else {
2888*d57664e9SAndroid Build Coastguard Worker out_badging->add_locales(config.first);
2889*d57664e9SAndroid Build Coastguard Worker }
2890*d57664e9SAndroid Build Coastguard Worker }
2891*d57664e9SAndroid Build Coastguard Worker for (auto& config : densities_) {
2892*d57664e9SAndroid Build Coastguard Worker out_badging->add_densities(config.first);
2893*d57664e9SAndroid Build Coastguard Worker }
2894*d57664e9SAndroid Build Coastguard Worker
2895*d57664e9SAndroid Build Coastguard Worker architectures_.ToProto(out_badging);
2896*d57664e9SAndroid Build Coastguard Worker return true;
2897*d57664e9SAndroid Build Coastguard Worker }
2898*d57664e9SAndroid Build Coastguard Worker
2899*d57664e9SAndroid Build Coastguard Worker template <typename T>
GetExpectedTagForType()2900*d57664e9SAndroid Build Coastguard Worker constexpr const char* GetExpectedTagForType() {
2901*d57664e9SAndroid Build Coastguard Worker // This array does not appear at runtime, as GetExpectedTagForType function is used by compiler
2902*d57664e9SAndroid Build Coastguard Worker // to inject proper 'expected_tag' into ElementCast.
2903*d57664e9SAndroid Build Coastguard Worker std::array<std::pair<const char*, bool>, 38> tags = {
2904*d57664e9SAndroid Build Coastguard Worker std::make_pair("action", std::is_same<Action, T>::value),
2905*d57664e9SAndroid Build Coastguard Worker std::make_pair("activity", std::is_same<Activity, T>::value),
2906*d57664e9SAndroid Build Coastguard Worker std::make_pair("additional-certificate", std::is_same<AdditionalCertificate, T>::value),
2907*d57664e9SAndroid Build Coastguard Worker std::make_pair("application", std::is_same<Application, T>::value),
2908*d57664e9SAndroid Build Coastguard Worker std::make_pair("category", std::is_same<Category, T>::value),
2909*d57664e9SAndroid Build Coastguard Worker std::make_pair("compatible-screens", std::is_same<CompatibleScreens, T>::value),
2910*d57664e9SAndroid Build Coastguard Worker std::make_pair("feature-group", std::is_same<FeatureGroup, T>::value),
2911*d57664e9SAndroid Build Coastguard Worker std::make_pair("input-type", std::is_same<InputType, T>::value),
2912*d57664e9SAndroid Build Coastguard Worker std::make_pair("install-constraints", std::is_same<InstallConstraints, T>::value),
2913*d57664e9SAndroid Build Coastguard Worker std::make_pair("intent-filter", std::is_same<IntentFilter, T>::value),
2914*d57664e9SAndroid Build Coastguard Worker std::make_pair("meta-data", std::is_same<MetaData, T>::value),
2915*d57664e9SAndroid Build Coastguard Worker std::make_pair("manifest", std::is_same<Manifest, T>::value),
2916*d57664e9SAndroid Build Coastguard Worker std::make_pair("original-package", std::is_same<OriginalPackage, T>::value),
2917*d57664e9SAndroid Build Coastguard Worker std::make_pair("overlay", std::is_same<Overlay, T>::value),
2918*d57664e9SAndroid Build Coastguard Worker std::make_pair("package-verifier", std::is_same<PackageVerifier, T>::value),
2919*d57664e9SAndroid Build Coastguard Worker std::make_pair("permission", std::is_same<Permission, T>::value),
2920*d57664e9SAndroid Build Coastguard Worker std::make_pair("property", std::is_same<Property, T>::value),
2921*d57664e9SAndroid Build Coastguard Worker std::make_pair("provider", std::is_same<Provider, T>::value),
2922*d57664e9SAndroid Build Coastguard Worker std::make_pair("receiver", std::is_same<Receiver, T>::value),
2923*d57664e9SAndroid Build Coastguard Worker std::make_pair("required-feature", std::is_same<RequiredFeature, T>::value),
2924*d57664e9SAndroid Build Coastguard Worker std::make_pair("required-not-feature", std::is_same<RequiredNotFeature, T>::value),
2925*d57664e9SAndroid Build Coastguard Worker std::make_pair("screen", std::is_same<Screen, T>::value),
2926*d57664e9SAndroid Build Coastguard Worker std::make_pair("service", std::is_same<Service, T>::value),
2927*d57664e9SAndroid Build Coastguard Worker std::make_pair("sdk-library", std::is_same<SdkLibrary, T>::value),
2928*d57664e9SAndroid Build Coastguard Worker std::make_pair("static-library", std::is_same<StaticLibrary, T>::value),
2929*d57664e9SAndroid Build Coastguard Worker std::make_pair("supports-gl-texture", std::is_same<SupportsGlTexture, T>::value),
2930*d57664e9SAndroid Build Coastguard Worker std::make_pair("supports-input", std::is_same<SupportsInput, T>::value),
2931*d57664e9SAndroid Build Coastguard Worker std::make_pair("supports-screens", std::is_same<SupportsScreen, T>::value),
2932*d57664e9SAndroid Build Coastguard Worker std::make_pair("uses-configuration", std::is_same<UsesConfiguarion, T>::value),
2933*d57664e9SAndroid Build Coastguard Worker std::make_pair("uses-feature", std::is_same<UsesFeature, T>::value),
2934*d57664e9SAndroid Build Coastguard Worker std::make_pair("uses-library", std::is_same<UsesLibrary, T>::value),
2935*d57664e9SAndroid Build Coastguard Worker std::make_pair("uses-native-library", std::is_same<UsesNativeLibrary, T>::value),
2936*d57664e9SAndroid Build Coastguard Worker std::make_pair("uses-package", std::is_same<UsesPackage, T>::value),
2937*d57664e9SAndroid Build Coastguard Worker std::make_pair("uses-permission", std::is_same<UsesPermission, T>::value),
2938*d57664e9SAndroid Build Coastguard Worker std::make_pair("uses-permission-sdk-23", std::is_same<UsesPermissionSdk23, T>::value),
2939*d57664e9SAndroid Build Coastguard Worker std::make_pair("uses-sdk", std::is_same<UsesSdkBadging, T>::value),
2940*d57664e9SAndroid Build Coastguard Worker std::make_pair("uses-sdk-library", std::is_same<UsesSdkLibrary, T>::value),
2941*d57664e9SAndroid Build Coastguard Worker std::make_pair("uses-static-library", std::is_same<UsesStaticLibrary, T>::value),
2942*d57664e9SAndroid Build Coastguard Worker };
2943*d57664e9SAndroid Build Coastguard Worker for (const auto& pair : tags) {
2944*d57664e9SAndroid Build Coastguard Worker if (pair.second) {
2945*d57664e9SAndroid Build Coastguard Worker return pair.first;
2946*d57664e9SAndroid Build Coastguard Worker }
2947*d57664e9SAndroid Build Coastguard Worker }
2948*d57664e9SAndroid Build Coastguard Worker return nullptr;
2949*d57664e9SAndroid Build Coastguard Worker }
2950*d57664e9SAndroid Build Coastguard Worker
2951*d57664e9SAndroid Build Coastguard Worker /**
2952*d57664e9SAndroid Build Coastguard Worker * Returns the element casted to the type if the element is of that type. Otherwise, returns a null
2953*d57664e9SAndroid Build Coastguard Worker * pointer.
2954*d57664e9SAndroid Build Coastguard Worker **/
2955*d57664e9SAndroid Build Coastguard Worker template<typename T>
ElementCast(ManifestExtractor::Element * element)2956*d57664e9SAndroid Build Coastguard Worker T* ElementCast(ManifestExtractor::Element* element) {
2957*d57664e9SAndroid Build Coastguard Worker constexpr const char* expected_tag = GetExpectedTagForType<T>();
2958*d57664e9SAndroid Build Coastguard Worker if (element != nullptr && expected_tag != nullptr && element->is_featured() &&
2959*d57664e9SAndroid Build Coastguard Worker element->tag() == expected_tag) {
2960*d57664e9SAndroid Build Coastguard Worker return static_cast<T*>(element);
2961*d57664e9SAndroid Build Coastguard Worker }
2962*d57664e9SAndroid Build Coastguard Worker return nullptr;
2963*d57664e9SAndroid Build Coastguard Worker }
2964*d57664e9SAndroid Build Coastguard Worker
2965*d57664e9SAndroid Build Coastguard Worker template<typename T>
CreateType()2966*d57664e9SAndroid Build Coastguard Worker std::unique_ptr<T> CreateType() {
2967*d57664e9SAndroid Build Coastguard Worker return std::move(util::make_unique<T>());
2968*d57664e9SAndroid Build Coastguard Worker }
2969*d57664e9SAndroid Build Coastguard Worker
Inflate(ManifestExtractor * extractor,xml::Element * el,const std::string & parent_tag)2970*d57664e9SAndroid Build Coastguard Worker std::unique_ptr<ManifestExtractor::Element> ManifestExtractor::Element::Inflate(
2971*d57664e9SAndroid Build Coastguard Worker ManifestExtractor* extractor, xml::Element* el, const std::string& parent_tag) {
2972*d57664e9SAndroid Build Coastguard Worker static const std::unordered_map<std::string_view,
2973*d57664e9SAndroid Build Coastguard Worker std::function<std::unique_ptr<ManifestExtractor::Element>()>>
2974*d57664e9SAndroid Build Coastguard Worker kTagCheck = {
2975*d57664e9SAndroid Build Coastguard Worker {"action", &CreateType<Action>},
2976*d57664e9SAndroid Build Coastguard Worker {"activity", &CreateType<Activity>},
2977*d57664e9SAndroid Build Coastguard Worker {"additional-certificate", &CreateType<AdditionalCertificate>},
2978*d57664e9SAndroid Build Coastguard Worker {"application", &CreateType<Application>},
2979*d57664e9SAndroid Build Coastguard Worker {"category", &CreateType<Category>},
2980*d57664e9SAndroid Build Coastguard Worker {"compatible-screens", &CreateType<CompatibleScreens>},
2981*d57664e9SAndroid Build Coastguard Worker {"feature-group", &CreateType<FeatureGroup>},
2982*d57664e9SAndroid Build Coastguard Worker {"input-type", &CreateType<InputType>},
2983*d57664e9SAndroid Build Coastguard Worker {"install-constraints", &CreateType<InstallConstraints>},
2984*d57664e9SAndroid Build Coastguard Worker {"intent-filter", &CreateType<IntentFilter>},
2985*d57664e9SAndroid Build Coastguard Worker {"manifest", &CreateType<Manifest>},
2986*d57664e9SAndroid Build Coastguard Worker {"meta-data", &CreateType<MetaData>},
2987*d57664e9SAndroid Build Coastguard Worker {"original-package", &CreateType<OriginalPackage>},
2988*d57664e9SAndroid Build Coastguard Worker {"overlay", &CreateType<Overlay>},
2989*d57664e9SAndroid Build Coastguard Worker {"package-verifier", &CreateType<PackageVerifier>},
2990*d57664e9SAndroid Build Coastguard Worker {"permission", &CreateType<Permission>},
2991*d57664e9SAndroid Build Coastguard Worker {"property", &CreateType<Property>},
2992*d57664e9SAndroid Build Coastguard Worker {"provider", &CreateType<Provider>},
2993*d57664e9SAndroid Build Coastguard Worker {"receiver", &CreateType<Receiver>},
2994*d57664e9SAndroid Build Coastguard Worker {"required-feature", &CreateType<RequiredFeature>},
2995*d57664e9SAndroid Build Coastguard Worker {"required-not-feature", &CreateType<RequiredNotFeature>},
2996*d57664e9SAndroid Build Coastguard Worker {"screen", &CreateType<Screen>},
2997*d57664e9SAndroid Build Coastguard Worker {"service", &CreateType<Service>},
2998*d57664e9SAndroid Build Coastguard Worker {"sdk-library", &CreateType<SdkLibrary>},
2999*d57664e9SAndroid Build Coastguard Worker {"static-library", &CreateType<StaticLibrary>},
3000*d57664e9SAndroid Build Coastguard Worker {"supports-gl-texture", &CreateType<SupportsGlTexture>},
3001*d57664e9SAndroid Build Coastguard Worker {"supports-input", &CreateType<SupportsInput>},
3002*d57664e9SAndroid Build Coastguard Worker {"supports-screens", &CreateType<SupportsScreen>},
3003*d57664e9SAndroid Build Coastguard Worker {"uses-configuration", &CreateType<UsesConfiguarion>},
3004*d57664e9SAndroid Build Coastguard Worker {"uses-feature", &CreateType<UsesFeature>},
3005*d57664e9SAndroid Build Coastguard Worker {"uses-library", &CreateType<UsesLibrary>},
3006*d57664e9SAndroid Build Coastguard Worker {"uses-native-library", &CreateType<UsesNativeLibrary>},
3007*d57664e9SAndroid Build Coastguard Worker {"uses-package", &CreateType<UsesPackage>},
3008*d57664e9SAndroid Build Coastguard Worker {"uses-permission", &CreateType<UsesPermission>},
3009*d57664e9SAndroid Build Coastguard Worker {"uses-permission-sdk-23", &CreateType<UsesPermissionSdk23>},
3010*d57664e9SAndroid Build Coastguard Worker {"uses-sdk", &CreateType<UsesSdkBadging>},
3011*d57664e9SAndroid Build Coastguard Worker {"uses-sdk-library", &CreateType<UsesSdkLibrary>},
3012*d57664e9SAndroid Build Coastguard Worker {"uses-static-library", &CreateType<UsesStaticLibrary>},
3013*d57664e9SAndroid Build Coastguard Worker };
3014*d57664e9SAndroid Build Coastguard Worker static constexpr std::array<std::pair<std::string_view, std::string_view>, 53>
3015*d57664e9SAndroid Build Coastguard Worker kValidChildParentTags = {
3016*d57664e9SAndroid Build Coastguard Worker std::make_pair("action", "intent-filter"),
3017*d57664e9SAndroid Build Coastguard Worker std::make_pair("activity", "application"),
3018*d57664e9SAndroid Build Coastguard Worker std::make_pair("additional-certificate", "uses-package"),
3019*d57664e9SAndroid Build Coastguard Worker std::make_pair("additional-certificate", "uses-static-library"),
3020*d57664e9SAndroid Build Coastguard Worker std::make_pair("application", "manifest"),
3021*d57664e9SAndroid Build Coastguard Worker std::make_pair("category", "intent-filter"),
3022*d57664e9SAndroid Build Coastguard Worker std::make_pair("compatible-screens", "manifest"),
3023*d57664e9SAndroid Build Coastguard Worker std::make_pair("feature-group", "manifest"),
3024*d57664e9SAndroid Build Coastguard Worker std::make_pair("input-type", "supports-input"),
3025*d57664e9SAndroid Build Coastguard Worker std::make_pair("intent-filter", "activity"),
3026*d57664e9SAndroid Build Coastguard Worker std::make_pair("intent-filter", "activity-alias"),
3027*d57664e9SAndroid Build Coastguard Worker std::make_pair("intent-filter", "service"),
3028*d57664e9SAndroid Build Coastguard Worker std::make_pair("intent-filter", "receiver"),
3029*d57664e9SAndroid Build Coastguard Worker std::make_pair("intent-filter", "provider"),
3030*d57664e9SAndroid Build Coastguard Worker std::make_pair("manifest", ""),
3031*d57664e9SAndroid Build Coastguard Worker std::make_pair("meta-data", "activity"),
3032*d57664e9SAndroid Build Coastguard Worker std::make_pair("meta-data", "activity-alias"),
3033*d57664e9SAndroid Build Coastguard Worker std::make_pair("meta-data", "application"),
3034*d57664e9SAndroid Build Coastguard Worker std::make_pair("meta-data", "service"),
3035*d57664e9SAndroid Build Coastguard Worker std::make_pair("meta-data", "receiver"),
3036*d57664e9SAndroid Build Coastguard Worker std::make_pair("meta-data", "provider"),
3037*d57664e9SAndroid Build Coastguard Worker std::make_pair("original-package", "manifest"),
3038*d57664e9SAndroid Build Coastguard Worker std::make_pair("overlay", "manifest"),
3039*d57664e9SAndroid Build Coastguard Worker std::make_pair("package-verifier", "manifest"),
3040*d57664e9SAndroid Build Coastguard Worker std::make_pair("permission", "manifest"),
3041*d57664e9SAndroid Build Coastguard Worker std::make_pair("property", "activity"),
3042*d57664e9SAndroid Build Coastguard Worker std::make_pair("property", "activity-alias"),
3043*d57664e9SAndroid Build Coastguard Worker std::make_pair("property", "application"),
3044*d57664e9SAndroid Build Coastguard Worker std::make_pair("property", "service"),
3045*d57664e9SAndroid Build Coastguard Worker std::make_pair("property", "receiver"),
3046*d57664e9SAndroid Build Coastguard Worker std::make_pair("property", "provider"),
3047*d57664e9SAndroid Build Coastguard Worker std::make_pair("provider", "application"),
3048*d57664e9SAndroid Build Coastguard Worker std::make_pair("receiver", "application"),
3049*d57664e9SAndroid Build Coastguard Worker std::make_pair("required-feature", "uses-permission"),
3050*d57664e9SAndroid Build Coastguard Worker std::make_pair("required-not-feature", "uses-permission"),
3051*d57664e9SAndroid Build Coastguard Worker std::make_pair("screen", "compatible-screens"),
3052*d57664e9SAndroid Build Coastguard Worker std::make_pair("service", "application"),
3053*d57664e9SAndroid Build Coastguard Worker std::make_pair("sdk-library", "application"),
3054*d57664e9SAndroid Build Coastguard Worker std::make_pair("static-library", "application"),
3055*d57664e9SAndroid Build Coastguard Worker std::make_pair("supports-gl-texture", "manifest"),
3056*d57664e9SAndroid Build Coastguard Worker std::make_pair("supports-input", "manifest"),
3057*d57664e9SAndroid Build Coastguard Worker std::make_pair("supports-screens", "manifest"),
3058*d57664e9SAndroid Build Coastguard Worker std::make_pair("uses-configuration", "manifest"),
3059*d57664e9SAndroid Build Coastguard Worker std::make_pair("uses-feature", "feature-group"),
3060*d57664e9SAndroid Build Coastguard Worker std::make_pair("uses-feature", "manifest"),
3061*d57664e9SAndroid Build Coastguard Worker std::make_pair("uses-library", "application"),
3062*d57664e9SAndroid Build Coastguard Worker std::make_pair("uses-native-library", "application"),
3063*d57664e9SAndroid Build Coastguard Worker std::make_pair("uses-package", "application"),
3064*d57664e9SAndroid Build Coastguard Worker std::make_pair("uses-permission", "manifest"),
3065*d57664e9SAndroid Build Coastguard Worker std::make_pair("uses-permission-sdk-23", "manifest"),
3066*d57664e9SAndroid Build Coastguard Worker std::make_pair("uses-sdk", "manifest"),
3067*d57664e9SAndroid Build Coastguard Worker std::make_pair("uses-sdk-library", "application"),
3068*d57664e9SAndroid Build Coastguard Worker std::make_pair("uses-static-library", "application"),
3069*d57664e9SAndroid Build Coastguard Worker };
3070*d57664e9SAndroid Build Coastguard Worker bool is_valid_tag = std::find(kValidChildParentTags.begin(), kValidChildParentTags.end(),
3071*d57664e9SAndroid Build Coastguard Worker std::make_pair<std::string_view, std::string_view>(
3072*d57664e9SAndroid Build Coastguard Worker el->name, parent_tag)) != kValidChildParentTags.end();
3073*d57664e9SAndroid Build Coastguard Worker // Attempt to map the xml tag to a element inflater
3074*d57664e9SAndroid Build Coastguard Worker std::unique_ptr<ManifestExtractor::Element> element;
3075*d57664e9SAndroid Build Coastguard Worker auto check = kTagCheck.find(el->name);
3076*d57664e9SAndroid Build Coastguard Worker if (check != kTagCheck.end() && is_valid_tag) {
3077*d57664e9SAndroid Build Coastguard Worker element = check->second();
3078*d57664e9SAndroid Build Coastguard Worker element->featured_ = true;
3079*d57664e9SAndroid Build Coastguard Worker } else {
3080*d57664e9SAndroid Build Coastguard Worker element = util::make_unique<ManifestExtractor::Element>();
3081*d57664e9SAndroid Build Coastguard Worker }
3082*d57664e9SAndroid Build Coastguard Worker
3083*d57664e9SAndroid Build Coastguard Worker element->extractor_ = extractor;
3084*d57664e9SAndroid Build Coastguard Worker element->tag_ = el->name;
3085*d57664e9SAndroid Build Coastguard Worker element->Extract(el);
3086*d57664e9SAndroid Build Coastguard Worker return element;
3087*d57664e9SAndroid Build Coastguard Worker }
3088*d57664e9SAndroid Build Coastguard Worker
Visit(xml::Element * el,const std::string & parent_tag)3089*d57664e9SAndroid Build Coastguard Worker std::unique_ptr<ManifestExtractor::Element> ManifestExtractor::Visit(
3090*d57664e9SAndroid Build Coastguard Worker xml::Element* el, const std::string& parent_tag) {
3091*d57664e9SAndroid Build Coastguard Worker auto element = ManifestExtractor::Element::Inflate(this, el, parent_tag);
3092*d57664e9SAndroid Build Coastguard Worker parent_stack_.insert(parent_stack_.begin(), element.get());
3093*d57664e9SAndroid Build Coastguard Worker
3094*d57664e9SAndroid Build Coastguard Worker // Process the element and recursively visit the children
3095*d57664e9SAndroid Build Coastguard Worker for (xml::Element* child : el->GetChildElements()) {
3096*d57664e9SAndroid Build Coastguard Worker auto v = Visit(child, el->name);
3097*d57664e9SAndroid Build Coastguard Worker element->AddChild(v);
3098*d57664e9SAndroid Build Coastguard Worker }
3099*d57664e9SAndroid Build Coastguard Worker
3100*d57664e9SAndroid Build Coastguard Worker parent_stack_.erase(parent_stack_.begin());
3101*d57664e9SAndroid Build Coastguard Worker return element;
3102*d57664e9SAndroid Build Coastguard Worker }
3103*d57664e9SAndroid Build Coastguard Worker
DumpManifest(LoadedApk * apk,DumpManifestOptions & options,text::Printer * printer,android::IDiagnostics * diag)3104*d57664e9SAndroid Build Coastguard Worker int DumpManifest(LoadedApk* apk, DumpManifestOptions& options, text::Printer* printer,
3105*d57664e9SAndroid Build Coastguard Worker android::IDiagnostics* diag) {
3106*d57664e9SAndroid Build Coastguard Worker ManifestExtractor extractor(apk, options);
3107*d57664e9SAndroid Build Coastguard Worker if (!extractor.Extract(diag)) {
3108*d57664e9SAndroid Build Coastguard Worker return 1;
3109*d57664e9SAndroid Build Coastguard Worker }
3110*d57664e9SAndroid Build Coastguard Worker return extractor.Dump(printer) ? 0 : 1;
3111*d57664e9SAndroid Build Coastguard Worker }
3112*d57664e9SAndroid Build Coastguard Worker
DumpBadgingProto(LoadedApk * apk,pb::Badging * out_badging,android::IDiagnostics * diag)3113*d57664e9SAndroid Build Coastguard Worker int DumpBadgingProto(LoadedApk* apk, pb::Badging* out_badging, android::IDiagnostics* diag) {
3114*d57664e9SAndroid Build Coastguard Worker DumpManifestOptions options{/* include_meta_data= */ true,
3115*d57664e9SAndroid Build Coastguard Worker /* only_permissions= */ false};
3116*d57664e9SAndroid Build Coastguard Worker ManifestExtractor extractor(apk, options);
3117*d57664e9SAndroid Build Coastguard Worker if (!extractor.Extract(diag)) {
3118*d57664e9SAndroid Build Coastguard Worker return 1;
3119*d57664e9SAndroid Build Coastguard Worker }
3120*d57664e9SAndroid Build Coastguard Worker return extractor.DumpProto(out_badging) ? 0 : 1;
3121*d57664e9SAndroid Build Coastguard Worker }
3122*d57664e9SAndroid Build Coastguard Worker
3123*d57664e9SAndroid Build Coastguard Worker } // namespace aapt
3124