939df096be
This change adds parsing, encoding, and validating of odm and oem overlayable policies to aapt2, libandroidfw, and idmap2. Bug: 121033532 Test: aapt2_tests, idmap2_tests Change-Id: Ifc0d4b6c9f9c37e06b2988abade69dbb277c50c2
350 lines
13 KiB
C++
350 lines
13 KiB
C++
/*
|
|
* Copyright (C) 2015 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.
|
|
*/
|
|
|
|
#ifndef AAPT_RESOURCE_TABLE_H
|
|
#define AAPT_RESOURCE_TABLE_H
|
|
|
|
#include "Diagnostics.h"
|
|
#include "Resource.h"
|
|
#include "ResourceValues.h"
|
|
#include "Source.h"
|
|
#include "StringPool.h"
|
|
#include "io/File.h"
|
|
|
|
#include "android-base/macros.h"
|
|
#include "androidfw/ConfigDescription.h"
|
|
#include "androidfw/StringPiece.h"
|
|
|
|
#include <functional>
|
|
#include <map>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <tuple>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
|
|
namespace aapt {
|
|
|
|
// The Public status of a resource.
|
|
struct Visibility {
|
|
enum class Level {
|
|
kUndefined,
|
|
kPrivate,
|
|
kPublic,
|
|
};
|
|
|
|
Level level = Level::kUndefined;
|
|
Source source;
|
|
std::string comment;
|
|
};
|
|
|
|
// Represents <add-resource> in an overlay.
|
|
struct AllowNew {
|
|
Source source;
|
|
std::string comment;
|
|
};
|
|
|
|
struct Overlayable {
|
|
Overlayable() = default;
|
|
Overlayable(const android::StringPiece& name, const android::StringPiece& actor)
|
|
: name(name.to_string()), actor(actor.to_string()) {}
|
|
Overlayable(const android::StringPiece& name, const android::StringPiece& actor,
|
|
const Source& source)
|
|
: name(name.to_string()), actor(actor.to_string()), source(source ){}
|
|
|
|
static const char* kActorScheme;
|
|
std::string name;
|
|
std::string actor;
|
|
Source source;
|
|
};
|
|
|
|
// Represents a declaration that a resource is overlayable at runtime.
|
|
struct OverlayableItem {
|
|
explicit OverlayableItem(const std::shared_ptr<Overlayable>& overlayable)
|
|
: overlayable(overlayable) {}
|
|
|
|
// Represents the types overlays that are allowed to overlay the resource.
|
|
typedef uint32_t PolicyFlags;
|
|
enum Policy : uint32_t {
|
|
kNone = 0x00000000,
|
|
|
|
// The resource can be overlaid by any overlay.
|
|
kPublic = 0x00000001,
|
|
|
|
// The resource can be overlaid by any overlay on the system partition.
|
|
kSystem = 0x00000002,
|
|
|
|
// The resource can be overlaid by any overlay on the vendor partition.
|
|
kVendor = 0x00000004,
|
|
|
|
// The resource can be overlaid by any overlay on the product partition.
|
|
kProduct = 0x00000008,
|
|
|
|
// The resource can be overlaid by any overlay signed with the same signature as its actor.
|
|
kSignature = 0x00000010,
|
|
|
|
// The resource can be overlaid by any overlay on the odm partition.
|
|
kOdm = 0x00000020,
|
|
|
|
// The resource can be overlaid by any overlay on the oem partition.
|
|
kOem = 0x00000040,
|
|
};
|
|
|
|
std::shared_ptr<Overlayable> overlayable;
|
|
PolicyFlags policies = Policy::kNone;
|
|
std::string comment;
|
|
Source source;
|
|
};
|
|
|
|
class ResourceConfigValue {
|
|
public:
|
|
// The configuration for which this value is defined.
|
|
const android::ConfigDescription config;
|
|
|
|
// The product for which this value is defined.
|
|
const std::string product;
|
|
|
|
// The actual Value.
|
|
std::unique_ptr<Value> value;
|
|
|
|
ResourceConfigValue(const android::ConfigDescription& config, const android::StringPiece& product)
|
|
: config(config), product(product.to_string()) {}
|
|
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(ResourceConfigValue);
|
|
};
|
|
|
|
// Represents a resource entry, which may have varying values for each defined configuration.
|
|
class ResourceEntry {
|
|
public:
|
|
// The name of the resource. Immutable, as this determines the order of this resource
|
|
// when doing lookups.
|
|
const std::string name;
|
|
|
|
// The entry ID for this resource (the EEEE in 0xPPTTEEEE).
|
|
Maybe<uint16_t> id;
|
|
|
|
// Whether this resource is public (and must maintain the same entry ID across builds).
|
|
Visibility visibility;
|
|
|
|
Maybe<AllowNew> allow_new;
|
|
|
|
// The declarations of this resource as overlayable for RROs
|
|
Maybe<OverlayableItem> overlayable_item;
|
|
|
|
// The resource's values for each configuration.
|
|
std::vector<std::unique_ptr<ResourceConfigValue>> values;
|
|
|
|
explicit ResourceEntry(const android::StringPiece& name) : name(name.to_string()) {}
|
|
|
|
ResourceConfigValue* FindValue(const android::ConfigDescription& config);
|
|
|
|
ResourceConfigValue* FindValue(const android::ConfigDescription& config,
|
|
const android::StringPiece& product);
|
|
|
|
ResourceConfigValue* FindOrCreateValue(const android::ConfigDescription& config,
|
|
const android::StringPiece& product);
|
|
std::vector<ResourceConfigValue*> FindAllValues(const android::ConfigDescription& config);
|
|
|
|
template <typename Func>
|
|
std::vector<ResourceConfigValue*> FindValuesIf(Func f) {
|
|
std::vector<ResourceConfigValue*> results;
|
|
for (auto& config_value : values) {
|
|
if (f(config_value.get())) {
|
|
results.push_back(config_value.get());
|
|
}
|
|
}
|
|
return results;
|
|
}
|
|
|
|
bool HasDefaultValue() const;
|
|
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(ResourceEntry);
|
|
};
|
|
|
|
// Represents a resource type (eg. string, drawable, layout, etc.) containing resource entries.
|
|
class ResourceTableType {
|
|
public:
|
|
// The logical type of resource (string, drawable, layout, etc.).
|
|
const ResourceType type;
|
|
|
|
// The type ID for this resource (the TT in 0xPPTTEEEE).
|
|
Maybe<uint8_t> id;
|
|
|
|
// Whether this type is public (and must maintain the same type ID across builds).
|
|
Visibility::Level visibility_level = Visibility::Level::kUndefined;
|
|
|
|
// List of resources for this type.
|
|
std::vector<std::unique_ptr<ResourceEntry>> entries;
|
|
|
|
explicit ResourceTableType(const ResourceType type) : type(type) {}
|
|
|
|
ResourceEntry* FindEntry(const android::StringPiece& name,
|
|
Maybe<uint16_t> id = Maybe<uint16_t>());
|
|
ResourceEntry* FindOrCreateEntry(const android::StringPiece& name,
|
|
Maybe<uint16_t> id = Maybe<uint16_t>());
|
|
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(ResourceTableType);
|
|
};
|
|
|
|
class ResourceTablePackage {
|
|
public:
|
|
std::string name;
|
|
|
|
// The package ID (the PP in 0xPPTTEEEE).
|
|
Maybe<uint8_t> id;
|
|
|
|
std::vector<std::unique_ptr<ResourceTableType>> types;
|
|
|
|
ResourceTablePackage() = default;
|
|
ResourceTableType* FindType(ResourceType type, Maybe<uint8_t> id = Maybe<uint8_t>());
|
|
ResourceTableType* FindOrCreateType(const ResourceType type,
|
|
Maybe<uint8_t> id = Maybe<uint8_t>());
|
|
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(ResourceTablePackage);
|
|
};
|
|
|
|
// The container and index for all resources defined for an app.
|
|
class ResourceTable {
|
|
public:
|
|
ResourceTable() = default;
|
|
explicit ResourceTable(bool validate_resources) : validate_resources_(validate_resources) {}
|
|
|
|
enum class CollisionResult { kKeepBoth, kKeepOriginal, kConflict, kTakeNew };
|
|
|
|
using CollisionResolverFunc = std::function<CollisionResult(Value*, Value*)>;
|
|
|
|
// When a collision of resources occurs, this method decides which value to keep.
|
|
static CollisionResult ResolveValueCollision(Value* existing, Value* incoming);
|
|
|
|
// When a collision of resources occurs, this method keeps both values
|
|
static CollisionResult IgnoreCollision(Value* existing, Value* incoming);
|
|
|
|
bool AddResource(const ResourceNameRef& name, const android::ConfigDescription& config,
|
|
const android::StringPiece& product, std::unique_ptr<Value> value,
|
|
IDiagnostics* diag);
|
|
|
|
bool AddResourceWithId(const ResourceNameRef& name, const ResourceId& res_id,
|
|
const android::ConfigDescription& config,
|
|
const android::StringPiece& product, std::unique_ptr<Value> value,
|
|
IDiagnostics* diag);
|
|
|
|
// Same as AddResource, but doesn't verify the validity of the name. This is used
|
|
// when loading resources from an existing binary resource table that may have mangled names.
|
|
bool AddResourceMangled(const ResourceNameRef& name, const android::ConfigDescription& config,
|
|
const android::StringPiece& product, std::unique_ptr<Value> value,
|
|
IDiagnostics* diag);
|
|
|
|
bool AddResourceWithIdMangled(const ResourceNameRef& name, const ResourceId& id,
|
|
const android::ConfigDescription& config,
|
|
const android::StringPiece& product, std::unique_ptr<Value> value,
|
|
IDiagnostics* diag);
|
|
|
|
bool GetValidateResources();
|
|
|
|
bool SetVisibility(const ResourceNameRef& name, const Visibility& visibility, IDiagnostics* diag);
|
|
bool SetVisibilityWithId(const ResourceNameRef& name, const Visibility& visibility,
|
|
const ResourceId& res_id, IDiagnostics* diag);
|
|
bool SetVisibilityWithIdMangled(const ResourceNameRef& name, const Visibility& visibility,
|
|
const ResourceId& res_id, IDiagnostics* diag);
|
|
|
|
bool SetOverlayable(const ResourceNameRef& name, const OverlayableItem& overlayable,
|
|
IDiagnostics *diag);
|
|
|
|
bool SetAllowNew(const ResourceNameRef& name, const AllowNew& allow_new, IDiagnostics* diag);
|
|
bool SetAllowNewMangled(const ResourceNameRef& name, const AllowNew& allow_new,
|
|
IDiagnostics* diag);
|
|
|
|
struct SearchResult {
|
|
ResourceTablePackage* package;
|
|
ResourceTableType* type;
|
|
ResourceEntry* entry;
|
|
};
|
|
|
|
Maybe<SearchResult> FindResource(const ResourceNameRef& name) const;
|
|
|
|
// Returns the package struct with the given name, or nullptr if such a package does not
|
|
// exist. The empty string is a valid package and typically is used to represent the
|
|
// 'current' package before it is known to the ResourceTable.
|
|
ResourceTablePackage* FindPackage(const android::StringPiece& name) const;
|
|
|
|
ResourceTablePackage* FindPackageById(uint8_t id) const;
|
|
|
|
ResourceTablePackage* CreatePackage(const android::StringPiece& name, Maybe<uint8_t> id = {});
|
|
|
|
// Attempts to find a package having the specified name and ID. If not found, a new package
|
|
// of the specified parameters is created and returned.
|
|
ResourceTablePackage* CreatePackageAllowingDuplicateNames(const android::StringPiece& name,
|
|
const Maybe<uint8_t> id);
|
|
|
|
std::unique_ptr<ResourceTable> Clone() const;
|
|
|
|
// The string pool used by this resource table. Values that reference strings must use
|
|
// this pool to create their strings.
|
|
// NOTE: `string_pool` must come before `packages` so that it is destroyed after.
|
|
// When `string_pool` references are destroyed (as they will be when `packages` is destroyed),
|
|
// they decrement a refCount, which would cause invalid memory access if the pool was already
|
|
// destroyed.
|
|
StringPool string_pool;
|
|
|
|
// The list of packages in this table, sorted alphabetically by package name and increasing
|
|
// package ID (missing ID being the lowest).
|
|
std::vector<std::unique_ptr<ResourceTablePackage>> packages;
|
|
|
|
// Set of dynamic packages that this table may reference. Their package names get encoded
|
|
// into the resources.arsc along with their compile-time assigned IDs.
|
|
std::map<size_t, std::string> included_packages_;
|
|
|
|
private:
|
|
// The function type that validates a symbol name. Returns a non-empty StringPiece representing
|
|
// the offending character (which may be more than one byte in UTF-8). Returns an empty string
|
|
// if the name was valid.
|
|
using NameValidator = android::StringPiece(const android::StringPiece&);
|
|
|
|
ResourceTablePackage* FindOrCreatePackage(const android::StringPiece& name);
|
|
|
|
bool ValidateName(NameValidator validator, const ResourceNameRef& name, const Source& source,
|
|
IDiagnostics* diag);
|
|
|
|
bool AddResourceImpl(const ResourceNameRef& name, const ResourceId& res_id,
|
|
const android::ConfigDescription& config,
|
|
const android::StringPiece& product, std::unique_ptr<Value> value,
|
|
NameValidator name_validator, const CollisionResolverFunc& conflict_resolver,
|
|
IDiagnostics* diag);
|
|
|
|
bool SetVisibilityImpl(const ResourceNameRef& name, const Visibility& visibility,
|
|
const ResourceId& res_id, NameValidator name_validator,
|
|
IDiagnostics* diag);
|
|
|
|
bool SetAllowNewImpl(const ResourceNameRef& name, const AllowNew& allow_new,
|
|
NameValidator name_validator, IDiagnostics* diag);
|
|
|
|
bool SetOverlayableImpl(const ResourceNameRef &name, const OverlayableItem& overlayable,
|
|
NameValidator name_validator, IDiagnostics *diag);
|
|
|
|
// Controls whether the table validates resource names and prevents duplicate resource names
|
|
bool validate_resources_ = true;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(ResourceTable);
|
|
};
|
|
|
|
} // namespace aapt
|
|
|
|
#endif // AAPT_RESOURCE_TABLE_H
|