Merge "AAPT2: Auto-version adaptive-icon XML"
This commit is contained in:
committed by
Android (Google) Code Review
commit
2fa4a346ec
@@ -1901,8 +1901,6 @@ int ResTable_config::compare(const ResTable_config& o) const {
|
||||
if (diff != 0) return diff;
|
||||
diff = (int32_t)(screenSize - o.screenSize);
|
||||
if (diff != 0) return diff;
|
||||
diff = (int32_t)(version - o.version);
|
||||
if (diff != 0) return diff;
|
||||
diff = (int32_t)(screenLayout - o.screenLayout);
|
||||
if (diff != 0) return diff;
|
||||
diff = (int32_t)(screenLayout2 - o.screenLayout2);
|
||||
@@ -1914,6 +1912,11 @@ int ResTable_config::compare(const ResTable_config& o) const {
|
||||
diff = (int32_t)(smallestScreenWidthDp - o.smallestScreenWidthDp);
|
||||
if (diff != 0) return diff;
|
||||
diff = (int32_t)(screenSizeDp - o.screenSizeDp);
|
||||
if (diff != 0) return diff;
|
||||
|
||||
// Version MUST be last to ensure that a sorted list of configurations will always have the
|
||||
// versions beside each other.
|
||||
diff = (int32_t)(version - o.version);
|
||||
return (int)diff;
|
||||
}
|
||||
|
||||
|
||||
@@ -987,4 +987,8 @@ bool ConfigDescription::IsCompatibleWith(const ConfigDescription& o) const {
|
||||
return !ConflictsWith(o) && !Dominates(o) && !o.Dominates(*this);
|
||||
}
|
||||
|
||||
::std::ostream& operator<<(::std::ostream& out, const ConfigDescription& o) {
|
||||
return out << o.toString().string();
|
||||
}
|
||||
|
||||
} // namespace aapt
|
||||
|
||||
@@ -24,30 +24,22 @@
|
||||
|
||||
namespace aapt {
|
||||
|
||||
/*
|
||||
* Subclass of ResTable_config that adds convenient
|
||||
* initialization and comparison methods.
|
||||
*/
|
||||
// Subclass of ResTable_config that adds convenient
|
||||
// initialization and comparison methods.
|
||||
struct ConfigDescription : public android::ResTable_config {
|
||||
/**
|
||||
* Returns an immutable default config.
|
||||
*/
|
||||
// Returns an immutable default config.
|
||||
static const ConfigDescription& DefaultConfig();
|
||||
|
||||
/*
|
||||
* Parse a string of the form 'fr-sw600dp-land' and fill in the
|
||||
* given ResTable_config with resulting configuration parameters.
|
||||
*
|
||||
* The resulting configuration has the appropriate sdkVersion defined
|
||||
* for backwards compatibility.
|
||||
*/
|
||||
// Parse a string of the form 'fr-sw600dp-land' and fill in the
|
||||
// given ResTable_config with resulting configuration parameters.
|
||||
//
|
||||
// The resulting configuration has the appropriate sdkVersion defined
|
||||
// for backwards compatibility.
|
||||
static bool Parse(const android::StringPiece& str, ConfigDescription* out = nullptr);
|
||||
|
||||
/**
|
||||
* If the configuration uses an axis that was added after
|
||||
* the original Android release, make sure the SDK version
|
||||
* is set accordingly.
|
||||
*/
|
||||
// If the configuration uses an axis that was added after
|
||||
// the original Android release, make sure the SDK version
|
||||
// is set accordingly.
|
||||
static void ApplyVersionForCompatibility(ConfigDescription* config);
|
||||
|
||||
ConfigDescription();
|
||||
@@ -61,38 +53,30 @@ struct ConfigDescription : public android::ResTable_config {
|
||||
|
||||
ConfigDescription CopyWithoutSdkVersion() const;
|
||||
|
||||
/**
|
||||
* A configuration X dominates another configuration Y, if X has at least the
|
||||
* precedence of Y and X is strictly more general than Y: for any type defined
|
||||
* by X, the same type is defined by Y with a value equal to or, in the case
|
||||
* of ranges, more specific than that of X.
|
||||
*
|
||||
* For example, the configuration 'en-w800dp' dominates 'en-rGB-w1024dp'. It
|
||||
* does not dominate 'fr', 'en-w720dp', or 'mcc001-en-w800dp'.
|
||||
*/
|
||||
// A configuration X dominates another configuration Y, if X has at least the
|
||||
// precedence of Y and X is strictly more general than Y: for any type defined
|
||||
// by X, the same type is defined by Y with a value equal to or, in the case
|
||||
// of ranges, more specific than that of X.
|
||||
//
|
||||
// For example, the configuration 'en-w800dp' dominates 'en-rGB-w1024dp'. It
|
||||
// does not dominate 'fr', 'en-w720dp', or 'mcc001-en-w800dp'.
|
||||
bool Dominates(const ConfigDescription& o) const;
|
||||
|
||||
/**
|
||||
* Returns true if this configuration defines a more important configuration
|
||||
* parameter than o. For example, "en" has higher precedence than "v23",
|
||||
* whereas "en" has the same precedence as "en-v23".
|
||||
*/
|
||||
// Returns true if this configuration defines a more important configuration
|
||||
// parameter than o. For example, "en" has higher precedence than "v23",
|
||||
// whereas "en" has the same precedence as "en-v23".
|
||||
bool HasHigherPrecedenceThan(const ConfigDescription& o) const;
|
||||
|
||||
/**
|
||||
* A configuration conflicts with another configuration if both
|
||||
* configurations define an incompatible configuration parameter. An
|
||||
* incompatible configuration parameter is a non-range, non-density parameter
|
||||
* that is defined in both configurations as a different, non-default value.
|
||||
*/
|
||||
// A configuration conflicts with another configuration if both
|
||||
// configurations define an incompatible configuration parameter. An
|
||||
// incompatible configuration parameter is a non-range, non-density parameter
|
||||
// that is defined in both configurations as a different, non-default value.
|
||||
bool ConflictsWith(const ConfigDescription& o) const;
|
||||
|
||||
/**
|
||||
* A configuration is compatible with another configuration if both
|
||||
* configurations can match a common concrete device configuration and are
|
||||
* unrelated by domination. For example, land-v11 conflicts with port-v21
|
||||
* but is compatible with v21 (both land-v11 and v21 would match en-land-v23).
|
||||
*/
|
||||
// A configuration is compatible with another configuration if both
|
||||
// configurations can match a common concrete device configuration and are
|
||||
// unrelated by domination. For example, land-v11 conflicts with port-v21
|
||||
// but is compatible with v21 (both land-v11 and v21 would match en-land-v23).
|
||||
bool IsCompatibleWith(const ConfigDescription& o) const;
|
||||
|
||||
bool MatchWithDensity(const ConfigDescription& o) const;
|
||||
@@ -105,6 +89,8 @@ struct ConfigDescription : public android::ResTable_config {
|
||||
bool operator>(const ConfigDescription& o) const;
|
||||
};
|
||||
|
||||
::std::ostream& operator<<(::std::ostream& out, const ConfigDescription& o);
|
||||
|
||||
inline ConfigDescription::ConfigDescription() {
|
||||
memset(this, 0, sizeof(*this));
|
||||
size = sizeof(android::ResTable_config);
|
||||
@@ -123,15 +109,13 @@ inline ConfigDescription::ConfigDescription(ConfigDescription&& o) {
|
||||
*this = o;
|
||||
}
|
||||
|
||||
inline ConfigDescription& ConfigDescription::operator=(
|
||||
const android::ResTable_config& o) {
|
||||
inline ConfigDescription& ConfigDescription::operator=(const android::ResTable_config& o) {
|
||||
*static_cast<android::ResTable_config*>(this) = o;
|
||||
size = sizeof(android::ResTable_config);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline ConfigDescription& ConfigDescription::operator=(
|
||||
const ConfigDescription& o) {
|
||||
inline ConfigDescription& ConfigDescription::operator=(const ConfigDescription& o) {
|
||||
*static_cast<android::ResTable_config*>(this) = o;
|
||||
return *this;
|
||||
}
|
||||
@@ -141,8 +125,7 @@ inline ConfigDescription& ConfigDescription::operator=(ConfigDescription&& o) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline bool ConfigDescription::MatchWithDensity(
|
||||
const ConfigDescription& o) const {
|
||||
inline bool ConfigDescription::MatchWithDensity(const ConfigDescription& o) const {
|
||||
return match(o) && (density == 0 || density == o.density);
|
||||
}
|
||||
|
||||
@@ -170,11 +153,6 @@ inline bool ConfigDescription::operator>(const ConfigDescription& o) const {
|
||||
return compare(o) > 0;
|
||||
}
|
||||
|
||||
inline ::std::ostream& operator<<(::std::ostream& out,
|
||||
const ConfigDescription& o) {
|
||||
return out << o.toString().string();
|
||||
}
|
||||
|
||||
} // namespace aapt
|
||||
|
||||
#endif // AAPT_CONFIG_DESCRIPTION_H
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
#include "unflatten/BinaryResourceParser.h"
|
||||
#include "util/Files.h"
|
||||
#include "xml/XmlDom.h"
|
||||
#include "xml/XmlUtil.h"
|
||||
|
||||
using android::StringPiece;
|
||||
using android::base::StringPrintf;
|
||||
@@ -342,16 +343,18 @@ class ResourceFileFlattener {
|
||||
ConfigDescription config;
|
||||
|
||||
// The entry this file came from.
|
||||
ResourceEntry* entry;
|
||||
ResourceEntry* entry = nullptr;
|
||||
|
||||
// The file to copy as-is.
|
||||
io::IFile* file_to_copy;
|
||||
io::IFile* file_to_copy = nullptr;
|
||||
|
||||
// The XML to process and flatten.
|
||||
std::unique_ptr<xml::XmlResource> xml_to_flatten;
|
||||
|
||||
// The destination to write this file to.
|
||||
std::string dst_path;
|
||||
|
||||
bool skip_versioning = false;
|
||||
};
|
||||
|
||||
uint32_t GetCompressionFlags(const StringPiece& str);
|
||||
@@ -431,19 +434,6 @@ uint32_t ResourceFileFlattener::GetCompressionFlags(const StringPiece& str) {
|
||||
return ArchiveEntry::kCompress;
|
||||
}
|
||||
|
||||
static bool IsTransitionElement(const std::string& name) {
|
||||
return name == "fade" || name == "changeBounds" || name == "slide" || name == "explode" ||
|
||||
name == "changeImageTransform" || name == "changeTransform" ||
|
||||
name == "changeClipBounds" || name == "autoTransition" || name == "recolor" ||
|
||||
name == "changeScroll" || name == "transitionSet" || name == "transition" ||
|
||||
name == "transitionManager";
|
||||
}
|
||||
|
||||
static bool IsVectorElement(const std::string& name) {
|
||||
return name == "vector" || name == "animated-vector" || name == "pathInterpolator" ||
|
||||
name == "objectAnimator";
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::vector<T> make_singleton_vec(T&& val) {
|
||||
std::vector<T> vec;
|
||||
@@ -476,21 +466,10 @@ std::vector<std::unique_ptr<xml::XmlResource>> ResourceFileFlattener::LinkAndVer
|
||||
}
|
||||
}
|
||||
|
||||
if (options_.no_auto_version) {
|
||||
if (options_.no_auto_version || file_op->skip_versioning) {
|
||||
return make_singleton_vec(std::move(file_op->xml_to_flatten));
|
||||
}
|
||||
|
||||
if (options_.no_version_vectors || options_.no_version_transitions) {
|
||||
// Skip this if it is a vector or animated-vector.
|
||||
xml::Element* el = xml::FindRootElement(doc);
|
||||
if (el && el->namespace_uri.empty()) {
|
||||
if ((options_.no_version_vectors && IsVectorElement(el->name)) ||
|
||||
(options_.no_version_transitions && IsTransitionElement(el->name))) {
|
||||
return make_singleton_vec(std::move(file_op->xml_to_flatten));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const ConfigDescription& config = file_op->config;
|
||||
ResourceEntry* entry = file_op->entry;
|
||||
|
||||
@@ -504,15 +483,26 @@ bool ResourceFileFlattener::Flatten(ResourceTable* table, IArchiveWriter* archiv
|
||||
bool error = false;
|
||||
std::map<std::pair<ConfigDescription, StringPiece>, FileOperation> config_sorted_files;
|
||||
|
||||
int tag_version_options = 0;
|
||||
if (options_.no_version_vectors) {
|
||||
tag_version_options |= xml::kNoVersionVector;
|
||||
}
|
||||
|
||||
if (options_.no_version_transitions) {
|
||||
tag_version_options |= xml::kNoVersionTransition;
|
||||
}
|
||||
|
||||
for (auto& pkg : table->packages) {
|
||||
for (auto& type : pkg->types) {
|
||||
// Sort by config and name, so that we get better locality in the zip file.
|
||||
config_sorted_files.clear();
|
||||
std::queue<FileOperation> file_operations;
|
||||
|
||||
// Populate the queue with all files in the ResourceTable.
|
||||
for (auto& entry : type->entries) {
|
||||
for (auto& config_value : entry->values) {
|
||||
const auto values_end = entry->values.end();
|
||||
for (auto values_iter = entry->values.begin(); values_iter != values_end; ++values_iter) {
|
||||
ResourceConfigValue* config_value = values_iter->get();
|
||||
|
||||
// WARNING! Do not insert or remove any resources while executing in this scope. It will
|
||||
// corrupt the iteration order.
|
||||
|
||||
@@ -554,6 +544,44 @@ bool ResourceFileFlattener::Flatten(ResourceTable* table, IArchiveWriter* archiv
|
||||
file_op.xml_to_flatten->file.config = config_value->config;
|
||||
file_op.xml_to_flatten->file.source = file_ref->GetSource();
|
||||
file_op.xml_to_flatten->file.name = ResourceName(pkg->name, type->type, entry->name);
|
||||
|
||||
// Check if this file needs to be versioned based on tag rules.
|
||||
xml::Element* root_el = xml::FindRootElement(file_op.xml_to_flatten.get());
|
||||
if (root_el == nullptr) {
|
||||
context_->GetDiagnostics()->Error(DiagMessage(file->GetSource())
|
||||
<< "failed to find the root XML element");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (root_el->namespace_uri.empty()) {
|
||||
if (Maybe<xml::TagApiVersionResult> result =
|
||||
xml::GetXmlTagApiVersion(root_el->name, tag_version_options)) {
|
||||
file_op.skip_versioning = result.value().skip_version;
|
||||
if (result.value().api_version && config_value->config.sdkVersion == 0u) {
|
||||
const ApiVersion min_tag_version = result.value().api_version.value();
|
||||
// Only version it if it doesn't specify its own version and the version is
|
||||
// greater than the minSdk.
|
||||
const util::Range<ApiVersion> valid_range{
|
||||
context_->GetMinSdkVersion() + 1,
|
||||
FindNextApiVersionForConfigInSortedVector(values_iter, values_end)};
|
||||
if (valid_range.Contains(min_tag_version)) {
|
||||
// Update the configurations. The iteration order will not be affected
|
||||
// since sdkVersions in ConfigDescriptions are the last property compared
|
||||
// in the sort function.
|
||||
if (context_->IsVerbose()) {
|
||||
context_->GetDiagnostics()->Note(DiagMessage(config_value->value->GetSource())
|
||||
<< "auto-versioning XML resource to API "
|
||||
<< min_tag_version);
|
||||
}
|
||||
const_cast<ConfigDescription&>(config_value->config).sdkVersion =
|
||||
static_cast<uint16_t>(min_tag_version);
|
||||
file_op.config.sdkVersion = static_cast<uint16_t>(min_tag_version);
|
||||
file_op.xml_to_flatten->file.config.sdkVersion =
|
||||
static_cast<uint16_t>(min_tag_version);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE(adamlesinski): Explicitly construct a StringPiece here, or
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2017 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.
|
||||
-->
|
||||
|
||||
<adaptive-icon xmlns:android="http://schema.android.com/apk/res/android">
|
||||
<background android:drawable="@android:color/white" />
|
||||
<foreground android:drawable="@drawable/image" />
|
||||
</adaptive-icon>
|
||||
@@ -34,6 +34,19 @@ bool ShouldGenerateVersionedResource(const ResourceEntry* entry, const ConfigDes
|
||||
return sdk_version_to_generate < FindNextApiVersionForConfig(entry, config);
|
||||
}
|
||||
|
||||
ApiVersion FindNextApiVersionForConfigInSortedVector(
|
||||
std::vector<std::unique_ptr<ResourceConfigValue>>::const_iterator start,
|
||||
std::vector<std::unique_ptr<ResourceConfigValue>>::const_iterator end) {
|
||||
const ConfigDescription start_config = (*start)->config.CopyWithoutSdkVersion();
|
||||
++start;
|
||||
if (start != end) {
|
||||
if ((*start)->config.CopyWithoutSdkVersion() == start_config) {
|
||||
return static_cast<ApiVersion>((*start)->config.sdkVersion);
|
||||
}
|
||||
}
|
||||
return std::numeric_limits<ApiVersion>::max();
|
||||
}
|
||||
|
||||
ApiVersion FindNextApiVersionForConfig(const ResourceEntry* entry,
|
||||
const ConfigDescription& config) {
|
||||
const auto end_iter = entry->values.end();
|
||||
@@ -46,25 +59,7 @@ ApiVersion FindNextApiVersionForConfig(const ResourceEntry* entry,
|
||||
|
||||
// The source config came from this list, so it should be here.
|
||||
CHECK(iter != entry->values.end());
|
||||
++iter;
|
||||
|
||||
// The next configuration either only varies in sdkVersion, or it is completely different
|
||||
// and therefore incompatible. If it is incompatible, we must generate the versioned resource.
|
||||
|
||||
// NOTE: The ordering of configurations takes sdkVersion as higher precedence than other
|
||||
// qualifiers, so we need to iterate through the entire list to be sure there
|
||||
// are no higher sdk level versions of this resource.
|
||||
ConfigDescription temp_config(config);
|
||||
for (; iter != end_iter; ++iter) {
|
||||
temp_config.sdkVersion = (*iter)->config.sdkVersion;
|
||||
if (temp_config == (*iter)->config) {
|
||||
// The two configs are the same, return the sdkVersion.
|
||||
return (*iter)->config.sdkVersion;
|
||||
}
|
||||
}
|
||||
|
||||
// Didn't find another config with a different sdk version, so return the highest possible value.
|
||||
return std::numeric_limits<ApiVersion>::max();
|
||||
return FindNextApiVersionForConfigInSortedVector(iter, end_iter);
|
||||
}
|
||||
|
||||
bool AutoVersioner::Consume(IAaptContext* context, ResourceTable* table) {
|
||||
|
||||
@@ -42,8 +42,8 @@ TEST(AutoVersionerTest, GenerateVersionedResourceWhenHigherVersionExists) {
|
||||
|
||||
ResourceEntry entry("foo");
|
||||
entry.values.push_back(util::make_unique<ResourceConfigValue>(ConfigDescription::DefaultConfig(), ""));
|
||||
entry.values.push_back(util::make_unique<ResourceConfigValue>(sw600dp_v13_config, ""));
|
||||
entry.values.push_back(util::make_unique<ResourceConfigValue>(v21_config, ""));
|
||||
entry.values.push_back(util::make_unique<ResourceConfigValue>(sw600dp_v13_config, ""));
|
||||
|
||||
EXPECT_TRUE(ShouldGenerateVersionedResource(&entry, ConfigDescription::DefaultConfig(), 17));
|
||||
EXPECT_FALSE(ShouldGenerateVersionedResource(&entry, ConfigDescription::DefaultConfig(), 22));
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "android-base/macros.h"
|
||||
|
||||
#include "Resource.h"
|
||||
#include "ResourceTable.h"
|
||||
#include "SdkConstants.h"
|
||||
#include "process/IResourceTableConsumer.h"
|
||||
#include "xml/XmlDom.h"
|
||||
@@ -41,17 +42,19 @@ struct CallSite {
|
||||
ResourceNameRef resource;
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines whether a versioned resource should be created. If a versioned
|
||||
* resource already exists, it takes precedence.
|
||||
*/
|
||||
// Determines whether a versioned resource should be created. If a versioned resource already
|
||||
// exists, it takes precedence.
|
||||
bool ShouldGenerateVersionedResource(const ResourceEntry* entry, const ConfigDescription& config,
|
||||
const ApiVersion sdk_version_to_generate);
|
||||
|
||||
// Finds the next largest ApiVersion of the config which is identical to the given config except
|
||||
// for sdkVersion.
|
||||
// Finds the next largest ApiVersion of `config` for values defined for `entry`.
|
||||
ApiVersion FindNextApiVersionForConfig(const ResourceEntry* entry, const ConfigDescription& config);
|
||||
|
||||
// Finds the next largest ApiVersion of the config pointed to by the iterator `start`.
|
||||
ApiVersion FindNextApiVersionForConfigInSortedVector(
|
||||
std::vector<std::unique_ptr<ResourceConfigValue>>::const_iterator start,
|
||||
std::vector<std::unique_ptr<ResourceConfigValue>>::const_iterator end);
|
||||
|
||||
class AutoVersioner : public IResourceTableConsumer {
|
||||
public:
|
||||
AutoVersioner() = default;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
(bug 62839863)
|
||||
- Fixed issue where Java classes referenced from fragments and menus were not added to
|
||||
the set of Proguard keep rules. (bug 62216174)
|
||||
- Automatically version XML `<adaptive-icon>` resources to v26. (bug 62316340)
|
||||
|
||||
## Version 2.17
|
||||
### `aapt2 ...`
|
||||
|
||||
@@ -38,6 +38,7 @@ namespace aapt {
|
||||
|
||||
DEFINE_HAS_BINARY_OP_TRAIT(has_eq_op, ==);
|
||||
DEFINE_HAS_BINARY_OP_TRAIT(has_lt_op, <);
|
||||
DEFINE_HAS_BINARY_OP_TRAIT(has_lte_op, <=);
|
||||
|
||||
/**
|
||||
* Type trait that checks if two types can be equated (==) and compared (<).
|
||||
|
||||
@@ -48,6 +48,11 @@ template <typename T>
|
||||
struct Range {
|
||||
T start;
|
||||
T end;
|
||||
|
||||
typename std::enable_if<has_lte_op<const T, const T>::value, bool>::type Contains(
|
||||
const T& t) const {
|
||||
return start <= t && t < end;
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<std::string> Split(const android::StringPiece& str, char sep);
|
||||
|
||||
@@ -80,5 +80,65 @@ void TransformReferenceFromNamespace(IPackageDeclStack* decl_stack,
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct TagCompat {
|
||||
ApiVersion api_version;
|
||||
|
||||
enum class XmlType {
|
||||
kVector,
|
||||
kTransition,
|
||||
kAdaptiveIcon,
|
||||
};
|
||||
|
||||
XmlType type;
|
||||
};
|
||||
|
||||
std::unordered_map<StringPiece, TagCompat> sTagVersions = {
|
||||
{"fade", {SDK_LOLLIPOP, TagCompat::XmlType::kTransition}},
|
||||
{"changeBounds", {SDK_LOLLIPOP, TagCompat::XmlType::kTransition}},
|
||||
{"slide", {SDK_LOLLIPOP, TagCompat::XmlType::kTransition}},
|
||||
{"explode", {SDK_LOLLIPOP, TagCompat::XmlType::kTransition}},
|
||||
{"changeImageTransform", {SDK_LOLLIPOP, TagCompat::XmlType::kTransition}},
|
||||
{"changeTransform", {SDK_LOLLIPOP, TagCompat::XmlType::kTransition}},
|
||||
{"changeClipBounds", {SDK_LOLLIPOP, TagCompat::XmlType::kTransition}},
|
||||
{"autoTransition", {SDK_LOLLIPOP, TagCompat::XmlType::kTransition}},
|
||||
{"recolor", {SDK_LOLLIPOP, TagCompat::XmlType::kTransition}},
|
||||
{"changeScroll", {SDK_LOLLIPOP, TagCompat::XmlType::kTransition}},
|
||||
{"transitionSet", {SDK_LOLLIPOP, TagCompat::XmlType::kTransition}},
|
||||
{"transition", {SDK_LOLLIPOP, TagCompat::XmlType::kTransition}},
|
||||
{"transitionManager", {SDK_LOLLIPOP, TagCompat::XmlType::kTransition}},
|
||||
|
||||
{"vector", {SDK_LOLLIPOP, TagCompat::XmlType::kVector}},
|
||||
{"animated-vector", {SDK_LOLLIPOP, TagCompat::XmlType::kVector}},
|
||||
{"pathInterpolator", {SDK_LOLLIPOP, TagCompat::XmlType::kVector}},
|
||||
{"objectAnimator", {SDK_LOLLIPOP, TagCompat::XmlType::kVector}},
|
||||
|
||||
{"adaptive-icon", {SDK_O, TagCompat::XmlType::kAdaptiveIcon}},
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
Maybe<TagApiVersionResult> GetXmlTagApiVersion(const StringPiece& tag_name, int options) {
|
||||
auto iter = sTagVersions.find(tag_name);
|
||||
if (iter == sTagVersions.end()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const TagCompat& tag_compat = iter->second;
|
||||
if (options & kNoVersionVector) {
|
||||
if (tag_compat.type == TagCompat::XmlType::kVector) {
|
||||
return TagApiVersionResult{{}, true /*skip_version*/};
|
||||
}
|
||||
}
|
||||
|
||||
if (options & kNoVersionTransition) {
|
||||
if (tag_compat.type == TagCompat::XmlType::kTransition) {
|
||||
return TagApiVersionResult{{}, true /*skip_version*/};
|
||||
}
|
||||
}
|
||||
return TagApiVersionResult{tag_compat.api_version, false /*skip_version*/};
|
||||
}
|
||||
|
||||
} // namespace xml
|
||||
} // namespace aapt
|
||||
|
||||
@@ -20,18 +20,16 @@
|
||||
#include <string>
|
||||
|
||||
#include "ResourceValues.h"
|
||||
#include "SdkConstants.h"
|
||||
#include "util/Maybe.h"
|
||||
|
||||
namespace aapt {
|
||||
namespace xml {
|
||||
|
||||
constexpr const char* kSchemaAuto = "http://schemas.android.com/apk/res-auto";
|
||||
constexpr const char* kSchemaPublicPrefix =
|
||||
"http://schemas.android.com/apk/res/";
|
||||
constexpr const char* kSchemaPrivatePrefix =
|
||||
"http://schemas.android.com/apk/prv/res/";
|
||||
constexpr const char* kSchemaAndroid =
|
||||
"http://schemas.android.com/apk/res/android";
|
||||
constexpr const char* kSchemaPublicPrefix = "http://schemas.android.com/apk/res/";
|
||||
constexpr const char* kSchemaPrivatePrefix = "http://schemas.android.com/apk/prv/res/";
|
||||
constexpr const char* kSchemaAndroid = "http://schemas.android.com/apk/res/android";
|
||||
constexpr const char* kSchemaTools = "http://schemas.android.com/tools";
|
||||
constexpr const char* kSchemaAapt = "http://schemas.android.com/aapt";
|
||||
|
||||
@@ -102,6 +100,24 @@ struct IPackageDeclStack {
|
||||
void TransformReferenceFromNamespace(IPackageDeclStack* decl_stack,
|
||||
const android::StringPiece& local_package, Reference* in_ref);
|
||||
|
||||
struct TagApiVersionResult {
|
||||
// If set, the API version to apply.
|
||||
Maybe<ApiVersion> api_version;
|
||||
|
||||
// Whether to skip any auto-versioning.
|
||||
bool skip_version;
|
||||
};
|
||||
|
||||
enum TagVersionOptions : int {
|
||||
// Skip versioning XML resources that deal with vector drawables.
|
||||
kNoVersionVector,
|
||||
|
||||
// Skip versioning XML resources that deal with transitions.
|
||||
kNoVersionTransition,
|
||||
};
|
||||
|
||||
Maybe<TagApiVersionResult> GetXmlTagApiVersion(const android::StringPiece& tag_name, int options);
|
||||
|
||||
} // namespace xml
|
||||
} // namespace aapt
|
||||
|
||||
|
||||
Reference in New Issue
Block a user