summaryrefslogtreecommitdiff
path: root/tools/aapt2/optimize/MultiApkGenerator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/aapt2/optimize/MultiApkGenerator.cpp')
-rw-r--r--tools/aapt2/optimize/MultiApkGenerator.cpp109
1 files changed, 75 insertions, 34 deletions
diff --git a/tools/aapt2/optimize/MultiApkGenerator.cpp b/tools/aapt2/optimize/MultiApkGenerator.cpp
index 563c46df26d1..fb150e204167 100644
--- a/tools/aapt2/optimize/MultiApkGenerator.cpp
+++ b/tools/aapt2/optimize/MultiApkGenerator.cpp
@@ -23,6 +23,7 @@
#include "LoadedApk.h"
#include "ResourceUtils.h"
+#include "ValueVisitor.h"
#include "configuration/ConfigurationParser.h"
#include "filter/AbiFilter.h"
#include "filter/Filter.h"
@@ -33,12 +34,14 @@
#include "split/TableSplitter.h"
#include "util/Files.h"
#include "xml/XmlDom.h"
+#include "xml/XmlUtil.h"
namespace aapt {
using ::aapt::configuration::AndroidSdk;
using ::aapt::configuration::Artifact;
using ::aapt::configuration::PostProcessingConfiguration;
+using ::aapt::xml::kSchemaAndroid;
using ::aapt::xml::XmlResource;
using ::android::StringPiece;
@@ -153,40 +156,10 @@ bool MultiApkGenerator::FromBaseApk(const MultiApkGeneratorOptions& options) {
}
std::unique_ptr<XmlResource> manifest;
-
- Maybe<AndroidSdk> maybe_sdk = GetAndroidSdk(artifact, config, diag);
- if (maybe_sdk) {
- // TODO(safarmer): Handle the rest of the Android SDK.
- const AndroidSdk& android_sdk = maybe_sdk.value();
-
- manifest = apk_->InflateManifest(context_);
- if (!manifest) {
- return false;
- }
-
- // Make sure the first element is <manifest> with package attribute.
- xml::Element* manifest_el = manifest->root.get();
- if (manifest_el == nullptr) {
- return {};
- }
-
- if (!manifest_el->namespace_uri.empty() || manifest_el->name != "manifest") {
- diag->Error(DiagMessage(manifest->file.source) << "root tag must be <manifest>");
- return {};
- }
-
- if (xml::Element* uses_sdk_el = manifest_el->FindChild({}, "uses-sdk")) {
- if (xml::Attribute* min_sdk_attr =
- uses_sdk_el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion")) {
- if (min_sdk_attr == nullptr) {
- diag->Error(DiagMessage(manifest->file.source.WithLine(uses_sdk_el->line_number))
- << "missing android:minSdkVersion");
- return {};
- }
- const std::string& min_sdk_str = std::to_string(android_sdk.min_sdk_version.value());
- min_sdk_attr->compiled_value = ResourceUtils::TryParseInt(min_sdk_str);
- }
- }
+ if (!UpdateManifest(artifact, config, &manifest, diag)) {
+ diag->Error(DiagMessage() << "could not update AndroidManifest.xml for "
+ << artifact_name.value());
+ return false;
}
std::string out = options.out_dir;
@@ -288,4 +261,72 @@ std::unique_ptr<ResourceTable> MultiApkGenerator::FilterTable(
return table;
}
+bool MultiApkGenerator::UpdateManifest(const Artifact& artifact,
+ const PostProcessingConfiguration& config,
+ std::unique_ptr<XmlResource>* updated_manifest,
+ IDiagnostics* diag) {
+ *updated_manifest = apk_->InflateManifest(context_);
+ XmlResource* manifest = updated_manifest->get();
+ if (manifest == nullptr) {
+ return false;
+ }
+
+ // Make sure the first element is <manifest> with package attribute.
+ xml::Element* manifest_el = manifest->root.get();
+ if (manifest_el == nullptr) {
+ return false;
+ }
+
+ if (!manifest_el->namespace_uri.empty() || manifest_el->name != "manifest") {
+ diag->Error(DiagMessage(manifest->file.source) << "root tag must be <manifest>");
+ return false;
+ }
+
+ // Update the versionCode attribute.
+ xml::Attribute* versionCode = manifest_el->FindAttribute(kSchemaAndroid, "versionCode");
+ if (versionCode == nullptr) {
+ diag->Error(DiagMessage(manifest->file.source) << "manifest must have a versionCode attribute");
+ return false;
+ }
+
+ auto* compiled_version = ValueCast<BinaryPrimitive>(versionCode->compiled_value.get());
+ if (compiled_version == nullptr) {
+ diag->Error(DiagMessage(manifest->file.source) << "versionCode is invalid");
+ return false;
+ }
+
+ int new_version = compiled_version->value.data + artifact.version;
+ versionCode->compiled_value = ResourceUtils::TryParseInt(std::to_string(new_version));
+
+ // Check to see if the minSdkVersion needs to be updated.
+ Maybe<AndroidSdk> maybe_sdk = GetAndroidSdk(artifact, config, diag);
+ if (maybe_sdk) {
+ // TODO(safarmer): Handle the rest of the Android SDK.
+ const AndroidSdk& android_sdk = maybe_sdk.value();
+
+ if (xml::Element* uses_sdk_el = manifest_el->FindChild({}, "uses-sdk")) {
+ if (xml::Attribute* min_sdk_attr =
+ uses_sdk_el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion")) {
+ // Populate with a pre-compiles attribute to we don't need to relink etc.
+ const std::string& min_sdk_str = std::to_string(android_sdk.min_sdk_version.value());
+ min_sdk_attr->compiled_value = ResourceUtils::TryParseInt(min_sdk_str);
+ } else {
+ // There was no minSdkVersion. This is strange since at this point we should have been
+ // through the manifest fixer which sets the default minSdkVersion.
+ diag->Error(DiagMessage(manifest->file.source) << "missing minSdkVersion from <uses-sdk>");
+ return false;
+ }
+ } else {
+ // No uses-sdk present. This is strange since at this point we should have been
+ // through the manifest fixer which should have added it.
+ diag->Error(DiagMessage(manifest->file.source) << "missing <uses-sdk> from <manifest>");
+ return false;
+ }
+ }
+
+ // TODO(safarmer): Check if we changed the supported screens and update the manifest.
+
+ return true;
+}
+
} // namespace aapt