Home | History | Annotate | Download | only in dump
      1 /*
      2  * Copyright (C) 2018 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "DumpManifest.h"
     18 
     19 #include <algorithm>
     20 
     21 #include "LoadedApk.h"
     22 #include "SdkConstants.h"
     23 #include "ValueVisitor.h"
     24 #include "io/File.h"
     25 #include "io/FileStream.h"
     26 #include "process/IResourceTableConsumer.h"
     27 #include "xml/XmlDom.h"
     28 
     29 #include "androidfw/ConfigDescription.h"
     30 
     31 using ::android::base::StringPrintf;
     32 using ::android::ConfigDescription;
     33 
     34 namespace aapt {
     35 
     36 /**
     37  * These are attribute resource constants for the platform, as found in android.R.attr.
     38  */
     39 enum {
     40   LABEL_ATTR = 0x01010001,
     41   ICON_ATTR = 0x01010002,
     42   NAME_ATTR = 0x01010003,
     43   PERMISSION_ATTR = 0x01010006,
     44   EXPORTED_ATTR = 0x01010010,
     45   GRANT_URI_PERMISSIONS_ATTR = 0x0101001b,
     46   PRIORITY_ATTR = 0x0101001c,
     47   RESOURCE_ATTR = 0x01010025,
     48   DEBUGGABLE_ATTR = 0x0101000f,
     49   TARGET_PACKAGE_ATTR = 0x01010021,
     50   VALUE_ATTR = 0x01010024,
     51   VERSION_CODE_ATTR = 0x0101021b,
     52   VERSION_NAME_ATTR = 0x0101021c,
     53   SCREEN_ORIENTATION_ATTR = 0x0101001e,
     54   MIN_SDK_VERSION_ATTR = 0x0101020c,
     55   MAX_SDK_VERSION_ATTR = 0x01010271,
     56   REQ_TOUCH_SCREEN_ATTR = 0x01010227,
     57   REQ_KEYBOARD_TYPE_ATTR = 0x01010228,
     58   REQ_HARD_KEYBOARD_ATTR = 0x01010229,
     59   REQ_NAVIGATION_ATTR = 0x0101022a,
     60   REQ_FIVE_WAY_NAV_ATTR = 0x01010232,
     61   TARGET_SDK_VERSION_ATTR = 0x01010270,
     62   TEST_ONLY_ATTR = 0x01010272,
     63   ANY_DENSITY_ATTR = 0x0101026c,
     64   GL_ES_VERSION_ATTR = 0x01010281,
     65   SMALL_SCREEN_ATTR = 0x01010284,
     66   NORMAL_SCREEN_ATTR = 0x01010285,
     67   LARGE_SCREEN_ATTR = 0x01010286,
     68   XLARGE_SCREEN_ATTR = 0x010102bf,
     69   REQUIRED_ATTR = 0x0101028e,
     70   INSTALL_LOCATION_ATTR = 0x010102b7,
     71   SCREEN_SIZE_ATTR = 0x010102ca,
     72   SCREEN_DENSITY_ATTR = 0x010102cb,
     73   REQUIRES_SMALLEST_WIDTH_DP_ATTR = 0x01010364,
     74   COMPATIBLE_WIDTH_LIMIT_DP_ATTR = 0x01010365,
     75   LARGEST_WIDTH_LIMIT_DP_ATTR = 0x01010366,
     76   PUBLIC_KEY_ATTR = 0x010103a6,
     77   CATEGORY_ATTR = 0x010103e8,
     78   BANNER_ATTR = 0x10103f2,
     79   ISGAME_ATTR = 0x10103f4,
     80   VERSION_ATTR = 0x01010519,
     81   CERT_DIGEST_ATTR = 0x01010548,
     82   REQUIRED_FEATURE_ATTR = 0x01010557,
     83   REQUIRED_NOT_FEATURE_ATTR = 0x01010558,
     84   IS_STATIC_ATTR = 0x0101055a,
     85   REQUIRED_SYSTEM_PROPERTY_NAME_ATTR = 0x01010565,
     86   REQUIRED_SYSTEM_PROPERTY_VALUE_ATTR = 0x01010566,
     87   COMPILE_SDK_VERSION_ATTR = 0x01010572,
     88   COMPILE_SDK_VERSION_CODENAME_ATTR = 0x01010573,
     89   VERSION_MAJOR_ATTR = 0x01010577,
     90   PACKAGE_TYPE_ATTR = 0x01010587,
     91 };
     92 
     93 const std::string& kAndroidNamespace = "http://schemas.android.com/apk/res/android";
     94 
     95 /** Retrieves the attribute of the element with the specified attribute resource id. */
     96 static xml::Attribute* FindAttribute(xml::Element *el, uint32_t resd_id) {
     97   for (auto& a : el->attributes) {
     98     if (a.compiled_attribute && a.compiled_attribute.value().id) {
     99       if (a.compiled_attribute.value().id.value() == resd_id) {
    100         return std::move(&a);
    101       }
    102     }
    103   }
    104   return nullptr;
    105 }
    106 
    107 /** Retrieves the attribute of the element that has the specified namespace and attribute name. */
    108 static xml::Attribute* FindAttribute(xml::Element *el, const std::string &package,
    109                                      const std::string &name) {
    110   return el->FindAttribute(package, name);
    111 }
    112 
    113 class CommonFeatureGroup;
    114 
    115 class ManifestExtractor {
    116  public:
    117 
    118   explicit ManifestExtractor(LoadedApk* apk, DumpManifestOptions& options)
    119       : apk_(apk), options_(options) { }
    120 
    121   class Element {
    122    public:
    123     Element() = default;
    124     virtual ~Element() = default;
    125 
    126     static std::unique_ptr<Element> Inflate(ManifestExtractor* extractor, xml::Element* el);
    127 
    128     /** Writes out the extracted contents of the element. */
    129     virtual void Print(text::Printer* printer) { }
    130 
    131     /** Adds an element to the list of children of the element. */
    132     void AddChild(std::unique_ptr<Element>& child) { children_.push_back(std::move(child)); }
    133 
    134     /** Retrieves the list of children of the element. */
    135     const std::vector<std::unique_ptr<Element>>& children() const {
    136       return children_;
    137     }
    138 
    139     /** Retrieves the extracted xml element tag. */
    140     const std::string tag() const {
    141       return tag_;
    142     }
    143 
    144    protected:
    145     ManifestExtractor* extractor() const {
    146       return extractor_;
    147     }
    148 
    149     /** Retrieves and stores the information extracted from the xml element. */
    150     virtual void Extract(xml::Element* el) { }
    151 
    152     /*
    153      * Retrieves a configuration value of the resource entry that best matches the specified
    154      * configuration.
    155      */
    156     static Value* BestConfigValue(ResourceEntry* entry,
    157                                   const ConfigDescription& match) {
    158       if (!entry) {
    159         return nullptr;
    160       }
    161 
    162       // Determine the config that best matches the desired config
    163       ResourceConfigValue* best_value = nullptr;
    164       for (auto& value : entry->values) {
    165         if (!value->config.match(match)) {
    166           continue;
    167         }
    168 
    169         if (best_value != nullptr) {
    170           if (!value->config.isBetterThan(best_value->config, &match)) {
    171             if (value->config.compare(best_value->config) != 0) {
    172               continue;
    173             }
    174           }
    175         }
    176 
    177         best_value = value.get();
    178       }
    179 
    180       // The entry has no values
    181       if (!best_value) {
    182         return nullptr;
    183       }
    184 
    185       return best_value->value.get();
    186     }
    187 
    188     /** Retrieves the resource assigned to the specified resource id if one exists. */
    189     Value* FindValueById(const ResourceTable* table, const ResourceId& res_id,
    190                          const ConfigDescription& config = DummyConfig()) {
    191       if (table) {
    192         for (auto& package : table->packages) {
    193           if (package->id && package->id.value() == res_id.package_id()) {
    194             for (auto& type : package->types) {
    195               if (type->id && type->id.value() == res_id.type_id()) {
    196                 for (auto& entry : type->entries) {
    197                   if (entry->id && entry->id.value() == res_id.entry_id()) {
    198                     if (auto value = BestConfigValue(entry.get(), config)) {
    199                       return value;
    200                     }
    201                   }
    202                 }
    203               }
    204             }
    205           }
    206         }
    207       }
    208       return nullptr;
    209     }
    210 
    211     /** Attempts to resolve the reference to a non-reference value. */
    212     Value* ResolveReference(Reference* ref, const ConfigDescription& config = DummyConfig()) {
    213       const int kMaxIterations = 40;
    214       int i = 0;
    215       while (ref && ref->id && i++ < kMaxIterations) {
    216         auto table = extractor_->apk_->GetResourceTable();
    217         if (auto value = FindValueById(table, ref->id.value(), config)) {
    218           if (ValueCast<Reference>(value)) {
    219             ref = ValueCast<Reference>(value);
    220           } else {
    221             return value;
    222           }
    223         }
    224       }
    225       return nullptr;
    226     }
    227 
    228     /**
    229      * Retrieves the integer value of the attribute . If the value of the attribute is a reference,
    230      * this will attempt to resolve the reference to an integer value.
    231      **/
    232     int32_t* GetAttributeInteger(xml::Attribute* attr,
    233                                  const ConfigDescription& config = DummyConfig()) {
    234       if (attr != nullptr) {
    235         if (attr->compiled_value) {
    236           // Resolve references using the dummy configuration
    237           Value* value = attr->compiled_value.get();
    238           if (ValueCast<Reference>(value)) {
    239             value = ResolveReference(ValueCast<Reference>(value), config);
    240           } else {
    241             value = attr->compiled_value.get();
    242           }
    243           // Retrieve the integer data if possible
    244           if (value != nullptr) {
    245             if (BinaryPrimitive* intValue = ValueCast<BinaryPrimitive>(value)) {
    246               return (int32_t*) &intValue->value.data;
    247             }
    248           }
    249         }
    250       }
    251       return nullptr;
    252     }
    253 
    254     /**
    255      * A version of GetAttributeInteger that returns a default integer if the attribute does not
    256      * exist or cannot be resolved to an integer value.
    257      **/
    258     int32_t GetAttributeIntegerDefault(xml::Attribute* attr, int32_t def,
    259                                        const ConfigDescription& config = DummyConfig()) {
    260       auto value = GetAttributeInteger(attr, config);
    261       if (value) {
    262         return *value;
    263       }
    264       return def;
    265     }
    266 
    267     /**
    268      * Retrieves the string value of the attribute. If the value of the attribute is a reference,
    269      * this will attempt to resolve the reference to a string value.
    270      **/
    271     const std::string* GetAttributeString(xml::Attribute* attr,
    272                                           const ConfigDescription& config = DummyConfig()) {
    273       if (attr != nullptr) {
    274         if (attr->compiled_value) {
    275           // Resolve references using the dummy configuration
    276           Value* value = attr->compiled_value.get();
    277           if (ValueCast<Reference>(value)) {
    278             value = ResolveReference(ValueCast<Reference>(value), config);
    279           } else {
    280             value = attr->compiled_value.get();
    281           }
    282 
    283           // Retrieve the string data of the value if possible
    284           if (value != nullptr) {
    285             if (String* intValue = ValueCast<String>(value)) {
    286               return &(*intValue->value);
    287             } else if (RawString* rawValue = ValueCast<RawString>(value)) {
    288               return &(*rawValue->value);
    289             } else if (FileReference* strValue = ValueCast<FileReference>(value)) {
    290               return &(*strValue->path);
    291             }
    292           }
    293         }
    294         return &attr->value;
    295       }
    296       return nullptr;
    297     }
    298 
    299     /**
    300      * A version of GetAttributeString that returns a default string if the attribute does not
    301      * exist or cannot be resolved to an string value.
    302      **/
    303     std::string GetAttributeStringDefault(xml::Attribute* attr, std::string def,
    304                                           const ConfigDescription& config = DummyConfig()) {
    305       auto value = GetAttributeString(attr, config);
    306       if (value) {
    307         return *value;
    308       }
    309       return def;
    310     }
    311 
    312    private:
    313       ManifestExtractor* extractor_;
    314       std::vector<std::unique_ptr<Element>> children_;
    315       std::string tag_;
    316   };
    317 
    318   friend Element;
    319 
    320   /** Creates a default configuration used to retrieve resources. */
    321   static ConfigDescription DummyConfig() {
    322     ConfigDescription config;
    323     config.orientation = android::ResTable_config::ORIENTATION_PORT;
    324     config.density = android::ResTable_config::DENSITY_MEDIUM;
    325     config.sdkVersion = 10000; // Very high.
    326     config.screenWidthDp = 320;
    327     config.screenHeightDp = 480;
    328     config.smallestScreenWidthDp = 320;
    329     config.screenLayout |= android::ResTable_config::SCREENSIZE_NORMAL;
    330     return config;
    331   }
    332 
    333   bool Dump(text::Printer* printer, IDiagnostics* diag);
    334 
    335   /** Recursively visit the xml element tree and return a processed badging element tree. */
    336   std::unique_ptr<Element> Visit(xml::Element* element);
    337 
    338     /** Raises the target sdk value if the min target is greater than the current target. */
    339   void RaiseTargetSdk(int32_t min_target) {
    340     if (min_target > target_sdk_) {
    341       target_sdk_ = min_target;
    342     }
    343   }
    344 
    345   /**
    346    * Retrieves the default feature group that features are added into when <uses-feature>
    347    * are not in a <feature-group> element.
    348    **/
    349   CommonFeatureGroup* GetCommonFeatureGroup() {
    350     return commonFeatureGroup_.get();
    351   }
    352 
    353   /**
    354    * Retrieves a mapping of density values to Configurations for retrieving resources that would be
    355    * used for that density setting.
    356    **/
    357   const std::map<uint16_t, ConfigDescription> densities() const {
    358     return densities_;
    359   }
    360 
    361   /**
    362    * Retrieves a mapping of locale BCP 47 strings to Configurations for retrieving resources that
    363    * would be used for that locale setting.
    364    **/
    365   const std::map<std::string, ConfigDescription> locales() const {
    366     return locales_;
    367   }
    368 
    369   /** Retrieves the current stack of parent during data extraction. */
    370   const std::vector<Element*> parent_stack() const {
    371     return parent_stack_;
    372   }
    373 
    374   int32_t target_sdk() const {
    375     return target_sdk_;
    376   }
    377 
    378   LoadedApk* const apk_;
    379   DumpManifestOptions& options_;
    380 
    381  private:
    382   std::unique_ptr<CommonFeatureGroup> commonFeatureGroup_ = util::make_unique<CommonFeatureGroup>();
    383   std::map<std::string, ConfigDescription> locales_;
    384   std::map<uint16_t, ConfigDescription> densities_;
    385   std::vector<Element*> parent_stack_;
    386   int32_t target_sdk_ = 0;
    387 };
    388 
    389 template<typename T> T* ElementCast(ManifestExtractor::Element* element);
    390 
    391 /** Recurs through the children of the specified root in depth-first order. */
    392 static void ForEachChild(ManifestExtractor::Element* root,
    393                          std::function<void(ManifestExtractor::Element*)> f) {
    394   for (auto& child : root->children()) {
    395     f(child.get());
    396     ForEachChild(child.get(), f);
    397   }
    398 }
    399 
    400 /**
    401  * Checks the element and its recursive children for an element that makes the specified
    402  * conditional function return true. Returns the first element that makes the conditional function
    403  * return true.
    404  **/
    405 static ManifestExtractor::Element* FindElement(ManifestExtractor::Element* root,
    406                                               std::function<bool(ManifestExtractor::Element*)> f) {
    407   if (f(root)) {
    408     return root;
    409   }
    410   for (auto& child : root->children()) {
    411     if (auto b2 = FindElement(child.get(), f)) {
    412       return b2;
    413     }
    414   }
    415   return nullptr;
    416 }
    417 
    418 /** Represents the <manifest> elements **/
    419 class Manifest : public ManifestExtractor::Element {
    420  public:
    421   Manifest() = default;
    422   std::string package;
    423   int32_t versionCode;
    424   std::string versionName;
    425   const std::string* split = nullptr;
    426   const std::string* platformVersionName = nullptr;
    427   const std::string* platformVersionCode = nullptr;
    428   const int32_t* compilesdkVersion = nullptr;
    429   const std::string* compilesdkVersionCodename = nullptr;
    430   const int32_t* installLocation = nullptr;
    431 
    432   void Extract(xml::Element* manifest) override {
    433     package = GetAttributeStringDefault(FindAttribute(manifest, {}, "package"), "");
    434     versionCode = GetAttributeIntegerDefault(FindAttribute(manifest, VERSION_CODE_ATTR), 0);
    435     versionName = GetAttributeStringDefault(FindAttribute(manifest, VERSION_NAME_ATTR), "");
    436     split = GetAttributeString(FindAttribute(manifest, {}, "split"));
    437 
    438     // Extract the platform build info
    439     platformVersionName = GetAttributeString(FindAttribute(manifest, {},
    440                                                            "platformBuildVersionName"));
    441     platformVersionCode = GetAttributeString(FindAttribute(manifest, {},
    442                                                            "platformBuildVersionCode"));
    443 
    444     // Extract the compile sdk info
    445     compilesdkVersion = GetAttributeInteger(FindAttribute(manifest, COMPILE_SDK_VERSION_ATTR));
    446     compilesdkVersionCodename = GetAttributeString(
    447         FindAttribute(manifest, COMPILE_SDK_VERSION_CODENAME_ATTR));
    448     installLocation = GetAttributeInteger(FindAttribute(manifest, INSTALL_LOCATION_ATTR));
    449   }
    450 
    451   void Print(text::Printer* printer) override {
    452     printer->Print(StringPrintf("package: name='%s' ", package.data()));
    453     printer->Print(StringPrintf("versionCode='%s' ",
    454                                (versionCode > 0) ? std::to_string(versionCode).data() : ""));
    455     printer->Print(StringPrintf("versionName='%s'", versionName.data()));
    456 
    457     if (split) {
    458       printer->Print(StringPrintf(" split='%s'", split->data()));
    459     }
    460     if (platformVersionName) {
    461       printer->Print(StringPrintf(" platformBuildVersionName='%s'", platformVersionName->data()));
    462     }
    463     if (platformVersionCode) {
    464       printer->Print(StringPrintf(" platformBuildVersionCode='%s'", platformVersionCode->data()));
    465     }
    466     if (compilesdkVersion) {
    467       printer->Print(StringPrintf(" compileSdkVersion='%d'", *compilesdkVersion));
    468     }
    469     if (compilesdkVersionCodename) {
    470       printer->Print(StringPrintf(" compileSdkVersionCodename='%s'",
    471                                  compilesdkVersionCodename->data()));
    472     }
    473     printer->Print("\n");
    474 
    475     if (installLocation) {
    476       switch (*installLocation) {
    477         case 0:
    478           printer->Print("install-location:'auto'\n");
    479           break;
    480         case 1:
    481           printer->Print("install-location:'internalOnly'\n");
    482           break;
    483         case 2:
    484           printer->Print("install-location:'preferExternal'\n");
    485           break;
    486         default:
    487           break;
    488       }
    489     }
    490   }
    491 };
    492 
    493 /** Represents <application> elements. **/
    494 class Application : public ManifestExtractor::Element {
    495  public:
    496   Application() = default;
    497   std::string label;
    498   std::string icon;
    499   std::string banner;
    500   int32_t is_game;
    501   int32_t debuggable;
    502   int32_t test_only;
    503   bool has_multi_arch;
    504 
    505   /** Mapping from locales to app names. */
    506   std::map<std::string, std::string> locale_labels;
    507 
    508   /** Mapping from densities to app icons. */
    509   std::map<uint16_t, std::string> density_icons;
    510 
    511   void Extract(xml::Element* element) override {
    512     label = GetAttributeStringDefault(FindAttribute(element, LABEL_ATTR), "");
    513     icon = GetAttributeStringDefault(FindAttribute(element, ICON_ATTR), "");
    514     test_only = GetAttributeIntegerDefault(FindAttribute(element, TEST_ONLY_ATTR), 0);
    515     banner = GetAttributeStringDefault(FindAttribute(element, BANNER_ATTR), "");
    516     is_game = GetAttributeIntegerDefault(FindAttribute(element, ISGAME_ATTR), 0);
    517     debuggable = GetAttributeIntegerDefault(FindAttribute(element, DEBUGGABLE_ATTR), 0);
    518 
    519     // We must search by name because the multiArch flag hasn't been API
    520     // frozen yet.
    521     has_multi_arch = (GetAttributeIntegerDefault(
    522         FindAttribute(element, kAndroidNamespace, "multiArch"), 0) != 0);
    523 
    524     // Retrieve the app names for every locale the app supports
    525     auto attr = FindAttribute(element, LABEL_ATTR);
    526     for (auto& config : extractor()->locales()) {
    527       if (auto label = GetAttributeString(attr, config.second)) {
    528         if (label) {
    529           locale_labels.insert(std::make_pair(config.first, *label));
    530         }
    531       }
    532     }
    533 
    534     // Retrieve the icons for the densities the app supports
    535     attr = FindAttribute(element, ICON_ATTR);
    536     for (auto& config : extractor()->densities()) {
    537       if (auto resource = GetAttributeString(attr, config.second)) {
    538         if (resource) {
    539           density_icons.insert(std::make_pair(config.first, *resource));
    540         }
    541       }
    542     }
    543   }
    544 
    545   void Print(text::Printer* printer) override {
    546     // Print the labels for every locale
    547     for (auto p : locale_labels) {
    548       if (p.first.empty()) {
    549         printer->Print(StringPrintf("application-label:'%s'\n",
    550                                     android::ResTable::normalizeForOutput(p.second.data())
    551                                         .c_str()));
    552       } else {
    553         printer->Print(StringPrintf("application-label-%s:'%s'\n", p.first.data(),
    554                                     android::ResTable::normalizeForOutput(p.second.data())
    555                                         .c_str()));
    556       }
    557     }
    558 
    559     // Print the icon paths for every density
    560     for (auto p : density_icons) {
    561       printer->Print(StringPrintf("application-icon-%d:'%s'\n", p.first, p.second.data()));
    562     }
    563 
    564     // Print the application info
    565     printer->Print(StringPrintf("application: label='%s' ",
    566                                 android::ResTable::normalizeForOutput(label.data()).c_str()));
    567     printer->Print(StringPrintf("icon='%s'", icon.data()));
    568     if (!banner.empty()) {
    569       printer->Print(StringPrintf(" banner='%s'", banner.data()));
    570     }
    571     printer->Print("\n");
    572 
    573     if (test_only != 0) {
    574       printer->Print(StringPrintf("testOnly='%d'\n", test_only));
    575     }
    576     if (is_game != 0) {
    577       printer->Print("application-isGame\n");
    578     }
    579     if (debuggable != 0) {
    580       printer->Print("application-debuggable\n");
    581     }
    582   }
    583 };
    584 
    585 /** Represents <uses-sdk> elements. **/
    586 class UsesSdkBadging : public ManifestExtractor::Element {
    587  public:
    588   UsesSdkBadging() = default;
    589   const int32_t* min_sdk = nullptr;
    590   const std::string* min_sdk_name = nullptr;
    591   const int32_t* max_sdk = nullptr;
    592   const int32_t* target_sdk = nullptr;
    593   const std::string* target_sdk_name = nullptr;
    594 
    595   void Extract(xml::Element* element) override {
    596     min_sdk = GetAttributeInteger(FindAttribute(element, MIN_SDK_VERSION_ATTR));
    597     min_sdk_name = GetAttributeString(FindAttribute(element, MIN_SDK_VERSION_ATTR));
    598     max_sdk = GetAttributeInteger(FindAttribute(element, MAX_SDK_VERSION_ATTR));
    599     target_sdk = GetAttributeInteger(FindAttribute(element, TARGET_SDK_VERSION_ATTR));
    600     target_sdk_name = GetAttributeString(FindAttribute(element, TARGET_SDK_VERSION_ATTR));
    601 
    602     // Detect the target sdk of the element
    603     if  ((min_sdk_name && *min_sdk_name == "Donut")
    604         || (target_sdk_name && *target_sdk_name == "Donut")) {
    605       extractor()->RaiseTargetSdk(4);
    606     }
    607     if (min_sdk) {
    608       extractor()->RaiseTargetSdk(*min_sdk);
    609     }
    610     if (target_sdk) {
    611       extractor()->RaiseTargetSdk(*target_sdk);
    612     }
    613   }
    614 
    615   void Print(text::Printer* printer) override {
    616     if (min_sdk) {
    617       printer->Print(StringPrintf("sdkVersion:'%d'\n", *min_sdk));
    618     } else if (min_sdk_name) {
    619       printer->Print(StringPrintf("sdkVersion:'%s'\n", min_sdk_name->data()));
    620     }
    621     if (max_sdk) {
    622       printer->Print(StringPrintf("maxSdkVersion:'%d'\n", *max_sdk));
    623     }
    624     if (target_sdk) {
    625       printer->Print(StringPrintf("targetSdkVersion:'%d'\n", *target_sdk));
    626     } else if (target_sdk_name) {
    627       printer->Print(StringPrintf("targetSdkVersion:'%s'\n", target_sdk_name->data()));
    628     }
    629   }
    630 };
    631 
    632 /** Represents <uses-configuration> elements. **/
    633 class UsesConfiguarion : public ManifestExtractor::Element {
    634  public:
    635   UsesConfiguarion() = default;
    636   int32_t req_touch_screen = 0;
    637   int32_t req_keyboard_type = 0;
    638   int32_t req_hard_keyboard = 0;
    639   int32_t req_navigation = 0;
    640   int32_t req_five_way_nav = 0;
    641 
    642   void Extract(xml::Element* element) override {
    643     req_touch_screen = GetAttributeIntegerDefault(
    644         FindAttribute(element, REQ_TOUCH_SCREEN_ATTR), 0);
    645     req_keyboard_type = GetAttributeIntegerDefault(
    646         FindAttribute(element, REQ_KEYBOARD_TYPE_ATTR), 0);
    647     req_hard_keyboard = GetAttributeIntegerDefault(
    648         FindAttribute(element, REQ_HARD_KEYBOARD_ATTR), 0);
    649     req_navigation = GetAttributeIntegerDefault(
    650         FindAttribute(element, REQ_NAVIGATION_ATTR), 0);
    651     req_five_way_nav = GetAttributeIntegerDefault(
    652         FindAttribute(element, REQ_FIVE_WAY_NAV_ATTR), 0);
    653   }
    654 
    655   void Print(text::Printer* printer) override {
    656     printer->Print("uses-configuration:");
    657     if (req_touch_screen != 0) {
    658       printer->Print(StringPrintf(" reqTouchScreen='%d'", req_touch_screen));
    659     }
    660     if (req_keyboard_type != 0) {
    661       printer->Print(StringPrintf(" reqKeyboardType='%d'", req_keyboard_type));
    662     }
    663     if (req_hard_keyboard != 0) {
    664       printer->Print(StringPrintf(" reqHardKeyboard='%d'", req_hard_keyboard));
    665     }
    666     if (req_navigation != 0) {
    667       printer->Print(StringPrintf(" reqNavigation='%d'", req_navigation));
    668     }
    669     if (req_five_way_nav != 0) {
    670       printer->Print(StringPrintf(" reqFiveWayNav='%d'", req_five_way_nav));
    671     }
    672     printer->Print("\n");
    673   }
    674 };
    675 
    676 /** Represents <supports-screen> elements. **/
    677 class SupportsScreen : public ManifestExtractor::Element {
    678  public:
    679   SupportsScreen() = default;
    680   int32_t small_screen = 1;
    681   int32_t normal_screen = 1;
    682   int32_t large_screen  = 1;
    683   int32_t xlarge_screen = 1;
    684   int32_t any_density = 1;
    685   int32_t requires_smallest_width_dp = 0;
    686   int32_t compatible_width_limit_dp = 0;
    687   int32_t largest_width_limit_dp = 0;
    688 
    689   void Extract(xml::Element* element) override {
    690     small_screen = GetAttributeIntegerDefault(FindAttribute(element, SMALL_SCREEN_ATTR), 1);
    691     normal_screen = GetAttributeIntegerDefault(FindAttribute(element, NORMAL_SCREEN_ATTR), 1);
    692     large_screen = GetAttributeIntegerDefault(FindAttribute(element, LARGE_SCREEN_ATTR), 1);
    693     xlarge_screen = GetAttributeIntegerDefault(FindAttribute(element, XLARGE_SCREEN_ATTR), 1);
    694     any_density = GetAttributeIntegerDefault(FindAttribute(element, ANY_DENSITY_ATTR), 1);
    695 
    696     requires_smallest_width_dp = GetAttributeIntegerDefault(
    697         FindAttribute(element, REQUIRES_SMALLEST_WIDTH_DP_ATTR), 0);
    698     compatible_width_limit_dp = GetAttributeIntegerDefault(
    699         FindAttribute(element, COMPATIBLE_WIDTH_LIMIT_DP_ATTR), 0);
    700     largest_width_limit_dp = GetAttributeIntegerDefault(
    701         FindAttribute(element, LARGEST_WIDTH_LIMIT_DP_ATTR), 0);
    702 
    703     // For modern apps, if screen size buckets haven't been specified
    704     // but the new width ranges have, then infer the buckets from them.
    705     if (small_screen > 0 && normal_screen > 0 && large_screen > 0 && xlarge_screen > 0
    706         && requires_smallest_width_dp > 0) {
    707       int32_t compat_width = (compatible_width_limit_dp > 0) ? compatible_width_limit_dp
    708                                                              : requires_smallest_width_dp;
    709       small_screen = (requires_smallest_width_dp <= 240 && compat_width >= 240) ? -1 : 0;
    710       normal_screen = (requires_smallest_width_dp <= 320 && compat_width >= 320) ? -1 : 0;
    711       large_screen = (requires_smallest_width_dp <= 480 && compat_width >= 480) ? -1 : 0;
    712       xlarge_screen = (requires_smallest_width_dp <= 720 && compat_width >= 720) ? -1 : 0;
    713     }
    714   }
    715 
    716   void PrintScreens(text::Printer* printer, int32_t target_sdk) {
    717     int32_t small_screen_temp = small_screen;
    718     int32_t normal_screen_temp  = normal_screen;
    719     int32_t large_screen_temp  = large_screen;
    720     int32_t xlarge_screen_temp  = xlarge_screen;
    721     int32_t any_density_temp  = any_density;
    722 
    723     // Determine default values for any unspecified screen sizes,
    724     // based on the target SDK of the package.  As of 4 (donut)
    725     // the screen size support was introduced, so all default to
    726     // enabled.
    727     if (small_screen_temp  > 0) {
    728       small_screen_temp  = target_sdk >= 4 ? -1 : 0;
    729     }
    730     if (normal_screen_temp  > 0) {
    731       normal_screen_temp  = -1;
    732     }
    733     if (large_screen_temp  > 0) {
    734       large_screen_temp  = target_sdk >= 4 ? -1 : 0;
    735     }
    736     if (xlarge_screen_temp  > 0) {
    737       // Introduced in Gingerbread.
    738       xlarge_screen_temp  = target_sdk >= 9 ? -1 : 0;
    739     }
    740     if (any_density_temp  > 0) {
    741       any_density_temp  = (target_sdk >= 4 || requires_smallest_width_dp > 0
    742           || compatible_width_limit_dp > 0) ? -1 : 0;
    743     }
    744 
    745     // Print the formatted screen info
    746     printer->Print("supports-screens:");
    747     if (small_screen_temp  != 0) {
    748       printer->Print(" 'small'");
    749     }
    750     if (normal_screen_temp  != 0) {
    751       printer->Print(" 'normal'");
    752     }
    753     if (large_screen_temp   != 0) {
    754       printer->Print(" 'large'");
    755     }
    756     if (xlarge_screen_temp  != 0) {
    757       printer->Print(" 'xlarge'");
    758     }
    759     printer->Print("\n");
    760     printer->Print(StringPrintf("supports-any-density: '%s'\n",
    761                                 (any_density_temp ) ? "true" : "false"));
    762     if (requires_smallest_width_dp > 0) {
    763       printer->Print(StringPrintf("requires-smallest-width:'%d'\n", requires_smallest_width_dp));
    764     }
    765     if (compatible_width_limit_dp > 0) {
    766       printer->Print(StringPrintf("compatible-width-limit:'%d'\n", compatible_width_limit_dp));
    767     }
    768     if (largest_width_limit_dp > 0) {
    769       printer->Print(StringPrintf("largest-width-limit:'%d'\n", largest_width_limit_dp));
    770     }
    771   }
    772 };
    773 
    774 /** Represents <feature-group> elements. **/
    775 class FeatureGroup : public ManifestExtractor::Element {
    776  public:
    777   FeatureGroup() = default;
    778   std::string label;
    779   int32_t open_gles_version = 0;
    780 
    781   void Extract(xml::Element* element) override {
    782     label = GetAttributeStringDefault(FindAttribute(element, LABEL_ATTR), "");
    783   }
    784 
    785   virtual void PrintGroup(text::Printer* printer) {
    786     printer->Print(StringPrintf("feature-group: label='%s'\n", label.data()));
    787     if (open_gles_version > 0) {
    788       printer->Print(StringPrintf("  uses-gl-es: '0x%x'\n", open_gles_version));
    789     }
    790 
    791     for (auto feature : features_) {
    792       printer->Print(StringPrintf("  uses-feature%s: name='%s'",
    793                                  (feature.second.required ? "" : "-not-required"),
    794                                  feature.first.data()));
    795       if (feature.second.version > 0) {
    796         printer->Print(StringPrintf(" version='%d'", feature.second.version));
    797       }
    798       printer->Print("\n");
    799     }
    800   }
    801 
    802   /** Adds a feature to the feature group. */
    803   void AddFeature(const std::string& name, bool required = true, int32_t version = -1) {
    804     features_.insert(std::make_pair(name, Feature{ required, version }));
    805     if (required) {
    806       if (name == "android.hardware.camera.autofocus" ||
    807           name == "android.hardware.camera.flash") {
    808         AddFeature("android.hardware.camera", true);
    809       } else if (name == "android.hardware.location.gps" ||
    810                  name == "android.hardware.location.network") {
    811         AddFeature("android.hardware.location", true);
    812       } else if (name == "android.hardware.faketouch.multitouch") {
    813         AddFeature("android.hardware.faketouch", true);
    814       } else if (name == "android.hardware.faketouch.multitouch.distinct" ||
    815                  name == "android.hardware.faketouch.multitouch.jazzhands") {
    816         AddFeature("android.hardware.faketouch.multitouch", true);
    817         AddFeature("android.hardware.faketouch", true);
    818       } else if (name == "android.hardware.touchscreen.multitouch") {
    819         AddFeature("android.hardware.touchscreen", true);
    820       } else if (name == "android.hardware.touchscreen.multitouch.distinct" ||
    821                  name == "android.hardware.touchscreen.multitouch.jazzhands") {
    822         AddFeature("android.hardware.touchscreen.multitouch", true);
    823         AddFeature("android.hardware.touchscreen", true);
    824       } else if (name == "android.hardware.opengles.aep") {
    825         const int kOpenGLESVersion31 = 0x00030001;
    826         if (kOpenGLESVersion31 > open_gles_version) {
    827           open_gles_version = kOpenGLESVersion31;
    828         }
    829       }
    830     }
    831   }
    832 
    833   /** Returns true if the feature group has the given feature. */
    834   virtual bool HasFeature(const std::string& name) {
    835     return features_.find(name) != features_.end();
    836   }
    837 
    838   /** Merges the features of another feature group into this group. */
    839   void Merge(FeatureGroup* group) {
    840     open_gles_version = std::max(open_gles_version, group->open_gles_version);
    841     for (auto& feature : group->features_) {
    842       features_.insert(feature);
    843     }
    844   }
    845 
    846  protected:
    847   struct Feature {
    848    public:
    849     bool required = false;
    850     int32_t version = -1;
    851   };
    852 
    853   /* Mapping of feature names to their properties. */
    854   std::map<std::string, Feature> features_;
    855 };
    856 
    857 /**
    858  * Represents the default feature group for the application if no <feature-group> elements are
    859  * present in the manifest.
    860  **/
    861 class CommonFeatureGroup : public FeatureGroup {
    862  public:
    863   CommonFeatureGroup() = default;
    864   void PrintGroup(text::Printer* printer) override {
    865     FeatureGroup::PrintGroup(printer);
    866 
    867     // Also print the implied features
    868     for (auto feature : implied_features_) {
    869       if (features_.find(feature.first) == features_.end()) {
    870         const char* sdk23 = feature.second.implied_from_sdk_k23 ? "-sdk-23" : "";
    871         printer->Print(StringPrintf("  uses-feature%s: name='%s'\n", sdk23, feature.first.data()));
    872         printer->Print(StringPrintf("  uses-implied-feature%s: name='%s' reason='", sdk23,
    873                                     feature.first.data()));
    874 
    875         // Print the reasons as a sentence
    876         size_t count = 0;
    877         for (auto reason : feature.second.reasons) {
    878           printer->Print(reason);
    879           if (count + 2 < feature.second.reasons.size()) {
    880             printer->Print(", ");
    881           } else if (count + 1 < feature.second.reasons.size()) {
    882             printer->Print(", and ");
    883           }
    884           count++;
    885         }
    886         printer->Print("'\n");
    887       }
    888     }
    889   }
    890 
    891   /** Returns true if the feature group has the given feature. */
    892   bool HasFeature(const std::string& name) override {
    893     return FeatureGroup::HasFeature(name)
    894         || implied_features_.find(name) != implied_features_.end();
    895   }
    896 
    897   /** Adds a feature to a set of implied features not explicitly requested in the manifest. */
    898   void addImpliedFeature(const std::string& name, const std::string& reason, bool sdk23 = false) {
    899     auto entry = implied_features_.find(name);
    900     if (entry == implied_features_.end()) {
    901       implied_features_.insert(std::make_pair(name, ImpliedFeature(sdk23)));
    902       entry = implied_features_.find(name);
    903     }
    904 
    905     // A non-sdk 23 implied feature takes precedence.
    906     if (entry->second.implied_from_sdk_k23 && !sdk23) {
    907       entry->second.implied_from_sdk_k23 = false;
    908     }
    909 
    910     entry->second.reasons.insert(reason);
    911   }
    912 
    913   /**
    914    * Adds a feature to a set of implied features for all features that are implied by the presence
    915    * of the permission.
    916    **/
    917   void addImpliedFeaturesForPermission(int32_t targetSdk, const std::string& name, bool sdk23) {
    918     if (name == "android.permission.CAMERA") {
    919       addImpliedFeature("android.hardware.camera",
    920                         StringPrintf("requested %s permission", name.data()),
    921                         sdk23);
    922 
    923     } else if (name == "android.permission.ACCESS_FINE_LOCATION") {
    924       if (targetSdk < SDK_LOLLIPOP) {
    925         addImpliedFeature("android.hardware.location.gps",
    926                           StringPrintf("requested %s permission", name.data()),
    927                           sdk23);
    928         addImpliedFeature("android.hardware.location.gps",
    929                           StringPrintf("targetSdkVersion < %d", SDK_LOLLIPOP),
    930                           sdk23);
    931       }
    932       addImpliedFeature("android.hardware.location",
    933                         StringPrintf("requested %s permission", name.data()),
    934                         sdk23);
    935 
    936     } else if (name == "android.permission.ACCESS_COARSE_LOCATION") {
    937       if (targetSdk < SDK_LOLLIPOP) {
    938         addImpliedFeature("android.hardware.location.network",
    939                           StringPrintf("requested %s permission", name.data()),
    940                           sdk23);
    941         addImpliedFeature("android.hardware.location.network",
    942                           StringPrintf("targetSdkVersion < %d", SDK_LOLLIPOP),
    943                           sdk23);
    944       }
    945       addImpliedFeature("android.hardware.location",
    946                         StringPrintf("requested %s permission", name.data()),
    947                         sdk23);
    948 
    949     } else if (name == "android.permission.ACCESS_MOCK_LOCATION" ||
    950         name == "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" ||
    951         name == "android.permission.INSTALL_LOCATION_PROVIDER") {
    952       addImpliedFeature("android.hardware.location",
    953                         StringPrintf("requested %s permission", name.data()),
    954                         sdk23);
    955 
    956     } else if (name == "android.permission.BLUETOOTH" ||
    957         name == "android.permission.BLUETOOTH_ADMIN") {
    958       if (targetSdk > SDK_DONUT) {
    959         addImpliedFeature("android.hardware.bluetooth",
    960                           StringPrintf("requested %s permission", name.data()),
    961                           sdk23);
    962         addImpliedFeature("android.hardware.bluetooth",
    963                           StringPrintf("targetSdkVersion > %d", SDK_DONUT),
    964                           sdk23);
    965       }
    966 
    967     } else if (name == "android.permission.RECORD_AUDIO") {
    968       addImpliedFeature("android.hardware.microphone",
    969                         StringPrintf("requested %s permission", name.data()),
    970                         sdk23);
    971 
    972     } else if (name == "android.permission.ACCESS_WIFI_STATE" ||
    973         name == "android.permission.CHANGE_WIFI_STATE" ||
    974         name == "android.permission.CHANGE_WIFI_MULTICAST_STATE") {
    975       addImpliedFeature("android.hardware.wifi",
    976                         StringPrintf("requested %s permission", name.data()),
    977                         sdk23);
    978 
    979     } else if (name == "android.permission.CALL_PHONE" ||
    980         name == "android.permission.CALL_PRIVILEGED" ||
    981         name == "android.permission.MODIFY_PHONE_STATE" ||
    982         name == "android.permission.PROCESS_OUTGOING_CALLS" ||
    983         name == "android.permission.READ_SMS" ||
    984         name == "android.permission.RECEIVE_SMS" ||
    985         name == "android.permission.RECEIVE_MMS" ||
    986         name == "android.permission.RECEIVE_WAP_PUSH" ||
    987         name == "android.permission.SEND_SMS" ||
    988         name == "android.permission.WRITE_APN_SETTINGS" ||
    989         name == "android.permission.WRITE_SMS") {
    990       addImpliedFeature("android.hardware.telephony",
    991                         "requested a telephony permission",
    992                         sdk23);
    993     }
    994   }
    995 
    996  private:
    997   /**
    998    * Represents a feature that has been automatically added due to a pre-requisite or for some
    999    * other reason.
   1000    */
   1001   struct ImpliedFeature {
   1002     explicit ImpliedFeature(bool sdk23 = false) : implied_from_sdk_k23(sdk23) {}
   1003 
   1004     /** List of human-readable reasons for why this feature was implied. */
   1005     std::set<std::string> reasons;
   1006 
   1007     // Was this implied by a permission from SDK 23 (<uses-permission-sdk-23 />)
   1008     bool implied_from_sdk_k23;
   1009   };
   1010 
   1011   /* Mapping of implied feature names to their properties. */
   1012   std::map<std::string, ImpliedFeature> implied_features_;
   1013 };
   1014 
   1015 /** Represents <uses-feature> elements. **/
   1016 class UsesFeature : public ManifestExtractor::Element {
   1017  public:
   1018   UsesFeature() = default;
   1019   void Extract(xml::Element* element) override {
   1020     const std::string* name = GetAttributeString(FindAttribute(element, NAME_ATTR));
   1021     int32_t* gl = GetAttributeInteger(FindAttribute(element, GL_ES_VERSION_ATTR));
   1022     bool required = GetAttributeIntegerDefault(
   1023         FindAttribute(element, REQUIRED_ATTR), true) != 0;
   1024     int32_t version = GetAttributeIntegerDefault(
   1025         FindAttribute(element, kAndroidNamespace, "version"), 0);
   1026 
   1027     // Add the feature to the parent feature group element if one exists; otherwise, add it to the
   1028     // common feature group
   1029     FeatureGroup* feature_group = ElementCast<FeatureGroup>(extractor()->parent_stack()[0]);
   1030     if (!feature_group) {
   1031       feature_group = extractor()->GetCommonFeatureGroup();
   1032     } else {
   1033       // All features in side of <feature-group> elements are required.
   1034       required = true;
   1035     }
   1036 
   1037     if (name) {
   1038       feature_group->AddFeature(*name, required, version);
   1039     } else if (gl) {
   1040       feature_group->open_gles_version = std::max(feature_group->open_gles_version, *gl);
   1041     }
   1042   }
   1043 };
   1044 
   1045 /** Represents <uses-permission> elements. **/
   1046 class UsesPermission : public ManifestExtractor::Element {
   1047  public:
   1048   UsesPermission() = default;
   1049   std::string name;
   1050   std::string requiredFeature;
   1051   std::string requiredNotFeature;
   1052   int32_t required = true;
   1053   int32_t maxSdkVersion = -1;
   1054 
   1055   void Extract(xml::Element* element) override {
   1056     name = GetAttributeStringDefault(FindAttribute(element, NAME_ATTR), "");
   1057     requiredFeature = GetAttributeStringDefault(
   1058         FindAttribute(element, REQUIRED_FEATURE_ATTR), "");
   1059     requiredNotFeature = GetAttributeStringDefault(
   1060         FindAttribute(element, REQUIRED_NOT_FEATURE_ATTR), "");
   1061     required = GetAttributeIntegerDefault(FindAttribute(element, REQUIRED_ATTR), 1);
   1062     maxSdkVersion = GetAttributeIntegerDefault(
   1063         FindAttribute(element, MAX_SDK_VERSION_ATTR), -1);
   1064 
   1065     if (!name.empty()) {
   1066       CommonFeatureGroup* common = extractor()->GetCommonFeatureGroup();
   1067       common->addImpliedFeaturesForPermission(extractor()->target_sdk(), name, false);
   1068     }
   1069   }
   1070 
   1071   void Print(text::Printer* printer) override {
   1072     if (!name.empty()) {
   1073       printer->Print(StringPrintf("uses-permission: name='%s'", name.data()));
   1074       if (maxSdkVersion >= 0) {
   1075         printer->Print(StringPrintf(" maxSdkVersion='%d'", maxSdkVersion));
   1076       }
   1077       if (!requiredFeature.empty()) {
   1078         printer->Print(StringPrintf(" requiredFeature='%s'", requiredFeature.data()));
   1079       }
   1080       if (!requiredNotFeature.empty()) {
   1081         printer->Print(StringPrintf(" requiredNotFeature='%s'", requiredNotFeature.data()));
   1082       }
   1083       printer->Print("\n");
   1084       if (required == 0) {
   1085         printer->Print(StringPrintf("optional-permission: name='%s'", name.data()));
   1086         if (maxSdkVersion >= 0) {
   1087           printer->Print(StringPrintf(" maxSdkVersion='%d'", maxSdkVersion));
   1088         }
   1089         printer->Print("\n");
   1090       }
   1091     }
   1092   }
   1093 
   1094   void PrintImplied(text::Printer* printer, const std::string& reason) {
   1095     printer->Print(StringPrintf("uses-implied-permission: name='%s'", name.data()));
   1096     if (maxSdkVersion >= 0) {
   1097       printer->Print(StringPrintf(" maxSdkVersion='%d'", maxSdkVersion));
   1098     }
   1099     printer->Print(StringPrintf(" reason='%s'\n", reason.data()));
   1100   }
   1101 };
   1102 
   1103 /** Represents <uses-permission-sdk-23> elements. **/
   1104 class UsesPermissionSdk23 : public ManifestExtractor::Element {
   1105  public:
   1106   UsesPermissionSdk23() = default;
   1107   const std::string* name = nullptr;
   1108   const int32_t* maxSdkVersion = nullptr;
   1109 
   1110   void Extract(xml::Element* element) override {
   1111     name = GetAttributeString(FindAttribute(element, NAME_ATTR));
   1112     maxSdkVersion = GetAttributeInteger(FindAttribute(element, MAX_SDK_VERSION_ATTR));
   1113 
   1114     if (name) {
   1115       CommonFeatureGroup* common = extractor()->GetCommonFeatureGroup();
   1116       common->addImpliedFeaturesForPermission(extractor()->target_sdk(), *name, true);
   1117     }
   1118   }
   1119 
   1120   void Print(text::Printer* printer) override {
   1121     if (name) {
   1122       printer->Print(StringPrintf("uses-permission-sdk-23: name='%s'", name->data()));
   1123       if (maxSdkVersion) {
   1124         printer->Print(StringPrintf(" maxSdkVersion='%d'", *maxSdkVersion));
   1125       }
   1126       printer->Print("\n");
   1127     }
   1128   }
   1129 };
   1130 
   1131 /** Represents <permission> elements. These elements are only printing when dumping permissions. **/
   1132 class Permission : public ManifestExtractor::Element {
   1133  public:
   1134   Permission() = default;
   1135   std::string name;
   1136 
   1137   void Extract(xml::Element* element) override {
   1138     name = GetAttributeStringDefault(FindAttribute(element, NAME_ATTR), "");
   1139   }
   1140 
   1141   void Print(text::Printer* printer) override {
   1142     if (extractor()->options_.only_permissions && !name.empty()) {
   1143       printer->Print(StringPrintf("permission: %s\n", name.data()));
   1144     }
   1145   }
   1146 };
   1147 
   1148 /** Represents <activity> elements. **/
   1149 class Activity : public ManifestExtractor::Element {
   1150  public:
   1151   Activity() = default;
   1152   std::string name;
   1153   std::string icon;
   1154   std::string label;
   1155   std::string banner;
   1156 
   1157   bool has_component_ = false;
   1158   bool has_launcher_category = false;
   1159   bool has_leanback_launcher_category = false;
   1160   bool has_main_action = false;
   1161 
   1162   void Extract(xml::Element* element) override {
   1163     name = GetAttributeStringDefault(FindAttribute(element, NAME_ATTR), "");
   1164     label = GetAttributeStringDefault(FindAttribute(element, LABEL_ATTR), "");
   1165     icon = GetAttributeStringDefault(FindAttribute(element, ICON_ATTR), "");
   1166     banner = GetAttributeStringDefault(FindAttribute(element, BANNER_ATTR), "");
   1167 
   1168     // Retrieve the package name from the manifest
   1169     std::string package;
   1170     for (auto& parent : extractor()->parent_stack()) {
   1171       if (auto manifest = ElementCast<Manifest>(parent)) {
   1172         package = manifest->package;
   1173         break;
   1174       }
   1175     }
   1176 
   1177     // Fully qualify the activity name
   1178     ssize_t idx = name.find(".");
   1179     if (idx == 0) {
   1180       name = package + name;
   1181     } else if (idx < 0) {
   1182       name = package + "." + name;
   1183     }
   1184 
   1185     auto orientation = GetAttributeInteger(FindAttribute(element, SCREEN_ORIENTATION_ATTR));
   1186     if (orientation) {
   1187       CommonFeatureGroup* common = extractor()->GetCommonFeatureGroup();
   1188       int orien = *orientation;
   1189       if (orien == 0 || orien == 6 || orien == 8) {
   1190         // Requests landscape, sensorLandscape, or reverseLandscape.
   1191         common->addImpliedFeature("android.hardware.screen.landscape",
   1192                                   "one or more activities have specified a landscape orientation",
   1193                                   false);
   1194       } else if (orien == 1 || orien == 7 || orien == 9) {
   1195         // Requests portrait, sensorPortrait, or reversePortrait.
   1196         common->addImpliedFeature("android.hardware.screen.portrait",
   1197                                   "one or more activities have specified a portrait orientation",
   1198                                   false);
   1199       }
   1200     }
   1201   }
   1202 
   1203   void Print(text::Printer* printer) override {
   1204     // Print whether the activity has the HOME category and a the MAIN action
   1205     if (has_main_action && has_launcher_category) {
   1206       printer->Print("launchable-activity:");
   1207       if (!name.empty()) {
   1208         printer->Print(StringPrintf(" name='%s' ", name.data()));
   1209       }
   1210       printer->Print(StringPrintf(" label='%s' icon='%s'\n",
   1211                                   android::ResTable::normalizeForOutput(label.data()).c_str(),
   1212                                   icon.data()));
   1213     }
   1214 
   1215     // Print wether the activity has the HOME category and a the MAIN action
   1216     if (has_leanback_launcher_category) {
   1217       printer->Print("leanback-launchable-activity:");
   1218       if (!name.empty()) {
   1219         printer->Print(StringPrintf(" name='%s' ", name.data()));
   1220       }
   1221       printer->Print(StringPrintf(" label='%s' icon='%s' banner='%s'\n",
   1222                                   android::ResTable::normalizeForOutput(label.data()).c_str(),
   1223                                   icon.data(), banner.data()));
   1224     }
   1225   }
   1226 };
   1227 
   1228 /** Represents <intent-filter> elements. */
   1229 class IntentFilter : public ManifestExtractor::Element {
   1230  public:
   1231   IntentFilter() = default;
   1232 };
   1233 
   1234 /** Represents <category> elements. */
   1235 class Category : public ManifestExtractor::Element {
   1236  public:
   1237   Category() = default;
   1238   std::string component = "";
   1239 
   1240   void Extract(xml::Element* element) override {
   1241     const std::string* category = GetAttributeString(FindAttribute(element, NAME_ATTR));
   1242 
   1243     auto parent_stack = extractor()->parent_stack();
   1244     if (category && ElementCast<IntentFilter>(parent_stack[0])
   1245         && ElementCast<Activity>(parent_stack[1])) {
   1246       Activity* activity = ElementCast<Activity>(parent_stack[1]);
   1247 
   1248       if (*category == "android.intent.category.LAUNCHER") {
   1249         activity->has_launcher_category = true;
   1250       } else if (*category == "android.intent.category.LEANBACK_LAUNCHER") {
   1251         activity->has_leanback_launcher_category = true;
   1252       } else if (*category == "android.intent.category.HOME") {
   1253         component = "launcher";
   1254       }
   1255     }
   1256   }
   1257 };
   1258 
   1259 /**
   1260  * Represents <provider> elements. The elements may have an <intent-filter> which may have <action>
   1261  * elements nested within.
   1262  **/
   1263 class Provider : public ManifestExtractor::Element {
   1264  public:
   1265   Provider() = default;
   1266   bool has_required_saf_attributes = false;
   1267 
   1268   void Extract(xml::Element* element) override {
   1269     const int32_t* exported = GetAttributeInteger(FindAttribute(element, EXPORTED_ATTR));
   1270     const int32_t* grant_uri_permissions = GetAttributeInteger(
   1271         FindAttribute(element, GRANT_URI_PERMISSIONS_ATTR));
   1272     const std::string* permission = GetAttributeString(
   1273         FindAttribute(element, PERMISSION_ATTR));
   1274 
   1275     has_required_saf_attributes = ((exported && *exported != 0)
   1276         && (grant_uri_permissions && *grant_uri_permissions != 0)
   1277         && (permission && *permission == "android.permission.MANAGE_DOCUMENTS"));
   1278   }
   1279 };
   1280 
   1281 /** Represents <receiver> elements. **/
   1282 class Receiver : public ManifestExtractor::Element {
   1283  public:
   1284   Receiver() = default;
   1285   const std::string* permission = nullptr;
   1286   bool has_component = false;
   1287 
   1288   void Extract(xml::Element* element) override {
   1289     permission = GetAttributeString(FindAttribute(element, PERMISSION_ATTR));
   1290   }
   1291 };
   1292 
   1293 /**Represents <service> elements. **/
   1294 class Service : public ManifestExtractor::Element {
   1295  public:
   1296   Service() = default;
   1297   const std::string* permission = nullptr;
   1298   bool has_component = false;
   1299 
   1300   void Extract(xml::Element* element) override {
   1301     permission = GetAttributeString(FindAttribute(element, PERMISSION_ATTR));
   1302   }
   1303 };
   1304 
   1305 /** Represents <uses-library> elements. **/
   1306 class UsesLibrary : public ManifestExtractor::Element {
   1307  public:
   1308   UsesLibrary() = default;
   1309   std::string name;
   1310   int required;
   1311 
   1312   void Extract(xml::Element* element) override {
   1313     auto parent_stack = extractor()->parent_stack();
   1314     if (parent_stack.size() > 0 && ElementCast<Application>(parent_stack[0])) {
   1315       name = GetAttributeStringDefault(FindAttribute(element, NAME_ATTR), "");
   1316       required = GetAttributeIntegerDefault(FindAttribute(element, REQUIRED_ATTR), 1);
   1317     }
   1318   }
   1319 
   1320   void Print(text::Printer* printer) override {
   1321     if (!name.empty()) {
   1322       printer->Print(StringPrintf("uses-library%s:'%s'\n",
   1323                                  (required == 0) ? "-not-required" : "", name.data()));
   1324     }
   1325   }
   1326 };
   1327 
   1328 /** Represents <static-library> elements. **/
   1329 class StaticLibrary : public ManifestExtractor::Element {
   1330  public:
   1331   StaticLibrary() = default;
   1332   std::string name;
   1333   int version;
   1334   int versionMajor;
   1335 
   1336   void Extract(xml::Element* element) override {
   1337     auto parent_stack = extractor()->parent_stack();
   1338     if (parent_stack.size() > 0 && ElementCast<Application>(parent_stack[0])) {
   1339       name = GetAttributeStringDefault(FindAttribute(element, NAME_ATTR), "");
   1340       version = GetAttributeIntegerDefault(FindAttribute(element, VERSION_ATTR), 0);
   1341       versionMajor = GetAttributeIntegerDefault(FindAttribute(element, VERSION_MAJOR_ATTR), 0);
   1342     }
   1343   }
   1344 
   1345   void Print(text::Printer* printer) override {
   1346     printer->Print(StringPrintf(
   1347       "static-library: name='%s' version='%d' versionMajor='%d'\n",
   1348       name.data(), version, versionMajor));
   1349   }
   1350 };
   1351 
   1352 /** Represents <uses-static-library> elements. **/
   1353 class UsesStaticLibrary : public ManifestExtractor::Element {
   1354  public:
   1355   UsesStaticLibrary() = default;
   1356   std::string name;
   1357   int version;
   1358   int versionMajor;
   1359   std::vector<std::string> certDigests;
   1360 
   1361   void Extract(xml::Element* element) override {
   1362     auto parent_stack = extractor()->parent_stack();
   1363     if (parent_stack.size() > 0 && ElementCast<Application>(parent_stack[0])) {
   1364       name = GetAttributeStringDefault(FindAttribute(element, NAME_ATTR), "");
   1365       version = GetAttributeIntegerDefault(FindAttribute(element, VERSION_ATTR), 0);
   1366       versionMajor = GetAttributeIntegerDefault(FindAttribute(element, VERSION_MAJOR_ATTR), 0);
   1367       AddCertDigest(element);
   1368     }
   1369   }
   1370 
   1371   void AddCertDigest(xml::Element* element) {
   1372     std::string digest = GetAttributeStringDefault(FindAttribute(element, CERT_DIGEST_ATTR), "");
   1373     // We allow ":" delimiters in the SHA declaration as this is the format
   1374     // emitted by the certtool making it easy for developers to copy/paste.
   1375     digest.erase(std::remove(digest.begin(), digest.end(), ':'), digest.end());
   1376     if (!digest.empty()) {
   1377       certDigests.push_back(digest);
   1378     }
   1379   }
   1380 
   1381   void Print(text::Printer* printer) override {
   1382     printer->Print(StringPrintf(
   1383       "uses-static-library: name='%s' version='%d' versionMajor='%d'",
   1384       name.data(), version, versionMajor));
   1385     for (size_t i = 0; i < certDigests.size(); i++) {
   1386       printer->Print(StringPrintf(" certDigest='%s'", certDigests[i].data()));
   1387     }
   1388     printer->Print("\n");
   1389   }
   1390 };
   1391 
   1392 /**
   1393  * Represents <meta-data> elements. These tags are only printed when a flag is passed in to
   1394  * explicitly enable meta data printing.
   1395  **/
   1396 class MetaData : public ManifestExtractor::Element {
   1397  public:
   1398   MetaData() = default;
   1399   std::string name;
   1400   std::string value;
   1401   const int* value_int;
   1402   std::string resource;
   1403   const int* resource_int;
   1404 
   1405   void Extract(xml::Element* element) override {
   1406     name = GetAttributeStringDefault(FindAttribute(element, NAME_ATTR), "");
   1407     value = GetAttributeStringDefault(FindAttribute(element, VALUE_ATTR), "");
   1408     value_int = GetAttributeInteger(FindAttribute(element, VALUE_ATTR));
   1409     resource = GetAttributeStringDefault(FindAttribute(element, RESOURCE_ATTR), "");
   1410     resource_int = GetAttributeInteger(FindAttribute(element, RESOURCE_ATTR));
   1411   }
   1412 
   1413   void Print(text::Printer* printer) override {
   1414     if (extractor()->options_.include_meta_data && !name.empty()) {
   1415       printer->Print(StringPrintf("meta-data: name='%s' ", name.data()));
   1416       if (!value.empty()) {
   1417         printer->Print(StringPrintf("value='%s' ", value.data()));
   1418       } else if (value_int) {
   1419         printer->Print(StringPrintf("value='%d' ", *value_int));
   1420       } else {
   1421         if (!resource.empty()) {
   1422           printer->Print(StringPrintf("resource='%s' ", resource.data()));
   1423         } else if (resource_int) {
   1424           printer->Print(StringPrintf("resource='%d' ", *resource_int));
   1425         }
   1426       }
   1427       printer->Print("\n");
   1428     }
   1429   }
   1430 };
   1431 
   1432 /**
   1433  * Represents <action> elements. Detects the presence of certain activity, provider, receiver, and
   1434  * service components.
   1435  **/
   1436 class Action : public ManifestExtractor::Element {
   1437  public:
   1438   Action() = default;
   1439   std::string component = "";
   1440 
   1441   void Extract(xml::Element* element) override {
   1442     auto parent_stack = extractor()->parent_stack();
   1443     std::string action = GetAttributeStringDefault(FindAttribute(element, NAME_ATTR), "");
   1444 
   1445     if (ElementCast<IntentFilter>(parent_stack[0])) {
   1446       if (ElementCast<Activity>(parent_stack[1])) {
   1447         // Detects the presence of a particular type of activity.
   1448         Activity* activity = ElementCast<Activity>(parent_stack[1]);
   1449         auto map = std::map<std::string, std::string>({
   1450             { "android.intent.action.MAIN" , "main" },
   1451             { "android.intent.action.VIDEO_CAMERA" , "camera" },
   1452             { "android.intent.action.STILL_IMAGE_CAMERA_SECURE" , "camera-secure" },
   1453         });
   1454 
   1455         auto entry = map.find(action);
   1456         if (entry != map.end()) {
   1457           component = entry->second;
   1458           activity->has_component_ = true;
   1459         }
   1460 
   1461         if (action == "android.intent.action.MAIN") {
   1462           activity->has_main_action = true;
   1463         }
   1464 
   1465       } else if (ElementCast<Receiver>(parent_stack[1])) {
   1466         // Detects the presence of a particular type of receiver. If the action requires a
   1467         // permission, then the receiver element is checked for the permission.
   1468         Receiver* receiver = ElementCast<Receiver>(parent_stack[1]);
   1469         auto map = std::map<std::string, std::string>({
   1470             { "android.appwidget.action.APPWIDGET_UPDATE" , "app-widget" },
   1471             { "android.app.action.DEVICE_ADMIN_ENABLED" , "device-admin" },
   1472         });
   1473 
   1474         auto permissions = std::map<std::string, std::string>({
   1475             { "android.app.action.DEVICE_ADMIN_ENABLED" , "android.permission.BIND_DEVICE_ADMIN" },
   1476         });
   1477 
   1478         auto entry = map.find(action);
   1479         auto permission = permissions.find(action);
   1480         if (entry != map.end() && (permission == permissions.end()
   1481             || (receiver->permission && permission->second == *receiver->permission))) {
   1482           receiver->has_component = true;
   1483           component = entry->second;
   1484         }
   1485 
   1486       } else if (ElementCast<Service>(parent_stack[1])) {
   1487         // Detects the presence of a particular type of service. If the action requires a
   1488         // permission, then the service element is checked for the permission.
   1489         Service* service = ElementCast<Service>(parent_stack[1]);
   1490         auto map = std::map<std::string, std::string>({
   1491             { "android.view.InputMethod" , "ime" },
   1492             { "android.service.wallpaper.WallpaperService" , "wallpaper" },
   1493             { "android.accessibilityservice.AccessibilityService" , "accessibility" },
   1494             { "android.printservice.PrintService" , "print-service" },
   1495             { "android.nfc.cardemulation.action.HOST_APDU_SERVICE" , "host-apdu" },
   1496             { "android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE" , "offhost-apdu" },
   1497             { "android.service.notification.NotificationListenerService" ,"notification-listener" },
   1498             { "android.service.dreams.DreamService" , "dream" },
   1499         });
   1500 
   1501         auto permissions = std::map<std::string, std::string>({
   1502             { "android.accessibilityservice.AccessibilityService" ,
   1503               "android.permission.BIND_ACCESSIBILITY_SERVICE" },
   1504             { "android.printservice.PrintService" , "android.permission.BIND_PRINT_SERVICE" },
   1505             { "android.nfc.cardemulation.action.HOST_APDU_SERVICE" ,
   1506               "android.permission.BIND_NFC_SERVICE" },
   1507             { "android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE" ,
   1508               "android.permission.BIND_NFC_SERVICE" },
   1509             { "android.service.notification.NotificationListenerService" ,
   1510               "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" },
   1511             { "android.service.dreams.DreamService" , "android.permission.BIND_DREAM_SERVICE" },
   1512         });
   1513 
   1514         auto entry = map.find(action);
   1515         auto permission = permissions.find(action);
   1516         if (entry != map.end() && (permission == permissions.end()
   1517             || (service->permission && permission->second == *service->permission))) {
   1518           service->has_component= true;
   1519           component = entry->second;
   1520         }
   1521 
   1522       } else if (ElementCast<Provider>(parent_stack[1])) {
   1523         // Detects the presence of a particular type of receiver. If the provider requires a
   1524         // permission, then the provider element is checked for the permission.
   1525         // Detect whether this action
   1526         Provider* provider = ElementCast<Provider>(parent_stack[1]);
   1527         if (action == "android.content.action.DOCUMENTS_PROVIDER"
   1528             && provider->has_required_saf_attributes) {
   1529           component = "document-provider";
   1530         }
   1531       }
   1532     }
   1533 
   1534     // Represents a searchable interface
   1535     if (action == "android.intent.action.SEARCH") {
   1536       component = "search";
   1537     }
   1538   }
   1539 };
   1540 
   1541 /**
   1542  * Represents <supports-input> elements. The element may have <input-type> elements nested within.
   1543  **/
   1544 class SupportsInput : public ManifestExtractor::Element {
   1545  public:
   1546   SupportsInput() = default;
   1547   std::vector<std::string> inputs;
   1548 
   1549   void Print(text::Printer* printer) override {
   1550     const size_t size = inputs.size();
   1551     if (size > 0) {
   1552       printer->Print("supports-input: '");
   1553       for (size_t i = 0; i < size; i++) {
   1554         printer->Print(StringPrintf("value='%s' ", inputs[i].data()));
   1555       }
   1556       printer->Print("\n");
   1557     }
   1558   }
   1559 };
   1560 
   1561 /** Represents <input-type> elements. **/
   1562 class InputType : public ManifestExtractor::Element {
   1563  public:
   1564   InputType() = default;
   1565   void Extract(xml::Element* element) override {
   1566     auto name = GetAttributeString(FindAttribute(element, NAME_ATTR));
   1567     auto parent_stack = extractor()->parent_stack();
   1568 
   1569     // Add the input to the set of supported inputs
   1570     if (name && ElementCast<SupportsInput>(parent_stack[0])) {
   1571       SupportsInput* supports = ElementCast<SupportsInput>(parent_stack[0]);
   1572       supports->inputs.push_back(*name);
   1573     }
   1574   }
   1575 };
   1576 
   1577 /** Represents <original-package> elements. **/
   1578 class OriginalPackage : public ManifestExtractor::Element {
   1579  public:
   1580   OriginalPackage() = default;
   1581   const std::string* name = nullptr;
   1582 
   1583   void Extract(xml::Element* element) override {
   1584     name = GetAttributeString(FindAttribute(element, NAME_ATTR));
   1585   }
   1586 
   1587   void Print(text::Printer* printer) override {
   1588     if (name) {
   1589       printer->Print(StringPrintf("original-package:'%s'\n", name->data()));
   1590     }
   1591   }
   1592 };
   1593 
   1594 
   1595 /** Represents <overlay> elements. **/
   1596 class Overlay : public ManifestExtractor::Element {
   1597  public:
   1598   Overlay() = default;
   1599   const std::string* target_package = nullptr;
   1600   int priority;
   1601   bool is_static;
   1602   const std::string* required_property_name = nullptr;
   1603   const std::string* required_property_value = nullptr;
   1604 
   1605   void Extract(xml::Element* element) override {
   1606     target_package = GetAttributeString(FindAttribute(element, TARGET_PACKAGE_ATTR));
   1607     priority = GetAttributeIntegerDefault(FindAttribute(element, PRIORITY_ATTR), 0);
   1608     is_static = GetAttributeIntegerDefault(FindAttribute(element, IS_STATIC_ATTR), false) != 0;
   1609     required_property_name = GetAttributeString(
   1610         FindAttribute(element, REQUIRED_SYSTEM_PROPERTY_NAME_ATTR));
   1611     required_property_value = GetAttributeString(
   1612         FindAttribute(element, REQUIRED_SYSTEM_PROPERTY_VALUE_ATTR));
   1613   }
   1614 
   1615   void Print(text::Printer* printer) override {
   1616     printer->Print(StringPrintf("overlay:"));
   1617     if (target_package) {
   1618       printer->Print(StringPrintf(" targetPackage='%s'", target_package->c_str()));
   1619     }
   1620     printer->Print(StringPrintf(" priority='%d'", priority));
   1621     printer->Print(StringPrintf(" isStatic='%s'", is_static ? "true" : "false"));
   1622     if (required_property_name) {
   1623       printer->Print(StringPrintf(" requiredPropertyName='%s'", required_property_name->c_str()));
   1624     }
   1625     if (required_property_value) {
   1626       printer->Print(StringPrintf(" requiredPropertyValue='%s'", required_property_value->c_str()));
   1627     }
   1628     printer->Print("\n");
   1629   }
   1630 };
   1631 
   1632 /** * Represents <package-verifier> elements. **/
   1633 class PackageVerifier : public ManifestExtractor::Element {
   1634  public:
   1635   PackageVerifier() = default;
   1636   const std::string* name = nullptr;
   1637   const std::string* public_key = nullptr;
   1638 
   1639   void Extract(xml::Element* element) override {
   1640     name = GetAttributeString(FindAttribute(element, NAME_ATTR));
   1641     public_key = GetAttributeString(FindAttribute(element, PUBLIC_KEY_ATTR));
   1642   }
   1643 
   1644   void Print(text::Printer* printer) override {
   1645     if (name && public_key) {
   1646       printer->Print(StringPrintf("package-verifier: name='%s' publicKey='%s'\n",
   1647                                  name->data(), public_key->data()));
   1648     }
   1649   }
   1650 };
   1651 
   1652 /** Represents <uses-package> elements. **/
   1653 class UsesPackage : public ManifestExtractor::Element {
   1654  public:
   1655   UsesPackage() = default;
   1656   const std::string* packageType = nullptr;
   1657   const std::string* name = nullptr;
   1658   int version;
   1659   int versionMajor;
   1660   std::vector<std::string> certDigests;
   1661 
   1662   void Extract(xml::Element* element) override {
   1663     auto parent_stack = extractor()->parent_stack();
   1664     if (parent_stack.size() > 0 && ElementCast<Application>(parent_stack[0])) {
   1665       packageType = GetAttributeString(FindAttribute(element, PACKAGE_TYPE_ATTR));
   1666       name = GetAttributeString(FindAttribute(element, NAME_ATTR));
   1667       version = GetAttributeIntegerDefault(FindAttribute(element, VERSION_ATTR), 0);
   1668       versionMajor = GetAttributeIntegerDefault(FindAttribute(element, VERSION_MAJOR_ATTR), 0);
   1669       AddCertDigest(element);
   1670     }
   1671   }
   1672 
   1673   void AddCertDigest(xml::Element* element) {
   1674     std::string digest = GetAttributeStringDefault(FindAttribute(element, CERT_DIGEST_ATTR), "");
   1675     // We allow ":" delimiters in the SHA declaration as this is the format
   1676     // emitted by the certtool making it easy for developers to copy/paste.
   1677     digest.erase(std::remove(digest.begin(), digest.end(), ':'), digest.end());
   1678     if (!digest.empty()) {
   1679       certDigests.push_back(digest);
   1680     }
   1681   }
   1682 
   1683   void Print(text::Printer* printer) override {
   1684     if (name) {
   1685       if (packageType) {
   1686         printer->Print(StringPrintf(
   1687           "uses-typed-package: type='%s' name='%s' version='%d' versionMajor='%d'",
   1688           packageType->data(), name->data(), version, versionMajor));
   1689         for (size_t i = 0; i < certDigests.size(); i++) {
   1690           printer->Print(StringPrintf(" certDigest='%s'", certDigests[i].data()));
   1691         }
   1692         printer->Print("\n");
   1693       } else {
   1694         printer->Print(StringPrintf("uses-package:'%s'\n", name->data()));
   1695       }
   1696     }
   1697   }
   1698 };
   1699 
   1700 /** Represents <additional-certificate> elements. **/
   1701 class AdditionalCertificate : public ManifestExtractor::Element {
   1702  public:
   1703   AdditionalCertificate() = default;
   1704 
   1705   void Extract(xml::Element* element) override {
   1706     auto parent_stack = extractor()->parent_stack();
   1707     if (parent_stack.size() > 0) {
   1708       if (ElementCast<UsesPackage>(parent_stack[0])) {
   1709         UsesPackage* uses = ElementCast<UsesPackage>(parent_stack[0]);
   1710         uses->AddCertDigest(element);
   1711       } else if (ElementCast<UsesStaticLibrary>(parent_stack[0])) {
   1712         UsesStaticLibrary* uses = ElementCast<UsesStaticLibrary>(parent_stack[0]);
   1713         uses->AddCertDigest(element);
   1714       }
   1715     }
   1716   }
   1717 };
   1718 
   1719 /** Represents <screen> elements found in <compatible-screens> elements. */
   1720 class Screen : public ManifestExtractor::Element {
   1721  public:
   1722   Screen() = default;
   1723   const int32_t* size = nullptr;
   1724   const int32_t* density = nullptr;
   1725 
   1726   void Extract(xml::Element* element) override {
   1727     size = GetAttributeInteger(FindAttribute(element, SCREEN_SIZE_ATTR));
   1728     density = GetAttributeInteger(FindAttribute(element, SCREEN_DENSITY_ATTR));
   1729   }
   1730 };
   1731 
   1732 /**
   1733  * Represents <compatible-screens> elements. These elements have <screen> elements nested within
   1734  * that each denote a supported screen size and screen density.
   1735  **/
   1736 class CompatibleScreens : public ManifestExtractor::Element {
   1737  public:
   1738   CompatibleScreens() = default;
   1739   void Print(text::Printer* printer) override {
   1740     printer->Print("compatible-screens:");
   1741 
   1742     bool first = true;
   1743     ForEachChild(this, [&printer, &first](ManifestExtractor::Element* el){
   1744       if (auto screen = ElementCast<Screen>(el)) {
   1745         if (first) {
   1746           first = false;
   1747         } else {
   1748           printer->Print(",");
   1749         }
   1750 
   1751         if (screen->size && screen->density) {
   1752           printer->Print(StringPrintf("'%d/%d'", *screen->size, *screen->density));
   1753         }
   1754       }
   1755     });
   1756     printer->Print("\n");
   1757   }
   1758 };
   1759 
   1760 /** Represents <supports-gl-texture> elements. **/
   1761 class SupportsGlTexture : public ManifestExtractor::Element {
   1762  public:
   1763   SupportsGlTexture() = default;
   1764   const std::string* name = nullptr;
   1765 
   1766   void Extract(xml::Element* element) override {
   1767     name = GetAttributeString(FindAttribute(element, NAME_ATTR));
   1768   }
   1769 
   1770   void Print(text::Printer* printer) override {
   1771     if (name) {
   1772       printer->Print(StringPrintf("supports-gl-texture:'%s'\n", name->data()));
   1773     }
   1774   }
   1775 };
   1776 
   1777 /** Recursively prints the extracted badging element. */
   1778 static void Print(ManifestExtractor::Element* el, text::Printer* printer) {
   1779   el->Print(printer);
   1780   for (auto &child : el->children()) {
   1781     Print(child.get(), printer);
   1782   }
   1783 }
   1784 
   1785 bool ManifestExtractor::Dump(text::Printer* printer, IDiagnostics* diag) {
   1786   // Load the manifest
   1787   std::unique_ptr<xml::XmlResource> doc = apk_->LoadXml("AndroidManifest.xml", diag);
   1788   if (doc == nullptr) {
   1789     diag->Error(DiagMessage() << "failed to find AndroidManifest.xml");
   1790     return false;
   1791   }
   1792 
   1793   xml::Element* element = doc->root.get();
   1794   if (element->name != "manifest") {
   1795     diag->Error(DiagMessage() << "manifest does not start with <manifest> tag");
   1796     return false;
   1797   }
   1798 
   1799   // Print only the <uses-permission>, <uses-permission-sdk23>, and <permission> elements if
   1800   // printing only permission elements is requested
   1801   if (options_.only_permissions) {
   1802     std::unique_ptr<ManifestExtractor::Element> manifest_element =
   1803         ManifestExtractor::Element::Inflate(this, element);
   1804 
   1805     if (auto manifest = ElementCast<Manifest>(manifest_element.get())) {
   1806       for (xml::Element* child : element->GetChildElements()) {
   1807         if (child->name == "uses-permission" || child->name == "uses-permission-sdk-23"
   1808             || child->name == "permission") {
   1809           auto permission_element = ManifestExtractor::Element::Inflate(this, child);
   1810           manifest->AddChild(permission_element);
   1811         }
   1812       }
   1813 
   1814       printer->Print(StringPrintf("package: %s\n", manifest->package.data()));
   1815       ForEachChild(manifest, [&printer](ManifestExtractor::Element* el) -> void {
   1816         el->Print(printer);
   1817       });
   1818 
   1819       return true;
   1820     }
   1821 
   1822     return false;
   1823   }
   1824 
   1825   // Collect information about the resource configurations
   1826   if (apk_->GetResourceTable()) {
   1827     for (auto &package : apk_->GetResourceTable()->packages) {
   1828       for (auto &type : package->types) {
   1829         for (auto &entry : type->entries) {
   1830           for (auto &value : entry->values) {
   1831             std::string locale_str = value->config.GetBcp47LanguageTag();
   1832 
   1833             // Collect all the unique locales of the apk
   1834             if (locales_.find(locale_str) == locales_.end()) {
   1835               ConfigDescription config = ManifestExtractor::DummyConfig();
   1836               config.setBcp47Locale(locale_str.data());
   1837               locales_.insert(std::make_pair(locale_str, config));
   1838             }
   1839 
   1840             // Collect all the unique density of the apk
   1841             uint16_t density = (value->config.density == 0) ? (uint16_t) 160
   1842                                                             : value->config.density;
   1843             if (densities_.find(density) == densities_.end()) {
   1844               ConfigDescription config = ManifestExtractor::DummyConfig();
   1845               config.density = density;
   1846               densities_.insert(std::make_pair(density, config));
   1847             }
   1848           }
   1849         }
   1850       }
   1851     }
   1852   }
   1853 
   1854   // Extract badging information
   1855   auto root = Visit(element);
   1856 
   1857   // Print the elements in order seen
   1858   Print(root.get(), printer);
   1859 
   1860   /** Recursively checks the extracted elements for the specified permission. **/
   1861   auto FindPermission = [&](ManifestExtractor::Element* root,
   1862                             const std::string& name) -> ManifestExtractor::Element* {
   1863     return FindElement(root, [&](ManifestExtractor::Element* el) -> bool {
   1864       if (UsesPermission* permission = ElementCast<UsesPermission>(el)) {
   1865         return permission->name == name;
   1866       }
   1867       return false;
   1868     });
   1869   };
   1870 
   1871   auto PrintPermission = [&printer](const std::string& name, const std::string& reason,
   1872                                     int32_t max_sdk_version) -> void {
   1873     auto permission = util::make_unique<UsesPermission>();
   1874     permission->name = name;
   1875     permission->maxSdkVersion = max_sdk_version;
   1876     permission->Print(printer);
   1877     permission->PrintImplied(printer, reason);
   1878   };
   1879 
   1880   // Implied permissions
   1881   // Pre-1.6 implicitly granted permission compatibility logic
   1882   CommonFeatureGroup* common_feature_group = GetCommonFeatureGroup();
   1883   bool insert_write_external = false;
   1884   auto write_external_permission = ElementCast<UsesPermission>(
   1885       FindPermission(root.get(), "android.permission.WRITE_EXTERNAL_STORAGE"));
   1886 
   1887   if (target_sdk() < 4) {
   1888     if (!write_external_permission) {
   1889       PrintPermission("android.permission.WRITE_EXTERNAL_STORAGE", "targetSdkVersion < 4", -1);
   1890       insert_write_external = true;
   1891     }
   1892 
   1893     if (!FindPermission(root.get(), "android.permission.READ_PHONE_STATE")) {
   1894       PrintPermission("android.permission.READ_PHONE_STATE", "targetSdkVersion < 4", -1);
   1895     }
   1896   }
   1897 
   1898   // If the application has requested WRITE_EXTERNAL_STORAGE, we will
   1899   // force them to always take READ_EXTERNAL_STORAGE as well.  We always
   1900   // do this (regardless of target API version) because we can't have
   1901   // an app with write permission but not read permission.
   1902   auto read_external = FindPermission(root.get(), "android.permission.READ_EXTERNAL_STORAGE");
   1903   if (!read_external && (insert_write_external || write_external_permission)) {
   1904     PrintPermission("android.permission.READ_EXTERNAL_STORAGE",
   1905                     "requested WRITE_EXTERNAL_STORAGE",
   1906                     (write_external_permission) ? write_external_permission->maxSdkVersion : -1);
   1907   }
   1908 
   1909   // Pre-JellyBean call log permission compatibility.
   1910   if (target_sdk() < 16) {
   1911     if (!FindPermission(root.get(), "android.permission.READ_CALL_LOG")
   1912         && FindPermission(root.get(), "android.permission.READ_CONTACTS")) {
   1913       PrintPermission("android.permission.READ_CALL_LOG",
   1914                       "targetSdkVersion < 16 and requested READ_CONTACTS", -1);
   1915     }
   1916 
   1917     if (!FindPermission(root.get(), "android.permission.WRITE_CALL_LOG")
   1918         && FindPermission(root.get(), "android.permission.WRITE_CONTACTS")) {
   1919       PrintPermission("android.permission.WRITE_CALL_LOG",
   1920                       "targetSdkVersion < 16 and requested WRITE_CONTACTS", -1);
   1921     }
   1922   }
   1923 
   1924   // If the app hasn't declared the touchscreen as a feature requirement (either
   1925   // directly or implied, required or not), then the faketouch feature is implied.
   1926   if (!common_feature_group->HasFeature("android.hardware.touchscreen")) {
   1927     common_feature_group->addImpliedFeature("android.hardware.faketouch",
   1928                                             "default feature for all apps", false);
   1929   }
   1930 
   1931   // Only print the common feature group if no feature group is defined
   1932   std::vector<FeatureGroup*> feature_groups;
   1933   ForEachChild(root.get(), [&feature_groups](ManifestExtractor::Element* el) -> void {
   1934     if (auto feature_group = ElementCast<FeatureGroup>(el)) {
   1935       feature_groups.push_back(feature_group);
   1936     }
   1937   });
   1938 
   1939   if (feature_groups.empty()) {
   1940     common_feature_group->PrintGroup(printer);
   1941   } else {
   1942     // Merge the common feature group into the feature group
   1943     for (auto& feature_group : feature_groups) {
   1944       feature_group->open_gles_version  = std::max(feature_group->open_gles_version,
   1945                                                    common_feature_group->open_gles_version);
   1946       feature_group->Merge(common_feature_group);
   1947       feature_group->PrintGroup(printer);
   1948     }
   1949   };
   1950 
   1951   // Collect the component types of the application
   1952   std::set<std::string> components;
   1953   ForEachChild(root.get(), [&components](ManifestExtractor::Element* el) -> void {
   1954     if (ElementCast<Action>(el)) {
   1955       auto action = ElementCast<Action>(el);
   1956       if (!action->component.empty()) {
   1957         components.insert(action->component);
   1958         return;
   1959       }
   1960     }
   1961 
   1962     if (ElementCast<Category>(el)) {
   1963       auto category = ElementCast<Category>(el);
   1964       if (!category->component.empty()) {
   1965         components.insert(category->component);
   1966         return;
   1967       }
   1968     }
   1969   });
   1970 
   1971   // Check for the payment component
   1972   auto apk = apk_;
   1973   ForEachChild(root.get(), [&apk, &components, &diag](ManifestExtractor::Element* el) -> void {
   1974     if (auto service = ElementCast<Service>(el)) {
   1975       auto host_apdu_action = ElementCast<Action>(FindElement(service,
   1976         [&](ManifestExtractor::Element* el) -> bool {
   1977           if (auto action = ElementCast<Action>(el)) {
   1978             return (action->component == "host-apdu");
   1979           }
   1980           return false;
   1981       }));
   1982 
   1983       auto offhost_apdu_action = ElementCast<Action>(FindElement(service,
   1984         [&](ManifestExtractor::Element* el) -> bool {
   1985            if (auto action = ElementCast<Action>(el)) {
   1986              return (action->component == "offhost-apdu");
   1987            }
   1988            return false;
   1989       }));
   1990 
   1991       ForEachChild(service, [&apk, &components, &diag, &host_apdu_action,
   1992           &offhost_apdu_action](ManifestExtractor::Element* el) -> void {
   1993         if (auto meta_data = ElementCast<MetaData>(el)) {
   1994           if ((meta_data->name == "android.nfc.cardemulation.host_apdu_service" && host_apdu_action)
   1995               || (meta_data->name == "android.nfc.cardemulation.off_host_apdu_service"
   1996                   && offhost_apdu_action)) {
   1997 
   1998             // Attempt to load the resource file
   1999             if (!meta_data->resource.empty()) {
   2000               return;
   2001             }
   2002             auto resource = apk->LoadXml(meta_data->resource, diag);
   2003             if (!resource) {
   2004               return;
   2005             }
   2006 
   2007             // Look for the payment category on an <aid-group> element
   2008             auto& root = resource.get()->root;
   2009             if ((host_apdu_action && root->name == "host-apdu-service")
   2010                 || (offhost_apdu_action && root->name == "offhost-apdu-service")) {
   2011 
   2012               for (auto& child : root->GetChildElements()) {
   2013                 if (child->name == "aid-group") {
   2014                   auto category = FindAttribute(child, CATEGORY_ATTR);
   2015                   if (category && category->value == "payment") {
   2016                     components.insert("payment");
   2017                     return;
   2018                   }
   2019                 }
   2020               }
   2021             }
   2022           }
   2023         }
   2024       });
   2025     }
   2026   });
   2027 
   2028   // Print the components types if they are present
   2029   auto PrintComponent = [&components, &printer](const std::string& component) -> void {
   2030     if (components.find(component) != components.end()) {
   2031       printer->Print(StringPrintf("provides-component:'%s'\n", component.data()));
   2032     }
   2033   };
   2034 
   2035   PrintComponent("app-widget");
   2036   PrintComponent("device-admin");
   2037   PrintComponent("ime");
   2038   PrintComponent("wallpaper");
   2039   PrintComponent("accessibility");
   2040   PrintComponent("print-service");
   2041   PrintComponent("payment");
   2042   PrintComponent("search");
   2043   PrintComponent("document-provider");
   2044   PrintComponent("launcher");
   2045   PrintComponent("notification-listener");
   2046   PrintComponent("dream");
   2047   PrintComponent("camera");
   2048   PrintComponent("camera-secure");
   2049 
   2050   // Print presence of main activity
   2051   if (components.find("main") != components.end()) {
   2052     printer->Print("main\n");
   2053   }
   2054 
   2055   // Print presence of activities, recivers, and services with no special components
   2056   FindElement(root.get(), [&printer](ManifestExtractor::Element* el) -> bool {
   2057     if (auto activity = ElementCast<Activity>(el)) {
   2058       if (!activity->has_component_) {
   2059         printer->Print("other-activities\n");
   2060         return true;
   2061       }
   2062     }
   2063     return false;
   2064   });
   2065 
   2066   FindElement(root.get(), [&printer](ManifestExtractor::Element* el) -> bool {
   2067     if (auto receiver = ElementCast<Receiver>(el)) {
   2068       if (!receiver->has_component) {
   2069         printer->Print("other-receivers\n");
   2070         return true;
   2071       }
   2072     }
   2073     return false;
   2074   });
   2075 
   2076   FindElement(root.get(), [&printer](ManifestExtractor::Element* el) -> bool {
   2077     if (auto service = ElementCast<Service>(el)) {
   2078       if (!service->has_component) {
   2079         printer->Print("other-services\n");
   2080         return true;
   2081       }
   2082     }
   2083     return false;
   2084   });
   2085 
   2086   // Print the supported screens
   2087   SupportsScreen* screen = ElementCast<SupportsScreen>(FindElement(root.get(),
   2088       [&](ManifestExtractor::Element* el) -> bool {
   2089     return ElementCast<SupportsScreen>(el) != nullptr;
   2090   }));
   2091 
   2092   if (screen) {
   2093     screen->PrintScreens(printer, target_sdk_);
   2094   } else {
   2095     // Print the default supported screens
   2096     SupportsScreen default_screens;
   2097     default_screens.PrintScreens(printer, target_sdk_);
   2098   }
   2099 
   2100   // Print all the unique locales of the apk
   2101   printer->Print("locales:");
   2102   for (auto& config : locales_) {
   2103     if (config.first.empty()) {
   2104       printer->Print(" '--_--'");
   2105     } else {
   2106       printer->Print(StringPrintf(" '%s'", config.first.data()));
   2107     }
   2108   }
   2109   printer->Print("\n");
   2110 
   2111   // Print all the densities locales of the apk
   2112   printer->Print("densities:");
   2113   for (auto& config : densities_) {
   2114     printer->Print(StringPrintf(" '%d'", config.first));
   2115   }
   2116   printer->Print("\n");
   2117 
   2118   // Print the supported architectures of the app
   2119   std::set<std::string> architectures;
   2120   auto it = apk_->GetFileCollection()->Iterator();
   2121   while (it->HasNext()) {
   2122     auto file_path = it->Next()->GetSource().path;
   2123 
   2124 
   2125     size_t pos = file_path.find("lib/");
   2126     if (pos != std::string::npos) {
   2127       file_path = file_path.substr(pos + 4);
   2128       pos = file_path.find("/");
   2129       if (pos != std::string::npos) {
   2130         file_path = file_path.substr(0, pos);
   2131       }
   2132 
   2133       architectures.insert(file_path);
   2134     }
   2135   }
   2136 
   2137   // Determine if the application has multiArch supports
   2138   auto has_multi_arch = FindElement(root.get(), [&](ManifestExtractor::Element* el) -> bool {
   2139     if (auto application = ElementCast<Application>(el)) {
   2140       return application->has_multi_arch;
   2141     }
   2142     return false;
   2143   });
   2144 
   2145   bool output_alt_native_code = false;
   2146   // A multiArch package is one that contains 64-bit and
   2147   // 32-bit versions of native code and expects 3rd-party
   2148   // apps to load these native code libraries. Since most
   2149   // 64-bit systems also support 32-bit apps, the apps
   2150   // loading this multiArch package's code may be either
   2151   if (has_multi_arch) {
   2152     // If this is a multiArch package, report the 64-bit
   2153     // version only. Then as a separate entry, report the
   2154     // rest.
   2155     //
   2156     // If we report the 32-bit architecture, this APK will
   2157     // be installed on a 32-bit device, causing a large waste
   2158     // of bandwidth and disk space. This assumes that
   2159     // the developer of the multiArch package has also
   2160     // made a version that is 32-bit only.
   2161     const std::string kIntel64 = "x86_64";
   2162     const std::string kArm64 = "arm64-v8a";
   2163 
   2164     auto arch = architectures.find(kIntel64);
   2165     if (arch == architectures.end()) {
   2166       arch = architectures.find(kArm64);
   2167     }
   2168 
   2169     if (arch != architectures.end()) {
   2170       printer->Print(StringPrintf("native-code: '%s'\n", arch->data()));
   2171       architectures.erase(arch);
   2172       output_alt_native_code = true;
   2173     }
   2174   }
   2175 
   2176   if (architectures.size() > 0) {
   2177     if (output_alt_native_code) {
   2178       printer->Print("alt-");
   2179     }
   2180     printer->Print("native-code:");
   2181     for (auto& arch : architectures) {
   2182       printer->Print(StringPrintf(" '%s'", arch.data()));
   2183     }
   2184     printer->Print("\n");
   2185   }
   2186 
   2187   return true;
   2188 }
   2189 
   2190 /**
   2191  * Returns the element casted to the type if the element is of that type. Otherwise, returns a null
   2192  * pointer.
   2193  **/
   2194 template<typename T>
   2195 T* ElementCast(ManifestExtractor::Element* element) {
   2196   if (element == nullptr) {
   2197     return nullptr;
   2198   }
   2199 
   2200   const std::unordered_map<std::string, bool> kTagCheck = {
   2201     {"action", std::is_base_of<Action, T>::value},
   2202     {"activity", std::is_base_of<Activity, T>::value},
   2203     {"application", std::is_base_of<Application, T>::value},
   2204     {"category", std::is_base_of<Category, T>::value},
   2205     {"compatible-screens", std::is_base_of<CompatibleScreens, T>::value},
   2206     {"feature-group", std::is_base_of<FeatureGroup, T>::value},
   2207     {"input-type", std::is_base_of<InputType, T>::value},
   2208     {"intent-filter", std::is_base_of<IntentFilter, T>::value},
   2209     {"meta-data", std::is_base_of<MetaData, T>::value},
   2210     {"manifest", std::is_base_of<Manifest, T>::value},
   2211     {"original-package", std::is_base_of<OriginalPackage, T>::value},
   2212     {"overlay", std::is_base_of<Overlay, T>::value},
   2213     {"package-verifier", std::is_base_of<PackageVerifier, T>::value},
   2214     {"permission", std::is_base_of<Permission, T>::value},
   2215     {"provider", std::is_base_of<Provider, T>::value},
   2216     {"receiver", std::is_base_of<Receiver, T>::value},
   2217     {"screen", std::is_base_of<Screen, T>::value},
   2218     {"service", std::is_base_of<Service, T>::value},
   2219     {"supports-gl-texture", std::is_base_of<SupportsGlTexture, T>::value},
   2220     {"supports-input", std::is_base_of<SupportsInput, T>::value},
   2221     {"supports-screens", std::is_base_of<SupportsScreen, T>::value},
   2222     {"uses-configuration", std::is_base_of<UsesConfiguarion, T>::value},
   2223     {"uses-feature", std::is_base_of<UsesFeature, T>::value},
   2224     {"uses-permission", std::is_base_of<UsesPermission, T>::value},
   2225     {"uses-permission-sdk-23", std::is_base_of<UsesPermissionSdk23, T>::value},
   2226     {"uses-library", std::is_base_of<UsesLibrary, T>::value},
   2227     {"uses-package", std::is_base_of<UsesPackage, T>::value},
   2228     {"static-library", std::is_base_of<StaticLibrary, T>::value},
   2229     {"uses-static-library", std::is_base_of<UsesStaticLibrary, T>::value},
   2230     {"additional-certificate", std::is_base_of<AdditionalCertificate, T>::value},
   2231     {"uses-sdk", std::is_base_of<UsesSdkBadging, T>::value},
   2232   };
   2233 
   2234   auto check = kTagCheck.find(element->tag());
   2235   if (check != kTagCheck.end() && check->second) {
   2236     return static_cast<T*>(element);
   2237   }
   2238   return nullptr;
   2239 }
   2240 
   2241 template<typename T>
   2242 std::unique_ptr<T> CreateType() {
   2243   return std::move(util::make_unique<T>());
   2244 }
   2245 
   2246 std::unique_ptr<ManifestExtractor::Element> ManifestExtractor::Element::Inflate(
   2247     ManifestExtractor* extractor, xml::Element* el) {
   2248   const std::unordered_map<std::string,
   2249                            std::function<std::unique_ptr<ManifestExtractor::Element>()>>
   2250       kTagCheck = {
   2251     {"action", &CreateType<Action>},
   2252     {"activity", &CreateType<Activity>},
   2253     {"application", &CreateType<Application>},
   2254     {"category", &CreateType<Category>},
   2255     {"compatible-screens", &CreateType<CompatibleScreens>},
   2256     {"feature-group", &CreateType<FeatureGroup>},
   2257     {"input-type", &CreateType<InputType>},
   2258     {"intent-filter",&CreateType<IntentFilter>},
   2259     {"manifest", &CreateType<Manifest>},
   2260     {"meta-data", &CreateType<MetaData>},
   2261     {"original-package", &CreateType<OriginalPackage>},
   2262     {"overlay", &CreateType<Overlay>},
   2263     {"package-verifier", &CreateType<PackageVerifier>},
   2264     {"permission", &CreateType<Permission>},
   2265     {"provider", &CreateType<Provider>},
   2266     {"receiver", &CreateType<Receiver>},
   2267     {"screen", &CreateType<Screen>},
   2268     {"service", &CreateType<Service>},
   2269     {"supports-gl-texture", &CreateType<SupportsGlTexture>},
   2270     {"supports-input", &CreateType<SupportsInput>},
   2271     {"supports-screens", &CreateType<SupportsScreen>},
   2272     {"uses-configuration", &CreateType<UsesConfiguarion>},
   2273     {"uses-feature", &CreateType<UsesFeature>},
   2274     {"uses-permission", &CreateType<UsesPermission>},
   2275     {"uses-permission-sdk-23", &CreateType<UsesPermissionSdk23>},
   2276     {"uses-library", &CreateType<UsesLibrary>},
   2277     {"static-library", &CreateType<StaticLibrary>},
   2278     {"uses-static-library", &CreateType<UsesStaticLibrary>},
   2279     {"uses-package", &CreateType<UsesPackage>},
   2280     {"additional-certificate", &CreateType<AdditionalCertificate>},
   2281     {"uses-sdk", &CreateType<UsesSdkBadging>},
   2282   };
   2283 
   2284   // Attempt to map the xml tag to a element inflater
   2285   std::unique_ptr<ManifestExtractor::Element> element;
   2286   auto check = kTagCheck.find(el->name);
   2287   if (check != kTagCheck.end()) {
   2288     element = check->second();
   2289   } else {
   2290     element = util::make_unique<ManifestExtractor::Element>();
   2291   }
   2292 
   2293   element->extractor_ = extractor;
   2294   element->tag_ = el->name;
   2295   element->Extract(el);
   2296   return element;
   2297 }
   2298 
   2299 std::unique_ptr<ManifestExtractor::Element> ManifestExtractor::Visit(xml::Element* el) {
   2300   auto element = ManifestExtractor::Element::Inflate(this, el);
   2301   parent_stack_.insert(parent_stack_.begin(), element.get());
   2302 
   2303   // Process the element and recursively visit the children
   2304   for (xml::Element* child : el->GetChildElements()) {
   2305     auto v = Visit(child);
   2306     element->AddChild(v);
   2307   }
   2308 
   2309   parent_stack_.erase(parent_stack_.begin());
   2310   return element;
   2311 }
   2312 
   2313 
   2314 int DumpManifest(LoadedApk* apk, DumpManifestOptions& options, text::Printer* printer,
   2315                  IDiagnostics* diag) {
   2316   ManifestExtractor extractor(apk, options);
   2317   return extractor.Dump(printer, diag) ? 0 : 1;
   2318 }
   2319 
   2320 } // namespace aapt
   2321