Extend DumpManifest unit to export badging data into proto.

Bug: b/228950123
Test: Dump_test.cpp
Change-Id: I3c228767b435d0e31f1eec1f34daeec1065628d0
This commit is contained in:
Iurii Makhno
2022-04-26 15:30:01 +00:00
parent a9c74c5378
commit 85875a8350
4 changed files with 874 additions and 111 deletions

View File

@@ -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",

338
tools/aapt2/ApkInfo.proto Normal file
View File

@@ -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 <manifest> and
// <original-package> 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 <application> element.
message Application {
string label = 1;
string icon = 2;
string banner = 3;
bool test_only = 4;
bool game = 5;
bool debuggable = 6;
map<string, string> locale_labels = 8;
map<int32, string> 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 <uses-permission>
// 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 <meta-data> 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 <package-verifier> 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 <property> 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;
}
}

View File

@@ -17,8 +17,10 @@
#include "DumpManifest.h"
#include <algorithm>
#include <array>
#include <memory>
#include <set>
#include <string_view>
#include <vector>
#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<std::string> architectures;
std::set<std::string> 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<std::string_view, 14> 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<std::string, std::less<>> 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<Element> 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<Element>& 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<Element> Visit(xml::Element* element);
@@ -402,12 +501,9 @@ class ManifestExtractor {
std::unique_ptr<ManifestExtractor::Element> root_element_;
std::vector<std::unique_ptr<ManifestExtractor::Element>> implied_permissions_;
std::set<std::string> components_;
std::vector<FeatureGroup*> feature_groups_;
bool other_activities_ = false;
bool other_receivers_ = false;
bool other_services_ = false;
std::unique_ptr<Architectures> architectures_ = util::make_unique<Architectures>();
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 <uses-sdk> 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 <uses-configuration> 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 <supports-screen> 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 <feature-group> 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 <required-feature> 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 <permission> 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 <activity> 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 <intent-filter> 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 <static-library> 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 <uses-static-library> 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 <sdk-library> 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 <uses-sdk-library> 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 <uses-native-library> 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 <input-type> 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 <package-verifier> 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 <uses-package> 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 <additional-certificate> 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 <property> elements. **/
@@ -1987,27 +2407,22 @@ class Property : public ManifestExtractor::Element {
}
printer->Print("\n");
}
};
class Architectures {
public:
std::set<std::string> architectures;
std::set<std::string> 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<Action>(el)) {
auto action = ElementCast<Action>(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<Category>(el)) {
auto category = ElementCast<Category>(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<Activity>(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<Receiver>(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<Service>(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::Element> 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

View File

@@ -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