From 85875a83501d3bdc551cbddcecc26bab4617b06a Mon Sep 17 00:00:00 2001 From: Iurii Makhno Date: Tue, 26 Apr 2022 15:30:01 +0000 Subject: [PATCH] Extend DumpManifest unit to export badging data into proto. Bug: b/228950123 Test: Dump_test.cpp Change-Id: I3c228767b435d0e31f1eec1f34daeec1065628d0 --- tools/aapt2/Android.bp | 1 + tools/aapt2/ApkInfo.proto | 338 ++++++++++++++++ tools/aapt2/dump/DumpManifest.cpp | 642 ++++++++++++++++++++++++------ tools/aapt2/dump/DumpManifest.h | 4 + 4 files changed, 874 insertions(+), 111 deletions(-) create mode 100644 tools/aapt2/ApkInfo.proto diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp index 3dc550e855eca..51694c0556ddd 100644 --- a/tools/aapt2/Android.bp +++ b/tools/aapt2/Android.bp @@ -159,6 +159,7 @@ cc_library_host_static { "xml/XmlDom.cpp", "xml/XmlPullParser.cpp", "xml/XmlUtil.cpp", + "ApkInfo.proto", "Configuration.proto", "Resources.proto", "ResourcesInternal.proto", diff --git a/tools/aapt2/ApkInfo.proto b/tools/aapt2/ApkInfo.proto new file mode 100644 index 0000000000000..80bdccbc4dd23 --- /dev/null +++ b/tools/aapt2/ApkInfo.proto @@ -0,0 +1,338 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto3"; + +import "frameworks/base/tools/aapt2/Resources.proto"; + +package aapt.pb; + +option java_package = "com.android.aapt"; + +// Top level message representing data extracted from the APK for 'apkinfo' +// command. +message ApkInfo { + message XmlFile { + string path = 1; + XmlNode root = 2; + } + + Badging badging = 1; + ResourceTable resource_table = 2; + repeated XmlFile xml_files = 3; +} + +// Data extracted from the manifest of the APK. +message Badging { + PackageInfo package = 1; + Application application = 2; + UsesSdk uses_sdk = 3; + UsesConfiguration uses_configuration = 4; + SupportsScreen supports_screen = 5; + SupportsInput supports_input = 6; + LaunchableActivity launchable_activity = 7; + LeanbackLaunchableActivity leanback_launchable_activity = 8; + StaticLibrary static_library = 9; + SdkLibrary sdk_library = 10; + Overlay overlay = 11; + PackageVerifier package_verifier = 12; + CompatibleScreens compatible_screens = 13; + Architectures architectures = 14; + SupportsGlTexture supports_gl_texture = 15; + Components components = 16; + + repeated string locales = 17; + repeated int32 densities = 18; + + repeated FeatureGroup feature_groups = 53; + repeated UsesPermission uses_permissions = 54; + repeated Permission permissions = 55; + repeated UsesLibrary uses_libraries = 56; + repeated UsesStaticLibrary uses_static_libraries = 57; + repeated UsesSdkLibrary uses_sdk_libraries = 58; + repeated UsesNativeLibrary uses_native_libraries = 59; + repeated UsesPackage uses_packages = 51; + + repeated Metadata metadata = 62; + repeated Property properties = 63; +} + +// Information extracted about package from and +// tags. +message PackageInfo { + enum InstallLocation { + DEFAULT_INSTALL_LOCATION = 0; + AUTO = 1; + INTERNAL_ONLY = 2; + PREFER_EXTERNAL = 3; + } + + string package = 1; + int32 version_code = 2; + string version_name = 3; + + string split = 4; + + string platform_version_name = 5; + string platform_version_code = 6; + + int32 compile_sdk_version = 7; + string compile_sdk_version_codename = 8; + + InstallLocation install_location = 9; + + string original_package = 10; +} + +// Information extracted from element. +message Application { + string label = 1; + string icon = 2; + string banner = 3; + + bool test_only = 4; + bool game = 5; + bool debuggable = 6; + + map locale_labels = 8; + map density_icons = 9; +} + +// Components defined in the APK. +message Components { + bool main = 1; + bool other_activities = 2; + bool other_receivers = 3; + bool other_services = 4; + + repeated string provided_components = 5; +} + +// Application's min and target SDKs. +message UsesSdk { + oneof min_sdk { + int32 min_sdk_version = 2; + string min_sdk_version_name = 3; + } + int32 max_sdk_version = 4; + oneof target_sdk { + int32 target_sdk_version = 5; + string target_sdk_version_name = 6; + } +} + +message UsesConfiguration { + int32 req_touch_screen = 1; + int32 req_keyboard_type = 2; + int32 req_hard_keyboard = 3; + int32 req_navigation = 4; + int32 req_five_way_nav = 5; +} + +// Screens supported by this application. +message SupportsScreen { + enum ScreenType { + UNSPECIFIED_SCREEN_TYPE = 0; + SMALL = 1; + NORMAL = 2; + LARGE = 3; + XLARGE = 4; + } + repeated ScreenType screens = 1; + bool supports_any_densities = 2; + int32 requires_smallest_width_dp = 3; + int32 compatible_width_limit_dp = 4; + int32 largest_width_limit_dp = 5; +} + +// Inputs supported by this application. +message SupportsInput { + repeated string inputs = 1; +} + +// Information about used features which is extracted from +// elements or implied from permissions. +message Feature { + message ImpliedData { + bool from_sdk_23_permission = 1; + repeated string reasons = 2; + } + + string name = 1; + bool required = 2; + int32 version = 3; + + ImpliedData implied_data = 4; +} + +message FeatureGroup { + string label = 1; + int32 open_gles_version = 2; + repeated Feature features = 3; +} + +// Information about permission requested by the application. +message UsesPermission { + message PermissionFlags { + bool never_for_location = 1; + } + + string name = 1; + int32 max_sdk_version = 2; + bool required = 3; + bool implied = 4; + bool sdk23_and_above = 5; + + repeated string required_features = 6; + repeated string required_not_features = 7; + + PermissionFlags permission_flags = 8; +} + +// Permission defined by the application. +message Permission { + string name = 1; +} + +// Data extracted about launchable activity. Launchable activity is an entry +// point on phone and tablet devices. +message LaunchableActivity { + string name = 1; + string icon = 2; + string label = 3; +} + +// Data extracted about leanback launchable activity. Leanback launchable +// activity is an entry point on TV devices. +message LeanbackLaunchableActivity { + string name = 1; + string icon = 2; + string label = 3; + string banner = 4; +} + +// Library used by the application. +message UsesLibrary { + string name = 1; + bool required = 2; +} + +// Static library this APK declares. +message StaticLibrary { + string name = 1; + int32 version = 2; + int32 version_major = 3; +} + +// Static library used by the application. +message UsesStaticLibrary { + string name = 1; + int32 version = 2; + int32 version_major = 3; + repeated string certificates = 4; +} + +// SDK library this APK declares. +message SdkLibrary { + string name = 1; + int32 version_major = 2; +} + +// SDK library used by the application. +message UsesSdkLibrary { + string name = 1; + int32 version_major = 2; + repeated string certificates = 3; +} + +// Native library used by the application. +message UsesNativeLibrary { + string name = 1; + bool required = 2; +} + +// Information extracted from elements defined across +// AndroidManifest.xml. +message Metadata { + string name = 1; + oneof value { + string value_string = 2; + int32 value_int = 3; + } + oneof resource { + string resource_string = 4; + int32 resource_int = 5; + } +} + +// Information about overlay that is declared in the APK. +message Overlay { + string target_package = 1; + int32 priority = 2; + bool static = 3; + string required_property_name = 4; + string required_property_value = 5; +} + +// Data extracted from element. +message PackageVerifier { + string name = 1; + string public_key = 2; +} + +// External packages used by the application +message UsesPackage { + string name = 1; + string package_type = 2; + int32 version = 3; + int32 version_major = 4; + repeated string certificates = 5; +} + +// Open GL textures format supported by the current application. +message SupportsGlTexture { + repeated string name = 1; +} + +// Screens compatible with the application. +message CompatibleScreens { + message Screen { + int32 size = 1; + int32 density = 2; + } + + repeated Screen screens = 1; +} + +// Architectures supported by the application. +message Architectures { + repeated string architectures = 1; + repeated string alt_architectures = 2; +} + +// Information extracted from elements defined across +// AndroidManifest.xml. +message Property { + string name = 1; + oneof value { + string value_string = 2; + int32 value_int = 3; + } + oneof resource { + string resource_string = 4; + int32 resource_int = 5; + } +} \ No newline at end of file diff --git a/tools/aapt2/dump/DumpManifest.cpp b/tools/aapt2/dump/DumpManifest.cpp index 64a9441d1ac2f..e36112d6126c2 100644 --- a/tools/aapt2/dump/DumpManifest.cpp +++ b/tools/aapt2/dump/DumpManifest.cpp @@ -17,8 +17,10 @@ #include "DumpManifest.h" #include +#include #include #include +#include #include #include "LoadedApk.h" @@ -114,10 +116,101 @@ static xml::Attribute* FindAttribute(xml::Element *el, const std::string &packag return el->FindAttribute(package, name); } +class Architectures { + public: + std::set architectures; + std::set alt_architectures; + + void Print(text::Printer* printer) { + if (!architectures.empty()) { + printer->Print("native-code:"); + for (auto& arch : architectures) { + printer->Print(StringPrintf(" '%s'", arch.data())); + } + printer->Print("\n"); + } + if (!alt_architectures.empty()) { + printer->Print("alt-native-code:"); + for (auto& arch : alt_architectures) { + printer->Print(StringPrintf(" '%s'", arch.data())); + } + printer->Print("\n"); + } + } + + void ToProto(pb::Badging* out_badging) { + auto out_architectures = out_badging->mutable_architectures(); + for (auto& arch : architectures) { + out_architectures->add_architectures(arch); + } + for (auto& arch : alt_architectures) { + out_architectures->add_alt_architectures(arch); + } + } +}; + +const static std::array printable_components{"app-widget", + "device-admin", + "ime", + "wallpaper", + "accessibility", + "print-service", + "payment", + "search", + "document-provider", + "launcher", + "notification-listener", + "dream", + "camera", + "camera-secure"}; + +class Components { + public: + std::set> discovered_components; + bool other_activities = false; + bool other_receivers = false; + bool other_services = false; + + void Print(text::Printer* printer) { + for (auto& component : printable_components) { + if (discovered_components.find(component) != discovered_components.end()) { + printer->Print(StringPrintf("provides-component:'%s'\n", component.data())); + } + } + // Print presence of main activity + if (discovered_components.find("main") != discovered_components.end()) { + printer->Print("main\n"); + } + + if (other_activities) { + printer->Print("other-activities\n"); + } + if (other_receivers) { + printer->Print("other-receivers\n"); + } + if (other_services) { + printer->Print("other-services\n"); + } + } + + void ToProto(pb::Badging* out_badging) { + auto out_components = out_badging->mutable_components(); + for (auto& component : printable_components) { + auto discovered = discovered_components.find(component); + if (discovered != discovered_components.end()) { + out_components->add_provided_components(*discovered); + } + } + out_components->set_main(discovered_components.find("main") != discovered_components.end()); + out_components->set_other_activities(other_activities); + out_components->set_other_receivers(other_receivers); + out_components->set_other_services(other_services); + } +}; + class CommonFeatureGroup; -class Architectures; -class SupportsScreen; class FeatureGroup; +class SupportsScreen; class ManifestExtractor { public: @@ -133,7 +226,12 @@ class ManifestExtractor { static std::unique_ptr Inflate(ManifestExtractor* extractor, xml::Element* el); /** Writes out the extracted contents of the element. */ - virtual void Print(text::Printer* printer) { } + virtual void Print(text::Printer* printer) { + } + + /** Saves extracted information into Badging proto. */ + virtual void ToProto(pb::Badging* out_badging) { + } /** Adds an element to the list of children of the element. */ void AddChild(std::unique_ptr& child) { children_.push_back(std::move(child)); } @@ -345,6 +443,7 @@ class ManifestExtractor { bool Extract(IDiagnostics* diag); bool Dump(text::Printer* printer); + bool DumpProto(pb::Badging* out_badging); /** Recursively visit the xml element tree and return a processed badging element tree. */ std::unique_ptr Visit(xml::Element* element); @@ -402,12 +501,9 @@ class ManifestExtractor { std::unique_ptr root_element_; std::vector> implied_permissions_; - std::set components_; std::vector feature_groups_; - bool other_activities_ = false; - bool other_receivers_ = false; - bool other_services_ = false; - std::unique_ptr architectures_ = util::make_unique(); + Components components_; + Architectures architectures_; const SupportsScreen* supports_screen_; }; @@ -480,6 +576,45 @@ class Manifest : public ManifestExtractor::Element { installLocation = GetAttributeInteger(FindAttribute(manifest, INSTALL_LOCATION_ATTR)); } + void ToProto(pb::Badging* out_badging) override { + auto out_package = out_badging->mutable_package(); + out_package->set_package(package); + out_package->set_version_code(versionCode); + out_package->set_version_name(versionName); + if (compilesdkVersion) { + out_package->set_compile_sdk_version(*compilesdkVersion); + } + if (compilesdkVersionCodename) { + out_package->set_compile_sdk_version_codename(*compilesdkVersionCodename); + } + if (platformVersionName) { + out_package->set_platform_version_name(*platformVersionName); + } else if (platformVersionNameInt) { + out_package->set_platform_version_name(std::to_string(*platformVersionNameInt)); + } + if (platformVersionCode) { + out_package->set_platform_version_code(*platformVersionCode); + } else if (platformVersionCodeInt) { + out_package->set_platform_version_code(std::to_string(*platformVersionCodeInt)); + } + + if (installLocation) { + switch (*installLocation) { + case 0: + out_package->set_install_location(pb::PackageInfo_InstallLocation_AUTO); + break; + case 1: + out_package->set_install_location(pb::PackageInfo_InstallLocation_INTERNAL_ONLY); + break; + case 2: + out_package->set_install_location(pb::PackageInfo_InstallLocation_PREFER_EXTERNAL); + break; + default: + break; + } + } + } + void Print(text::Printer* printer) override { if (only_package_name) { printer->Println(StringPrintf("package: %s", package.data())); @@ -624,6 +759,27 @@ class Application : public ManifestExtractor::Element { printer->Print("application-debuggable\n"); } } + + void ToProto(pb::Badging* out_badging) override { + auto application = out_badging->mutable_application(); + application->set_label(android::ResTable::normalizeForOutput(label.data())); + application->set_icon(icon); + application->set_banner(banner); + application->set_test_only(test_only != 0); + application->set_game(is_game != 0); + application->set_debuggable(debuggable != 0); + + auto out_locale_labels = application->mutable_locale_labels(); + for (auto& p : locale_labels) { + if (!p.first.empty()) { + (*out_locale_labels)[p.first] = p.second; + } + } + auto out_density_icons = application->mutable_density_icons(); + for (auto& p : density_icons) { + (*out_density_icons)[p.first] = p.second; + } + } }; /** Represents elements. **/ @@ -673,6 +829,23 @@ class UsesSdkBadging : public ManifestExtractor::Element { printer->Print(StringPrintf("targetSdkVersion:'%s'\n", target_sdk_name->data())); } } + + void ToProto(pb::Badging* out_badging) override { + auto out_sdks = out_badging->mutable_uses_sdk(); + if (min_sdk) { + out_sdks->set_min_sdk_version(*min_sdk); + } else if (min_sdk_name) { + out_sdks->set_min_sdk_version_name(*min_sdk_name); + } + if (max_sdk) { + out_sdks->set_max_sdk_version(*max_sdk); + } + if (target_sdk) { + out_sdks->set_target_sdk_version(*target_sdk); + } else if (target_sdk_name) { + out_sdks->set_target_sdk_version_name(*target_sdk_name); + } + } }; /** Represents elements. **/ @@ -717,6 +890,15 @@ class UsesConfiguarion : public ManifestExtractor::Element { } printer->Print("\n"); } + + void ToProto(pb::Badging* out_badging) override { + auto out_configuration = out_badging->mutable_uses_configuration(); + out_configuration->set_req_touch_screen(req_touch_screen); + out_configuration->set_req_keyboard_type(req_keyboard_type); + out_configuration->set_req_hard_keyboard(req_hard_keyboard); + out_configuration->set_req_navigation(req_navigation); + out_configuration->set_req_five_way_nav(req_five_way_nav); + } }; /** Represents elements. **/ @@ -760,53 +942,23 @@ class SupportsScreen : public ManifestExtractor::Element { } void PrintScreens(text::Printer* printer, int32_t target_sdk) const { - int32_t small_screen_temp = small_screen; - int32_t normal_screen_temp = normal_screen; - int32_t large_screen_temp = large_screen; - int32_t xlarge_screen_temp = xlarge_screen; - int32_t any_density_temp = any_density; - - // Determine default values for any unspecified screen sizes, - // based on the target SDK of the package. As of 4 (donut) - // the screen size support was introduced, so all default to - // enabled. - if (small_screen_temp > 0) { - small_screen_temp = target_sdk >= SDK_DONUT ? -1 : 0; - } - if (normal_screen_temp > 0) { - normal_screen_temp = -1; - } - if (large_screen_temp > 0) { - large_screen_temp = target_sdk >= SDK_DONUT ? -1 : 0; - } - if (xlarge_screen_temp > 0) { - // Introduced in Gingerbread. - xlarge_screen_temp = target_sdk >= SDK_GINGERBREAD ? -1 : 0; - } - if (any_density_temp > 0) { - any_density_temp = (target_sdk >= SDK_DONUT || requires_smallest_width_dp > 0 || - compatible_width_limit_dp > 0) - ? -1 - : 0; - } - // Print the formatted screen info printer->Print("supports-screens:"); - if (small_screen_temp != 0) { + if (IsSmallScreenSupported(target_sdk)) { printer->Print(" 'small'"); } - if (normal_screen_temp != 0) { + if (normal_screen != 0) { printer->Print(" 'normal'"); } - if (large_screen_temp != 0) { + if (IsLargeScreenSupported(target_sdk)) { printer->Print(" 'large'"); } - if (xlarge_screen_temp != 0) { + if (IsXLargeScreenSupported(target_sdk)) { printer->Print(" 'xlarge'"); } printer->Print("\n"); printer->Print(StringPrintf("supports-any-density: '%s'\n", - (any_density_temp ) ? "true" : "false")); + (IsAnyDensitySupported(target_sdk)) ? "true" : "false")); if (requires_smallest_width_dp > 0) { printer->Print(StringPrintf("requires-smallest-width:'%d'\n", requires_smallest_width_dp)); } @@ -817,6 +969,60 @@ class SupportsScreen : public ManifestExtractor::Element { printer->Print(StringPrintf("largest-width-limit:'%d'\n", largest_width_limit_dp)); } } + + void ToProtoScreens(pb::Badging* out_badging, int32_t target_sdk) const { + auto supports_screen = out_badging->mutable_supports_screen(); + if (IsSmallScreenSupported(target_sdk)) { + supports_screen->add_screens(pb::SupportsScreen_ScreenType_SMALL); + } + if (normal_screen != 0) { + supports_screen->add_screens(pb::SupportsScreen_ScreenType_NORMAL); + } + if (IsLargeScreenSupported(target_sdk)) { + supports_screen->add_screens(pb::SupportsScreen_ScreenType_LARGE); + } + if (IsXLargeScreenSupported(target_sdk)) { + supports_screen->add_screens(pb::SupportsScreen_ScreenType_XLARGE); + } + supports_screen->set_supports_any_densities(IsAnyDensitySupported(target_sdk)); + supports_screen->set_requires_smallest_width_dp(requires_smallest_width_dp); + supports_screen->set_compatible_width_limit_dp(compatible_width_limit_dp); + supports_screen->set_largest_width_limit_dp(largest_width_limit_dp); + } + + private: + // Determine default values for any unspecified screen sizes, + // based on the target SDK of the package. As of 4 (donut) + // the screen size support was introduced, so all default to + // enabled. + bool IsSmallScreenSupported(int32_t target_sdk) const { + if (small_screen > 0) { + return target_sdk >= SDK_DONUT; + } + return small_screen != 0; + } + + bool IsLargeScreenSupported(int32_t target_sdk) const { + if (large_screen > 0) { + return target_sdk >= SDK_DONUT; + } + return large_screen != 0; + } + + bool IsXLargeScreenSupported(int32_t target_sdk) const { + if (xlarge_screen > 0) { + return target_sdk >= SDK_GINGERBREAD; + } + return xlarge_screen != 0; + } + + bool IsAnyDensitySupported(int32_t target_sdk) const { + if (any_density > 0) { + return target_sdk >= SDK_DONUT || requires_smallest_width_dp > 0 || + compatible_width_limit_dp > 0; + } + return any_density != 0; + } }; /** Represents elements. **/ @@ -847,6 +1053,18 @@ class FeatureGroup : public ManifestExtractor::Element { } } + virtual void GroupToProto(pb::Badging* out_badging) { + auto feature_group = out_badging->add_feature_groups(); + feature_group->set_label(label); + feature_group->set_open_gles_version(open_gles_version); + for (auto& feature : features_) { + auto out_feature = feature_group->add_features(); + out_feature->set_name(feature.first); + out_feature->set_required(feature.second.required); + out_feature->set_version(feature.second.version); + } + } + /** Adds a feature to the feature group. */ void AddFeature(const std::string& name, bool required = true, int32_t version = -1) { features_.insert(std::make_pair(name, Feature{ required, version })); @@ -936,6 +1154,23 @@ class CommonFeatureGroup : public FeatureGroup { } } + virtual void GroupToProto(pb::Badging* out_badging) override { + FeatureGroup::GroupToProto(out_badging); + auto feature_group = + out_badging->mutable_feature_groups(out_badging->feature_groups_size() - 1); + for (auto& feature : implied_features_) { + if (features_.find(feature.first) == features_.end()) { + auto out_feature = feature_group->add_features(); + out_feature->set_name(feature.first); + auto implied_data = out_feature->mutable_implied_data(); + implied_data->set_from_sdk_23_permission(feature.second.implied_from_sdk_k23); + for (auto& reason : feature.second.reasons) { + implied_data->add_reasons(reason); + } + } + } + } + /** Returns true if the feature group has the given feature. */ bool HasFeature(const std::string& name) override { return FeatureGroup::HasFeature(name) @@ -1165,6 +1400,27 @@ class UsesPermission : public ManifestExtractor::Element { printer->Print(StringPrintf(" reason='%s'\n", impliedReason.data())); } } + + void ToProto(pb::Badging* out_badging) override { + if (!name.empty()) { + auto permission = out_badging->add_uses_permissions(); + permission->set_name(name); + if (maxSdkVersion > 0) { + permission->set_max_sdk_version(maxSdkVersion); + } + if ((usesPermissionFlags & kNeverForLocation) != 0) { + permission->mutable_permission_flags()->set_never_for_location(true); + } + for (auto& requiredFeature : requiredFeatures) { + permission->add_required_features(requiredFeature); + } + for (auto& requiredNotFeature : requiredNotFeatures) { + permission->add_required_not_features(requiredNotFeature); + } + permission->set_required(required != 0); + permission->set_implied(implied); + } + } }; /** Represents elements. **/ @@ -1225,6 +1481,17 @@ class UsesPermissionSdk23 : public ManifestExtractor::Element { printer->Print("\n"); } } + + void ToProto(pb::Badging* out_badging) override { + if (name) { + auto permission = out_badging->add_uses_permissions(); + permission->set_sdk23_and_above(true); + permission->set_name(*name); + if (maxSdkVersion) { + permission->set_max_sdk_version(*maxSdkVersion); + } + } + } }; /** Represents elements. These elements are only printing when dumping permissions. **/ @@ -1242,6 +1509,12 @@ class Permission : public ManifestExtractor::Element { printer->Print(StringPrintf("permission: %s\n", name.data())); } } + + void ToProto(pb::Badging* out_badging) override { + if (!name.empty()) { + out_badging->add_permissions()->set_name(name); + } + } }; /** Represents elements. **/ @@ -1322,6 +1595,22 @@ class Activity : public ManifestExtractor::Element { icon.data(), banner.data())); } } + + void ToProto(pb::Badging* out_badging) override { + if (has_main_action && has_launcher_category) { + auto activity = out_badging->mutable_launchable_activity(); + activity->set_name(name); + activity->set_label(android::ResTable::normalizeForOutput(label.data())); + activity->set_icon(icon); + } + if (has_leanback_launcher_category) { + auto activity = out_badging->mutable_leanback_launchable_activity(); + activity->set_name(name); + activity->set_label(android::ResTable::normalizeForOutput(label.data())); + activity->set_icon(icon); + activity->set_banner(banner); + } + } }; /** Represents elements. */ @@ -1422,6 +1711,14 @@ class UsesLibrary : public ManifestExtractor::Element { (required == 0) ? "-not-required" : "", name.data())); } } + + void ToProto(pb::Badging* out_badging) override { + if (!name.empty()) { + auto uses_library = out_badging->add_uses_libraries(); + uses_library->set_name(name); + uses_library->set_required(required != 0); + } + } }; /** Represents elements. **/ @@ -1446,6 +1743,13 @@ class StaticLibrary : public ManifestExtractor::Element { "static-library: name='%s' version='%d' versionMajor='%d'\n", name.data(), version, versionMajor)); } + + void ToProto(pb::Badging* out_badging) override { + auto static_library = out_badging->mutable_static_library(); + static_library->set_name(name); + static_library->set_version(version); + static_library->set_version_major(versionMajor); + } }; /** Represents elements. **/ @@ -1486,6 +1790,16 @@ class UsesStaticLibrary : public ManifestExtractor::Element { } printer->Print("\n"); } + + void ToProto(pb::Badging* out_badging) override { + auto uses_static_library = out_badging->add_uses_static_libraries(); + uses_static_library->set_name(name); + uses_static_library->set_version(version); + uses_static_library->set_version_major(versionMajor); + for (auto& cert : certDigests) { + uses_static_library->add_certificates(cert); + } + } }; /** Represents elements. **/ @@ -1507,6 +1821,12 @@ class SdkLibrary : public ManifestExtractor::Element { printer->Print( StringPrintf("sdk-library: name='%s' versionMajor='%d'\n", name.data(), versionMajor)); } + + void ToProto(pb::Badging* out_badging) override { + auto sdk_library = out_badging->mutable_sdk_library(); + sdk_library->set_name(name); + sdk_library->set_version_major(versionMajor); + } }; /** Represents elements. **/ @@ -1544,6 +1864,15 @@ class UsesSdkLibrary : public ManifestExtractor::Element { } printer->Print("\n"); } + + void ToProto(pb::Badging* out_badging) override { + auto uses_sdk_library = out_badging->add_uses_sdk_libraries(); + uses_sdk_library->set_name(name); + uses_sdk_library->set_version_major(versionMajor); + for (auto& cert : certDigests) { + uses_sdk_library->add_certificates(cert); + } + } }; /** Represents elements. **/ @@ -1567,6 +1896,14 @@ class UsesNativeLibrary : public ManifestExtractor::Element { (required == 0) ? "-not-required" : "", name.data())); } } + + void ToProto(pb::Badging* out_badging) override { + if (!name.empty()) { + auto uses_native_library = out_badging->add_uses_native_libraries(); + uses_native_library->set_name(name); + uses_native_library->set_required(required != 0); + } + } }; /** @@ -1607,6 +1944,24 @@ class MetaData : public ManifestExtractor::Element { printer->Print("\n"); } } + + void ToProto(pb::Badging* out_badging) override { + if (!name.empty()) { + auto metadata = out_badging->add_metadata(); + metadata->set_name(name); + if (!value.empty()) { + metadata->set_value_string(value); + } else if (value_int) { + metadata->set_value_int(*value_int); + } else { + if (!resource.empty()) { + metadata->set_resource_string(resource); + } else if (resource_int) { + metadata->set_resource_int(*resource_int); + } + } + } + } }; /** @@ -1736,6 +2091,13 @@ class SupportsInput : public ManifestExtractor::Element { printer->Print("\n"); } } + + void ToProto(pb::Badging* out_badging) override { + auto supports_input = out_badging->mutable_supports_input(); + for (auto& input : inputs) { + supports_input->add_inputs(input); + } + } }; /** Represents elements. **/ @@ -1769,6 +2131,12 @@ class OriginalPackage : public ManifestExtractor::Element { printer->Print(StringPrintf("original-package:'%s'\n", name->data())); } } + + void ToProto(pb::Badging* out_badging) override { + if (name) { + out_badging->mutable_package()->set_original_package(*name); + } + } }; @@ -1807,6 +2175,21 @@ class Overlay : public ManifestExtractor::Element { } printer->Print("\n"); } + + void ToProto(pb::Badging* out_badging) override { + auto overlay = out_badging->mutable_overlay(); + if (target_package) { + overlay->set_target_package(*target_package); + } + overlay->set_priority(priority); + overlay->set_static_(is_static); + if (required_property_name) { + overlay->set_required_property_name(*required_property_name); + } + if (required_property_value) { + overlay->set_required_property_value(*required_property_value); + } + } }; /** * Represents elements. **/ @@ -1827,6 +2210,14 @@ class PackageVerifier : public ManifestExtractor::Element { name->data(), public_key->data())); } } + + void ToProto(pb::Badging* out_badging) override { + auto package_verifier = out_badging->mutable_package_verifier(); + if (name && public_key) { + package_verifier->set_name(*name); + package_verifier->set_public_key(*public_key); + } + } }; /** Represents elements. **/ @@ -1875,6 +2266,21 @@ class UsesPackage : public ManifestExtractor::Element { } } } + + void ToProto(pb::Badging* out_badging) override { + if (name) { + auto uses_package = out_badging->add_uses_packages(); + uses_package->set_name(*name); + if (packageType) { + uses_package->set_package_type(*packageType); + uses_package->set_version(version); + uses_package->set_version_major(versionMajor); + for (auto& cert : certDigests) { + uses_package->add_certificates(cert); + } + } + } + } }; /** Represents elements. **/ @@ -1907,6 +2313,14 @@ class Screen : public ManifestExtractor::Element { size = GetAttributeInteger(FindAttribute(element, SCREEN_SIZE_ATTR)); density = GetAttributeInteger(FindAttribute(element, SCREEN_DENSITY_ATTR)); } + + void ToProto(pb::Badging* out_badging) override { + if (size && density) { + auto screen = out_badging->mutable_compatible_screens()->add_screens(); + screen->set_density(*density); + screen->set_size(*size); + } + } }; /** @@ -1952,6 +2366,12 @@ class SupportsGlTexture : public ManifestExtractor::Element { printer->Print(StringPrintf("supports-gl-texture:'%s'\n", name->data())); } } + + void ToProto(pb::Badging* out_badging) override { + if (name) { + out_badging->mutable_supports_gl_texture()->add_name(*name); + } + } }; /** Represents elements. **/ @@ -1987,27 +2407,22 @@ class Property : public ManifestExtractor::Element { } printer->Print("\n"); } -}; -class Architectures { - public: - std::set architectures; - std::set alt_architectures; - - void Print(text::Printer* printer) { - if (!architectures.empty()) { - printer->Print("native-code:"); - for (auto& arch : architectures) { - printer->Print(StringPrintf(" '%s'", arch.data())); + void ToProto(pb::Badging* out_badging) override { + if (!name.empty()) { + auto property = out_badging->add_properties(); + property->set_name(name); + if (!value.empty()) { + property->set_value_string(value); + } else if (value_int) { + property->set_value_int(*value_int); + } else { + if (!resource.empty()) { + property->set_resource_string(resource); + } else if (resource_int) { + property->set_resource_int(*resource_int); + } } - printer->Print("\n"); - } - if (!alt_architectures.empty()) { - printer->Print("alt-native-code:"); - for (auto& arch : alt_architectures) { - printer->Print(StringPrintf(" '%s'", arch.data())); - } - printer->Print("\n"); } } }; @@ -2020,6 +2435,14 @@ static void Print(ManifestExtractor::Element* el, text::Printer* printer) { } } +/** Recursively serializes extracted badging elements to proto. */ +static void ToProto(ManifestExtractor::Element* el, pb::Badging* out_badging) { + el->ToProto(out_badging); + for (auto& child : el->children()) { + ToProto(child.get(), out_badging); + } +} + bool ManifestExtractor::Extract(IDiagnostics* diag) { // Load the manifest doc_ = apk_->LoadXml("AndroidManifest.xml", diag); @@ -2198,7 +2621,7 @@ bool ManifestExtractor::Extract(IDiagnostics* diag) { if (ElementCast(el)) { auto action = ElementCast(el); if (!action->component.empty()) { - components_.insert(action->component); + components_.discovered_components.insert(action->component); return; } } @@ -2206,7 +2629,7 @@ bool ManifestExtractor::Extract(IDiagnostics* diag) { if (ElementCast(el)) { auto category = ElementCast(el); if (!category->component.empty()) { - components_.insert(category->component); + components_.discovered_components.insert(category->component); return; } } @@ -2256,7 +2679,7 @@ bool ManifestExtractor::Extract(IDiagnostics* diag) { if (child->name == "aid-group") { auto category = FindAttribute(child, CATEGORY_ATTR); if (category && category->value == "payment") { - this->components_.insert("payment"); + this->components_.discovered_components.insert("payment"); return; } } @@ -2272,7 +2695,7 @@ bool ManifestExtractor::Extract(IDiagnostics* diag) { FindElement(root_element_.get(), [&](ManifestExtractor::Element* el) -> bool { if (auto activity = ElementCast(el)) { if (!activity->has_component_) { - other_activities_ = true; + components_.other_activities = true; return true; } } @@ -2282,7 +2705,7 @@ bool ManifestExtractor::Extract(IDiagnostics* diag) { FindElement(root_element_.get(), [&](ManifestExtractor::Element* el) -> bool { if (auto receiver = ElementCast(el)) { if (!receiver->has_component) { - other_receivers_ = true; + components_.other_receivers = true; return true; } } @@ -2292,7 +2715,7 @@ bool ManifestExtractor::Extract(IDiagnostics* diag) { FindElement(root_element_.get(), [&](ManifestExtractor::Element* el) -> bool { if (auto service = ElementCast(el)) { if (!service->has_component) { - other_services_ = true; + components_.other_services = true; return true; } } @@ -2358,16 +2781,16 @@ bool ManifestExtractor::Extract(IDiagnostics* diag) { } if (arch != architectures_from_apk.end()) { - architectures_->architectures.insert(*arch); + architectures_.architectures.insert(*arch); architectures_from_apk.erase(arch); output_alt_native_code = true; } } for (auto& arch : architectures_from_apk) { if (output_alt_native_code) { - architectures_->alt_architectures.insert(arch); + architectures_.alt_architectures.insert(arch); } else { - architectures_->architectures.insert(arch); + architectures_.architectures.insert(arch); } } return true; @@ -2385,43 +2808,7 @@ bool ManifestExtractor::Dump(text::Printer* printer) { for (auto& feature_group : feature_groups_) { feature_group->PrintGroup(printer); } - // Print the components types if they are present - auto& components = components_; - auto PrintComponent = [&components, &printer](const std::string& component) -> void { - if (components.find(component) != components.end()) { - printer->Print(StringPrintf("provides-component:'%s'\n", component.data())); - } - }; - - PrintComponent("app-widget"); - PrintComponent("device-admin"); - PrintComponent("ime"); - PrintComponent("wallpaper"); - PrintComponent("accessibility"); - PrintComponent("print-service"); - PrintComponent("payment"); - PrintComponent("search"); - PrintComponent("document-provider"); - PrintComponent("launcher"); - PrintComponent("notification-listener"); - PrintComponent("dream"); - PrintComponent("camera"); - PrintComponent("camera-secure"); - - // Print presence of main activity - if (components.find("main") != components.end()) { - printer->Print("main\n"); - } - - if (other_activities_) { - printer->Print("other-activities\n"); - } - if (other_receivers_) { - printer->Print("other-receivers\n"); - } - if (other_services_) { - printer->Print("other-services\n"); - } + components_.Print(printer); supports_screen_->PrintScreens(printer, target_sdk_); // Print all the unique locales of the apk @@ -2442,7 +2829,31 @@ bool ManifestExtractor::Dump(text::Printer* printer) { } printer->Print("\n"); - architectures_->Print(printer); + architectures_.Print(printer); + return true; +} + +bool ManifestExtractor::DumpProto(pb::Badging* out_badging) { + ToProto(root_element_.get(), out_badging); + for (auto& implied_permission : implied_permissions_) { + implied_permission->ToProto(out_badging); + } + for (auto& feature_group : feature_groups_) { + feature_group->GroupToProto(out_badging); + } + components_.ToProto(out_badging); + supports_screen_->ToProtoScreens(out_badging, target_sdk_); + + for (auto& config : locales_) { + if (!config.first.empty()) { + out_badging->add_locales(config.first); + } + } + for (auto& config : densities_) { + out_badging->add_densities(config.first); + } + + architectures_.ToProto(out_badging); return true; } @@ -2581,14 +2992,23 @@ std::unique_ptr ManifestExtractor::Visit(xml::Elemen return element; } - int DumpManifest(LoadedApk* apk, DumpManifestOptions& options, text::Printer* printer, IDiagnostics* diag) { ManifestExtractor extractor(apk, options); if (!extractor.Extract(diag)) { - return 0; + return 1; } return extractor.Dump(printer) ? 0 : 1; } +int DumpBadgingProto(LoadedApk* apk, pb::Badging* out_badging, IDiagnostics* diag) { + DumpManifestOptions options{/* include_meta_data= */ true, + /* only_permissions= */ false}; + ManifestExtractor extractor(apk, options); + if (!extractor.Extract(diag)) { + return 1; + } + return extractor.DumpProto(out_badging) ? 0 : 1; +} + } // namespace aapt diff --git a/tools/aapt2/dump/DumpManifest.h b/tools/aapt2/dump/DumpManifest.h index daf22ed57a84d..72d1b464f1f5d 100644 --- a/tools/aapt2/dump/DumpManifest.h +++ b/tools/aapt2/dump/DumpManifest.h @@ -17,6 +17,7 @@ #ifndef AAPT2_DUMP_MANIFEST_H #define AAPT2_DUMP_MANIFEST_H +#include "ApkInfo.pb.h" #include "Diagnostics.h" #include "LoadedApk.h" #include "text/Printer.h" @@ -34,6 +35,9 @@ struct DumpManifestOptions { int DumpManifest(LoadedApk* apk, DumpManifestOptions& options, text::Printer* printer, IDiagnostics* diag); +/** Extracts badging data from the manifest of the APK and stores it in Badging proto. */ +int DumpBadgingProto(LoadedApk* apk, pb::Badging* out_badging, IDiagnostics* diag); + } // namespace aapt #endif // AAPT2_DUMP_MANIFEST_H \ No newline at end of file