Merge changes I2eef812b,I7b607192
* changes: AAPT v1 embed compile SDK version and codename into app AAPT2: Embed version of framework an app was compiled against.
This commit is contained in:
committed by
Android (Google) Code Review
commit
4ab869e1e6
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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_;
|
||||
|
||||
|
||||
@@ -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, {}, {}, {});
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user