summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/aapt/Bundle.h7
-rw-r--r--tools/aapt/Command.cpp34
-rw-r--r--tools/aapt/Resource.cpp38
-rw-r--r--tools/aapt2/cmd/Link.cpp104
-rw-r--r--tools/aapt2/link/ManifestFixer.cpp19
-rw-r--r--tools/aapt2/link/ManifestFixer.h32
-rw-r--r--tools/aapt2/link/ManifestFixer_test.cpp211
-rw-r--r--tools/aapt2/process/SymbolTable.h4
-rw-r--r--tools/aapt2/xml/XmlDom.cpp9
-rw-r--r--tools/aapt2/xml/XmlDom.h2
10 files changed, 350 insertions, 110 deletions
diff --git a/tools/aapt/Bundle.h b/tools/aapt/Bundle.h
index a93ee2e2b71d..deb9cc083eb0 100644
--- a/tools/aapt/Bundle.h
+++ b/tools/aapt/Bundle.h
@@ -68,6 +68,7 @@ public:
mSingleCrunchInputFile(NULL), mSingleCrunchOutputFile(NULL),
mBuildSharedLibrary(false),
mBuildAppAsSharedLibrary(false),
+ mCompileSdkVersion(0),
mArgc(0), mArgv(NULL)
{}
~Bundle(void) {}
@@ -123,6 +124,10 @@ public:
void setErrorOnFailedInsert(bool val) { mErrorOnFailedInsert = val; }
bool getErrorOnMissingConfigEntry() { return mErrorOnMissingConfigEntry; }
void setErrorOnMissingConfigEntry(bool val) { mErrorOnMissingConfigEntry = val; }
+ const android::String8& getCompileSdkVersionCodename() { return mCompileSdkVersionCodename; }
+ void setCompileSdkVersionCodename(const android::String8& codename) { mCompileSdkVersionCodename = codename; }
+ int getCompileSdkVersion() { return mCompileSdkVersion; }
+ void setCompileSdkVersion(int version) { mCompileSdkVersion = version; }
const android::String8& getPlatformBuildVersionCode() { return mPlatformVersionCode; }
void setPlatformBuildVersionCode(const android::String8& code) { mPlatformVersionCode = code; }
const android::String8& getPlatformBuildVersionName() { return mPlatformVersionName; }
@@ -344,6 +349,8 @@ private:
const char* mSingleCrunchOutputFile;
bool mBuildSharedLibrary;
bool mBuildAppAsSharedLibrary;
+ int mCompileSdkVersion;
+ android::String8 mCompileSdkVersionCodename;
android::String8 mPlatformVersionCode;
android::String8 mPlatformVersionName;
android::String8 mPrivateSymbolsPackage;
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index cb87737c6868..05375b0cb871 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -293,6 +293,8 @@ enum {
ISGAME_ATTR = 0x10103f4,
REQUIRED_FEATURE_ATTR = 0x1010557,
REQUIRED_NOT_FEATURE_ATTR = 0x1010558,
+ COMPILE_SDK_VERSION_ATTR = 0x01010572, // NOT FINALIZED
+ COMPILE_SDK_VERSION_CODENAME_ATTR = 0x01010573, // NOT FINALIZED
};
String8 getComponentName(String8 &pkgName, String8 &componentName) {
@@ -1247,9 +1249,37 @@ int doDump(Bundle* bundle)
splitName.string()).string());
}
- String8 platformVersionName = AaptXml::getAttribute(tree, NULL,
+ String8 platformBuildVersionName = AaptXml::getAttribute(tree, NULL,
"platformBuildVersionName");
- printf(" platformBuildVersionName='%s'", platformVersionName.string());
+ if (platformBuildVersionName != "") {
+ printf(" platformBuildVersionName='%s'", platformBuildVersionName.string());
+ }
+
+ String8 platformBuildVersionCode = AaptXml::getAttribute(tree, NULL,
+ "platformBuildVersionCode");
+ if (platformBuildVersionCode != "") {
+ printf(" platformBuildVersionCode='%s'", platformBuildVersionCode.string());
+ }
+
+ int32_t compileSdkVersion = AaptXml::getIntegerAttribute(tree,
+ COMPILE_SDK_VERSION_ATTR, &error);
+ if (error != "") {
+ SourcePos(manifestFile, tree.getLineNumber()).error(
+ "ERROR getting 'android:compileSdkVersion' attribute: %s",
+ error.string());
+ goto bail;
+ }
+ if (compileSdkVersion > 0) {
+ printf(" compileSdkVersion='%d'", compileSdkVersion);
+ }
+
+ String8 compileSdkVersionCodename = AaptXml::getResolvedAttribute(res, tree,
+ COMPILE_SDK_VERSION_CODENAME_ATTR, &error);
+ if (compileSdkVersionCodename != "") {
+ printf(" compileSdkVersionCodename='%s'", ResTable::normalizeForOutput(
+ compileSdkVersionCodename.string()).string());
+ }
+
printf("\n");
int32_t installLocation = AaptXml::getResolvedIntegerAttribute(res, tree,
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index bd2b2a36788f..ab6dced5b67d 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -918,6 +918,22 @@ status_t massageManifest(Bundle* bundle, ResourceTable* table, sp<XMLNode> root)
}
}
+
+ if (bundle->getCompileSdkVersion() != 0) {
+ if (!addTagAttribute(root, RESOURCES_ANDROID_NAMESPACE, "compileSdkVersion",
+ String8::format("%d", bundle->getCompileSdkVersion()),
+ errorOnFailedInsert, true)) {
+ return UNKNOWN_ERROR;
+ }
+ }
+
+ if (bundle->getCompileSdkVersionCodename() != "") {
+ if (!addTagAttribute(root, RESOURCES_ANDROID_NAMESPACE, "compileSdkVersionCodename",
+ bundle->getCompileSdkVersionCodename(), errorOnFailedInsert, true)) {
+ return UNKNOWN_ERROR;
+ }
+ }
+
if (bundle->getPlatformBuildVersionCode() != "") {
if (!addTagAttribute(root, "", "platformBuildVersionCode",
bundle->getPlatformBuildVersionCode(), errorOnFailedInsert, true)) {
@@ -1052,7 +1068,12 @@ enum {
VERSION_NAME_ATTR = 0x0101021c,
};
-static ssize_t extractPlatformBuildVersion(ResXMLTree& tree, Bundle* bundle) {
+static ssize_t extractPlatformBuildVersion(const ResTable& table, ResXMLTree& tree, Bundle* bundle) {
+ // First check if we should be recording the compileSdkVersion* attributes.
+ static const String16 compileSdkVersionName("android:attr/compileSdkVersion");
+ const bool useCompileSdkVersion = table.identifierForName(compileSdkVersionName.string(),
+ compileSdkVersionName.size()) != 0u;
+
size_t len;
ResXMLTree::event_code_t code;
while ((code = tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
@@ -1082,6 +1103,10 @@ static ssize_t extractPlatformBuildVersion(ResXMLTree& tree, Bundle* bundle) {
bundle->setPlatformBuildVersionCode(String8::format("%d", versionCode));
}
+ if (useCompileSdkVersion && versionCode >= 0 && bundle->getCompileSdkVersion() == 0) {
+ bundle->setCompileSdkVersion(versionCode);
+ }
+
String8 versionName = AaptXml::getAttribute(tree, VERSION_NAME_ATTR, &error);
if (error != "") {
fprintf(stderr, "ERROR: failed to get platform version name\n");
@@ -1091,6 +1116,11 @@ static ssize_t extractPlatformBuildVersion(ResXMLTree& tree, Bundle* bundle) {
if (versionName != "" && bundle->getPlatformBuildVersionName() == "") {
bundle->setPlatformBuildVersionName(versionName);
}
+
+ if (useCompileSdkVersion && versionName != ""
+ && bundle->getCompileSdkVersionCodename() == "") {
+ bundle->setCompileSdkVersionCodename(versionName);
+ }
return NO_ERROR;
}
@@ -1121,7 +1151,7 @@ static ssize_t extractPlatformBuildVersion(AssetManager& assets, Bundle* bundle)
fprintf(stderr, "ERROR: Platform AndroidManifest.xml is corrupt\n");
result = UNKNOWN_ERROR;
} else {
- result = extractPlatformBuildVersion(tree, bundle);
+ result = extractPlatformBuildVersion(assets.getResources(true), tree, bundle);
}
}
@@ -1707,7 +1737,9 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets, sp<ApkBuil
// extract them from the platform APK.
if (packageType != ResourceTable::System &&
(bundle->getPlatformBuildVersionCode() == "" ||
- bundle->getPlatformBuildVersionName() == "")) {
+ bundle->getPlatformBuildVersionName() == "" ||
+ bundle->getCompileSdkVersion() == 0 ||
+ bundle->getCompileSdkVersionCodename() == "")) {
err = extractPlatformBuildVersion(assets->getAssetManager(), bundle);
if (err != NO_ERROR) {
return UNKNOWN_ERROR;
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index d2aebfd31bbf..13dd93e83b64 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -15,6 +15,7 @@
*/
#include <sys/stat.h>
+#include <cinttypes>
#include <queue>
#include <unordered_map>
@@ -725,6 +726,30 @@ static bool LoadStableIdMap(IDiagnostics* diag, const std::string& path,
return true;
}
+static int32_t FindFrameworkAssetManagerCookie(const android::AssetManager& assets) {
+ using namespace android;
+
+ // Find the system package (0x01). AAPT always generates attributes with the type 0x01, so
+ // we're looking for the first attribute resource in the system package.
+ const ResTable& table = assets.getResources(true);
+ Res_value val;
+ ssize_t idx = table.getResource(0x01010000, &val, true);
+ if (idx != NO_ERROR) {
+ // Try as a bag.
+ const ResTable::bag_entry* entry;
+ ssize_t cnt = table.lockBag(0x01010000, &entry);
+ if (cnt >= 0) {
+ idx = entry->stringBlock;
+ }
+ table.unlockBag(entry);
+ }
+
+ if (idx < 0) {
+ return 0;
+ }
+ return table.getTableCookie(idx);
+}
+
class LinkCommand {
public:
LinkCommand(LinkContext* context, const LinkOptions& options)
@@ -734,7 +759,65 @@ class LinkCommand {
file_collection_(util::make_unique<io::FileCollection>()) {
}
+ void ExtractCompileSdkVersions(android::AssetManager* assets) {
+ using namespace android;
+
+ int32_t cookie = FindFrameworkAssetManagerCookie(*assets);
+ if (cookie == 0) {
+ // No Framework assets loaded. Not a failure.
+ return;
+ }
+
+ std::unique_ptr<Asset> manifest(
+ assets->openNonAsset(cookie, kAndroidManifestPath, Asset::AccessMode::ACCESS_BUFFER));
+ if (manifest == nullptr) {
+ // No errors.
+ return;
+ }
+
+ std::string error;
+ std::unique_ptr<xml::XmlResource> manifest_xml =
+ xml::Inflate(manifest->getBuffer(true /*wordAligned*/), manifest->getLength(), &error);
+ if (manifest_xml == nullptr) {
+ // No errors.
+ return;
+ }
+
+ xml::Attribute* attr = manifest_xml->root->FindAttribute(xml::kSchemaAndroid, "versionCode");
+ if (attr != nullptr) {
+ Maybe<std::string>& compile_sdk_version = options_.manifest_fixer_options.compile_sdk_version;
+ if (BinaryPrimitive* prim = ValueCast<BinaryPrimitive>(attr->compiled_value.get())) {
+ switch (prim->value.dataType) {
+ case Res_value::TYPE_INT_DEC:
+ compile_sdk_version = StringPrintf("%" PRId32, static_cast<int32_t>(prim->value.data));
+ break;
+ case Res_value::TYPE_INT_HEX:
+ compile_sdk_version = StringPrintf("%" PRIx32, prim->value.data);
+ break;
+ default:
+ break;
+ }
+ } else if (String* str = ValueCast<String>(attr->compiled_value.get())) {
+ compile_sdk_version = *str->value;
+ } else {
+ compile_sdk_version = attr->value;
+ }
+ }
+
+ attr = manifest_xml->root->FindAttribute(xml::kSchemaAndroid, "versionName");
+ if (attr != nullptr) {
+ Maybe<std::string>& compile_sdk_version_codename =
+ options_.manifest_fixer_options.compile_sdk_version_codename;
+ if (String* str = ValueCast<String>(attr->compiled_value.get())) {
+ compile_sdk_version_codename = *str->value;
+ } else {
+ compile_sdk_version_codename = attr->value;
+ }
+ }
+ }
+
// Creates a SymbolTable that loads symbols from the various APKs.
+ // Pre-condition: context_->GetCompilationPackage() needs to be set.
bool LoadSymbolsFromIncludePaths() {
auto asset_source = util::make_unique<AssetManagerSymbolSource>();
for (const std::string& path : options_.include_paths) {
@@ -802,6 +885,17 @@ class LinkCommand {
} else if (entry.first == kAppPackageId) {
// Capture the included base feature package.
included_feature_base_ = entry.second;
+ } else if (entry.first == kFrameworkPackageId) {
+ // Try to embed which version of the framework we're compiling against.
+ // First check if we should use compileSdkVersion at all. Otherwise compilation may fail
+ // when linking our synthesized 'android:compileSdkVersion' attribute.
+ std::unique_ptr<SymbolTable::Symbol> symbol = asset_source->FindByName(
+ ResourceName("android", ResourceType::kAttr, "compileSdkVersion"));
+ if (symbol != nullptr && symbol->is_public) {
+ // The symbol is present and public, extract the android:versionName and
+ // android:versionCode from the framework AndroidManifest.xml.
+ ExtractCompileSdkVersions(asset_source->GetAssetManager());
+ }
}
}
@@ -1535,6 +1629,12 @@ class LinkCommand {
context_->SetCompilationPackage(app_info.package);
}
+ // Now that the compilation package is set, load the dependencies. This will also extract
+ // the Android framework's versionCode and versionName, if they exist.
+ if (!LoadSymbolsFromIncludePaths()) {
+ return 1;
+ }
+
ManifestFixer manifest_fixer(options_.manifest_fixer_options);
if (!manifest_fixer.Consume(context_, manifest_xml.get())) {
return 1;
@@ -1563,10 +1663,6 @@ class LinkCommand {
}
}
- if (!LoadSymbolsFromIncludePaths()) {
- return 1;
- }
-
TableMergerOptions table_merger_options;
table_merger_options.auto_add_overlay = options_.auto_add_overlay;
table_merger_ = util::make_unique<TableMerger>(context_, &final_table_, table_merger_options);
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index eaaefd5e099a..a68df1dbc998 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -406,6 +406,25 @@ bool ManifestFixer::Consume(IAaptContext* context, xml::XmlResource* doc) {
root->InsertChild(0, std::move(uses_sdk));
}
+ if (options_.compile_sdk_version) {
+ xml::Attribute* attr = root->FindOrCreateAttribute(xml::kSchemaAndroid, "compileSdkVersion");
+
+ // Make sure we un-compile the value if it was set to something else.
+ attr->compiled_value = {};
+
+ attr->value = options_.compile_sdk_version.value();
+ }
+
+ if (options_.compile_sdk_version_codename) {
+ xml::Attribute* attr =
+ root->FindOrCreateAttribute(xml::kSchemaAndroid, "compileSdkVersionCodename");
+
+ // Make sure we un-compile the value if it was set to something else.
+ attr->compiled_value = {};
+
+ attr->value = options_.compile_sdk_version_codename.value();
+ }
+
xml::XmlActionExecutor executor;
if (!BuildRules(&executor, context->GetDiagnostics())) {
return false;
diff --git a/tools/aapt2/link/ManifestFixer.h b/tools/aapt2/link/ManifestFixer.h
index 470f65eb01c4..f5715f605b04 100644
--- a/tools/aapt2/link/ManifestFixer.h
+++ b/tools/aapt2/link/ManifestFixer.h
@@ -29,22 +29,42 @@
namespace aapt {
struct ManifestFixerOptions {
+ // The minimum SDK version to set if no 'android:minSdkVersion' is defined in a <uses-sdk> tag.
Maybe<std::string> min_sdk_version_default;
+
+ // The target SDK version to set if no 'android:targetSdkVersion' is defined in a <uses-sdk> tag.
Maybe<std::string> target_sdk_version_default;
+
+ // The Android package to use instead of the one defined in 'package' in <manifest>.
+ // This also renames all relative package/class names in the manifest to fully qualified
+ // Java names.
Maybe<std::string> rename_manifest_package;
+
+ // The Android package to use instead of the one defined in 'android:targetPackage' in
+ // <instrumentation>.
Maybe<std::string> rename_instrumentation_target_package;
+
+ // The version name to set if 'android:versionName' is not defined in <manifest>.
Maybe<std::string> version_name_default;
+
+ // The version code to set if 'android:versionCode' is not defined in <manifest>.
Maybe<std::string> version_code_default;
+
+ // The version of the framework being compiled against to set for 'android:compileSdkVersion' in
+ // the <manifest> tag.
+ Maybe<std::string> compile_sdk_version;
+
+ // The version codename of the framework being compiled against to set for
+ // 'android:compileSdkVersionCodename' in the <manifest> tag.
+ Maybe<std::string> compile_sdk_version_codename;
};
-/**
- * Verifies that the manifest is correctly formed and inserts defaults
- * where specified with ManifestFixerOptions.
- */
+// Verifies that the manifest is correctly formed and inserts defaults where specified with
+// ManifestFixerOptions.
class ManifestFixer : public IXmlResourceConsumer {
public:
- explicit ManifestFixer(const ManifestFixerOptions& options)
- : options_(options) {}
+ explicit ManifestFixer(const ManifestFixerOptions& options) : options_(options) {
+ }
bool Consume(IAaptContext* context, xml::XmlResource* doc) override;
diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp
index 40085eab9707..1320dcd2a170 100644
--- a/tools/aapt2/link/ManifestFixer_test.cpp
+++ b/tools/aapt2/link/ManifestFixer_test.cpp
@@ -19,7 +19,12 @@
#include "test/Test.h"
using ::android::StringPiece;
+using ::testing::Eq;
+using ::testing::Gt;
+using ::testing::IsNull;
+using ::testing::Ne;
using ::testing::NotNull;
+using ::testing::StrEq;
namespace aapt {
@@ -72,22 +77,20 @@ struct ManifestFixerTest : public ::testing::Test {
};
TEST_F(ManifestFixerTest, EnsureManifestIsRootTag) {
- EXPECT_EQ(nullptr, Verify("<other-tag />"));
- EXPECT_EQ(nullptr, Verify("<ns:manifest xmlns:ns=\"com\" />"));
- EXPECT_NE(nullptr, Verify("<manifest package=\"android\"></manifest>"));
+ EXPECT_THAT(Verify("<other-tag />"), IsNull());
+ EXPECT_THAT(Verify("<ns:manifest xmlns:ns=\"com\" />"), IsNull());
+ EXPECT_THAT(Verify("<manifest package=\"android\"></manifest>"), NotNull());
}
TEST_F(ManifestFixerTest, EnsureManifestHasPackage) {
- EXPECT_NE(nullptr, Verify("<manifest package=\"android\" />"));
- EXPECT_NE(nullptr, Verify("<manifest package=\"com.android\" />"));
- EXPECT_NE(nullptr, Verify("<manifest package=\"com.android.google\" />"));
- EXPECT_EQ(nullptr,
- Verify("<manifest package=\"com.android.google.Class$1\" />"));
- EXPECT_EQ(nullptr, Verify("<manifest "
- "xmlns:android=\"http://schemas.android.com/apk/"
- "res/android\" "
- "android:package=\"com.android\" />"));
- EXPECT_EQ(nullptr, Verify("<manifest package=\"@string/str\" />"));
+ EXPECT_THAT(Verify("<manifest package=\"android\" />"), NotNull());
+ EXPECT_THAT(Verify("<manifest package=\"com.android\" />"), NotNull());
+ EXPECT_THAT(Verify("<manifest package=\"com.android.google\" />"), NotNull());
+ EXPECT_THAT(Verify("<manifest package=\"com.android.google.Class$1\" />"), IsNull());
+ EXPECT_THAT(Verify("<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\" "
+ "android:package=\"com.android\" />"),
+ IsNull());
+ EXPECT_THAT(Verify("<manifest package=\"@string/str\" />"), IsNull());
}
TEST_F(ManifestFixerTest, AllowMetaData) {
@@ -105,7 +108,7 @@ TEST_F(ManifestFixerTest, AllowMetaData) {
</application>
<instrumentation android:name=".Go"><meta-data /></instrumentation>
</manifest>)EOF");
- ASSERT_NE(nullptr, doc);
+ ASSERT_THAT(doc, NotNull());
}
TEST_F(ManifestFixerTest, UseDefaultSdkVersionsIfNonePresent) {
@@ -117,21 +120,21 @@ TEST_F(ManifestFixerTest, UseDefaultSdkVersionsIfNonePresent) {
<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="21" />
</manifest>)EOF",
options);
- ASSERT_NE(nullptr, doc);
+ ASSERT_THAT(doc, NotNull());
xml::Element* el;
xml::Attribute* attr;
el = doc->root.get();
- ASSERT_NE(nullptr, el);
+ ASSERT_THAT(el, NotNull());
el = el->FindChild({}, "uses-sdk");
- ASSERT_NE(nullptr, el);
+ ASSERT_THAT(el, NotNull());
attr = el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion");
- ASSERT_NE(nullptr, attr);
- EXPECT_EQ("7", attr->value);
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("7"));
attr = el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion");
- ASSERT_NE(nullptr, attr);
- EXPECT_EQ("21", attr->value);
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("21"));
doc = VerifyWithOptions(R"EOF(
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
@@ -139,18 +142,18 @@ TEST_F(ManifestFixerTest, UseDefaultSdkVersionsIfNonePresent) {
<uses-sdk android:targetSdkVersion="21" />
</manifest>)EOF",
options);
- ASSERT_NE(nullptr, doc);
+ ASSERT_THAT(doc, NotNull());
el = doc->root.get();
- ASSERT_NE(nullptr, el);
+ ASSERT_THAT(el, NotNull());
el = el->FindChild({}, "uses-sdk");
- ASSERT_NE(nullptr, el);
+ ASSERT_THAT(el, NotNull());
attr = el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion");
- ASSERT_NE(nullptr, attr);
- EXPECT_EQ("8", attr->value);
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("8"));
attr = el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion");
- ASSERT_NE(nullptr, attr);
- EXPECT_EQ("21", attr->value);
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("21"));
doc = VerifyWithOptions(R"EOF(
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
@@ -158,35 +161,35 @@ TEST_F(ManifestFixerTest, UseDefaultSdkVersionsIfNonePresent) {
<uses-sdk />
</manifest>)EOF",
options);
- ASSERT_NE(nullptr, doc);
+ ASSERT_THAT(doc, NotNull());
el = doc->root.get();
- ASSERT_NE(nullptr, el);
+ ASSERT_THAT(el, NotNull());
el = el->FindChild({}, "uses-sdk");
- ASSERT_NE(nullptr, el);
+ ASSERT_THAT(el, NotNull());
attr = el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion");
- ASSERT_NE(nullptr, attr);
- EXPECT_EQ("8", attr->value);
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("8"));
attr = el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion");
- ASSERT_NE(nullptr, attr);
- EXPECT_EQ("22", attr->value);
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("22"));
doc = VerifyWithOptions(R"EOF(
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android" />)EOF",
options);
- ASSERT_NE(nullptr, doc);
+ ASSERT_THAT(doc, NotNull());
el = doc->root.get();
- ASSERT_NE(nullptr, el);
+ ASSERT_THAT(el, NotNull());
el = el->FindChild({}, "uses-sdk");
- ASSERT_NE(nullptr, el);
+ ASSERT_THAT(el, NotNull());
attr = el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion");
- ASSERT_NE(nullptr, attr);
- EXPECT_EQ("8", attr->value);
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("8"));
attr = el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion");
- ASSERT_NE(nullptr, attr);
- EXPECT_EQ("22", attr->value);
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("22"));
}
TEST_F(ManifestFixerTest, UsesSdkMustComeBeforeApplication) {
@@ -197,17 +200,17 @@ TEST_F(ManifestFixerTest, UsesSdkMustComeBeforeApplication) {
<application android:name=".MainApplication" />
</manifest>)EOF",
options);
- ASSERT_NE(nullptr, doc);
+ ASSERT_THAT(doc, NotNull());
xml::Element* manifest_el = doc->root.get();
- ASSERT_NE(nullptr, manifest_el);
+ ASSERT_THAT(manifest_el, NotNull());
ASSERT_EQ("manifest", manifest_el->name);
xml::Element* application_el = manifest_el->FindChild("", "application");
- ASSERT_NE(nullptr, application_el);
+ ASSERT_THAT(application_el, NotNull());
xml::Element* uses_sdk_el = manifest_el->FindChild("", "uses-sdk");
- ASSERT_NE(nullptr, uses_sdk_el);
+ ASSERT_THAT(uses_sdk_el, NotNull());
// Check that the uses_sdk_el comes before application_el in the children
// vector.
@@ -225,12 +228,12 @@ TEST_F(ManifestFixerTest, UsesSdkMustComeBeforeApplication) {
return child.get() == application_el;
});
- ASSERT_NE(manifest_el->children.end(), uses_sdk_iter);
- ASSERT_NE(manifest_el->children.end(), application_iter);
+ ASSERT_THAT(uses_sdk_iter, Ne(manifest_el->children.end()));
+ ASSERT_THAT(application_iter, Ne(manifest_el->children.end()));
// The distance should be positive, meaning uses_sdk_iter comes before
// application_iter.
- EXPECT_GT(std::distance(uses_sdk_iter, application_iter), 0);
+ EXPECT_THAT(std::distance(uses_sdk_iter, application_iter), Gt(0));
}
TEST_F(ManifestFixerTest, RenameManifestPackageAndFullyQualifyClasses) {
@@ -247,48 +250,49 @@ TEST_F(ManifestFixerTest, RenameManifestPackageAndFullyQualifyClasses) {
</application>
</manifest>)EOF",
options);
- ASSERT_NE(nullptr, doc);
+ ASSERT_THAT(doc, NotNull());
xml::Element* manifest_el = doc->root.get();
- ASSERT_NE(nullptr, manifest_el);
+ ASSERT_THAT(manifest_el, NotNull());
xml::Attribute* attr = nullptr;
attr = manifest_el->FindAttribute({}, "package");
- ASSERT_NE(nullptr, attr);
- EXPECT_EQ(std::string("com.android"), attr->value);
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("com.android"));
xml::Element* uses_split_el = manifest_el->FindChild({}, "uses-split");
- ASSERT_NE(nullptr, uses_split_el);
+ ASSERT_THAT(uses_split_el, NotNull());
attr = uses_split_el->FindAttribute(xml::kSchemaAndroid, "name");
- ASSERT_NE(nullptr, attr);
- EXPECT_EQ(std::string("feature_a"), attr->value);
+ ASSERT_THAT(attr, NotNull());
+ // This should NOT have been affected.
+ EXPECT_THAT(attr->value, StrEq("feature_a"));
xml::Element* application_el = manifest_el->FindChild({}, "application");
- ASSERT_NE(nullptr, application_el);
+ ASSERT_THAT(application_el, NotNull());
attr = application_el->FindAttribute(xml::kSchemaAndroid, "name");
- ASSERT_NE(nullptr, attr);
- EXPECT_EQ(std::string("android.MainApplication"), attr->value);
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("android.MainApplication"));
attr = application_el->FindAttribute({}, "text");
- ASSERT_NE(nullptr, attr);
- EXPECT_EQ(std::string("hello"), attr->value);
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("hello"));
xml::Element* el;
el = application_el->FindChild({}, "activity");
- ASSERT_NE(nullptr, el);
+ ASSERT_THAT(el, NotNull());
attr = el->FindAttribute(xml::kSchemaAndroid, "name");
- ASSERT_NE(nullptr, el);
- EXPECT_EQ(std::string("android.activity.Start"), attr->value);
+ ASSERT_THAT(el, NotNull());
+ EXPECT_THAT(attr->value, StrEq("android.activity.Start"));
el = application_el->FindChild({}, "receiver");
- ASSERT_NE(nullptr, el);
+ ASSERT_THAT(el, NotNull());
attr = el->FindAttribute(xml::kSchemaAndroid, "name");
- ASSERT_NE(nullptr, el);
- EXPECT_EQ(std::string("com.google.android.Receiver"), attr->value);
+ ASSERT_THAT(el, NotNull());
+ EXPECT_THAT(attr->value, StrEq("com.google.android.Receiver"));
}
TEST_F(ManifestFixerTest,
@@ -302,19 +306,19 @@ TEST_F(ManifestFixerTest,
<instrumentation android:name=".TestRunner" android:targetPackage="android" />
</manifest>)EOF",
options);
- ASSERT_NE(nullptr, doc);
+ ASSERT_THAT(doc, NotNull());
xml::Element* manifest_el = doc->root.get();
- ASSERT_NE(nullptr, manifest_el);
+ ASSERT_THAT(manifest_el, NotNull());
xml::Element* instrumentation_el =
manifest_el->FindChild({}, "instrumentation");
- ASSERT_NE(nullptr, instrumentation_el);
+ ASSERT_THAT(instrumentation_el, NotNull());
xml::Attribute* attr =
instrumentation_el->FindAttribute(xml::kSchemaAndroid, "targetPackage");
- ASSERT_NE(nullptr, attr);
- EXPECT_EQ(std::string("com.android"), attr->value);
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("com.android"));
}
TEST_F(ManifestFixerTest, UseDefaultVersionNameAndCode) {
@@ -326,41 +330,39 @@ TEST_F(ManifestFixerTest, UseDefaultVersionNameAndCode) {
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android" />)EOF",
options);
- ASSERT_NE(nullptr, doc);
+ ASSERT_THAT(doc, NotNull());
xml::Element* manifest_el = doc->root.get();
- ASSERT_NE(nullptr, manifest_el);
+ ASSERT_THAT(manifest_el, NotNull());
xml::Attribute* attr =
manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
- ASSERT_NE(nullptr, attr);
- EXPECT_EQ(std::string("Beta"), attr->value);
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("Beta"));
attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
- ASSERT_NE(nullptr, attr);
- EXPECT_EQ(std::string("0x10000000"), attr->value);
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("0x10000000"));
}
TEST_F(ManifestFixerTest, EnsureManifestAttributesAreTyped) {
- EXPECT_EQ(nullptr,
- Verify("<manifest package=\"android\" coreApp=\"hello\" />"));
- EXPECT_EQ(nullptr,
- Verify("<manifest package=\"android\" coreApp=\"1dp\" />"));
+ EXPECT_THAT(Verify("<manifest package=\"android\" coreApp=\"hello\" />"), IsNull());
+ EXPECT_THAT(Verify("<manifest package=\"android\" coreApp=\"1dp\" />"), IsNull());
std::unique_ptr<xml::XmlResource> doc =
Verify("<manifest package=\"android\" coreApp=\"true\" />");
- ASSERT_NE(nullptr, doc);
+ ASSERT_THAT(doc, NotNull());
xml::Element* el = doc->root.get();
- ASSERT_NE(nullptr, el);
+ ASSERT_THAT(el, NotNull());
- EXPECT_EQ("manifest", el->name);
+ EXPECT_THAT(el->name, StrEq("manifest"));
xml::Attribute* attr = el->FindAttribute("", "coreApp");
- ASSERT_NE(nullptr, attr);
+ ASSERT_THAT(attr, NotNull());
- EXPECT_NE(nullptr, attr->compiled_value);
- EXPECT_NE(nullptr, ValueCast<BinaryPrimitive>(attr->compiled_value.get()));
+ EXPECT_THAT(attr->compiled_value, NotNull());
+ EXPECT_THAT(ValueCast<BinaryPrimitive>(attr->compiled_value.get()), NotNull());
}
TEST_F(ManifestFixerTest, UsesFeatureMustHaveNameOrGlEsVersion) {
@@ -375,21 +377,21 @@ TEST_F(ManifestFixerTest, UsesFeatureMustHaveNameOrGlEsVersion) {
<uses-feature android:glEsVersion="2" />
</feature-group>
</manifest>)EOF";
- EXPECT_NE(nullptr, Verify(input));
+ EXPECT_THAT(Verify(input), NotNull());
input = R"EOF(
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android">
<uses-feature android:name="feature" android:glEsVersion="1" />
</manifest>)EOF";
- EXPECT_EQ(nullptr, Verify(input));
+ EXPECT_THAT(Verify(input), IsNull());
input = R"EOF(
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android">
<uses-feature />
</manifest>)EOF";
- EXPECT_EQ(nullptr, Verify(input));
+ EXPECT_THAT(Verify(input), IsNull());
input = R"EOF(
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
@@ -398,7 +400,7 @@ TEST_F(ManifestFixerTest, UsesFeatureMustHaveNameOrGlEsVersion) {
<uses-feature android:name="feature" android:glEsVersion="1" />
</feature-group>
</manifest>)EOF";
- EXPECT_EQ(nullptr, Verify(input));
+ EXPECT_THAT(Verify(input), IsNull());
input = R"EOF(
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
@@ -407,7 +409,7 @@ TEST_F(ManifestFixerTest, UsesFeatureMustHaveNameOrGlEsVersion) {
<uses-feature />
</feature-group>
</manifest>)EOF";
- EXPECT_EQ(nullptr, Verify(input));
+ EXPECT_THAT(Verify(input), IsNull());
}
TEST_F(ManifestFixerTest, IgnoreNamespacedElements) {
@@ -416,7 +418,7 @@ TEST_F(ManifestFixerTest, IgnoreNamespacedElements) {
package="android">
<special:tag whoo="true" xmlns:special="http://google.com" />
</manifest>)EOF";
- EXPECT_NE(nullptr, Verify(input));
+ EXPECT_THAT(Verify(input), NotNull());
}
TEST_F(ManifestFixerTest, DoNotIgnoreNonNamespacedElements) {
@@ -425,7 +427,7 @@ TEST_F(ManifestFixerTest, DoNotIgnoreNonNamespacedElements) {
package="android">
<tag whoo="true" />
</manifest>)EOF";
- EXPECT_EQ(nullptr, Verify(input));
+ EXPECT_THAT(Verify(input), IsNull());
}
TEST_F(ManifestFixerTest, SupportKeySets) {
@@ -446,4 +448,23 @@ TEST_F(ManifestFixerTest, SupportKeySets) {
EXPECT_THAT(Verify(input), NotNull());
}
+TEST_F(ManifestFixerTest, InsertCompileSdkVersions) {
+ std::string input = R"(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android" />)";
+ ManifestFixerOptions options;
+ options.compile_sdk_version = {"28"};
+ options.compile_sdk_version_codename = {"P"};
+
+ std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options);
+ ASSERT_THAT(manifest, NotNull());
+
+ xml::Attribute* attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersion");
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("28"));
+
+ attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersionCodename");
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("P"));
+}
+
} // namespace aapt
diff --git a/tools/aapt2/process/SymbolTable.h b/tools/aapt2/process/SymbolTable.h
index 4a2181e0b344..b676efb8d025 100644
--- a/tools/aapt2/process/SymbolTable.h
+++ b/tools/aapt2/process/SymbolTable.h
@@ -199,6 +199,10 @@ class AssetManagerSymbolSource : public ISymbolSource {
std::unique_ptr<SymbolTable::Symbol> FindByReference(
const Reference& ref) override;
+ android::AssetManager* GetAssetManager() {
+ return &assets_;
+ }
+
private:
android::AssetManager assets_;
diff --git a/tools/aapt2/xml/XmlDom.cpp b/tools/aapt2/xml/XmlDom.cpp
index b0cf44accafa..fddb6b8c5d87 100644
--- a/tools/aapt2/xml/XmlDom.cpp
+++ b/tools/aapt2/xml/XmlDom.cpp
@@ -418,6 +418,15 @@ const Attribute* Element::FindAttribute(const StringPiece& ns, const StringPiece
return nullptr;
}
+Attribute* Element::FindOrCreateAttribute(const StringPiece& ns, const StringPiece& name) {
+ Attribute* attr = FindAttribute(ns, name);
+ if (attr == nullptr) {
+ attributes.push_back(Attribute{ns.to_string(), name.to_string()});
+ attr = &attributes.back();
+ }
+ return attr;
+}
+
Element* Element::FindChild(const StringPiece& ns, const StringPiece& name) {
return FindChildWithAttribute(ns, name, {}, {}, {});
}
diff --git a/tools/aapt2/xml/XmlDom.h b/tools/aapt2/xml/XmlDom.h
index cf06ba5cc50e..8f3829611f30 100644
--- a/tools/aapt2/xml/XmlDom.h
+++ b/tools/aapt2/xml/XmlDom.h
@@ -100,6 +100,8 @@ class Element : public Node {
Attribute* FindAttribute(const android::StringPiece& ns, const android::StringPiece& name);
const Attribute* FindAttribute(const android::StringPiece& ns,
const android::StringPiece& name) const;
+ Attribute* FindOrCreateAttribute(const android::StringPiece& ns,
+ const android::StringPiece& name);
Element* FindChild(const android::StringPiece& ns, const android::StringPiece& name);
const Element* FindChild(const android::StringPiece& ns, const android::StringPiece& name) const;