blob: 1775f5070f4ea2ae4518d6d0dc50ea73ed40aad3 [file] [log] [blame]
/*
* Copyright (C) 2016 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 LOADEDARSC_H_
#define LOADEDARSC_H_
#include <memory>
#include <set>
#include <vector>
#include "android-base/macros.h"
#include "androidfw/ByteBucketArray.h"
#include "androidfw/Chunk.h"
#include "androidfw/Idmap.h"
#include "androidfw/ResourceTypes.h"
#include "androidfw/Util.h"
namespace android {
class DynamicPackageEntry {
public:
DynamicPackageEntry() = default;
DynamicPackageEntry(std::string&& package_name, int package_id)
: package_name(std::move(package_name)), package_id(package_id) {}
std::string package_name;
int package_id = 0;
};
struct FindEntryResult {
// A pointer to the resource table entry for this resource.
// If the size of the entry is > sizeof(ResTable_entry), it can be cast to
// a ResTable_map_entry and processed as a bag/map.
const ResTable_entry* entry;
// The configuration for which the resulting entry was defined. This points to a structure that
// is already swapped to host endianness.
const ResTable_config* config;
// The bitmask of configuration axis with which the resource value varies.
uint32_t type_flags;
// The dynamic package ID map for the package from which this resource came from.
const DynamicRefTable* dynamic_ref_table;
// The string pool reference to the type's name. This uses a different string pool than
// the global string pool, but this is hidden from the caller.
StringPoolRef type_string_ref;
// The string pool reference to the entry's name. This uses a different string pool than
// the global string pool, but this is hidden from the caller.
StringPoolRef entry_string_ref;
};
struct TypeSpec;
class LoadedArsc;
class LoadedPackage {
public:
static std::unique_ptr<const LoadedPackage> Load(const Chunk& chunk,
const LoadedIdmap* loaded_idmap, bool system,
bool load_as_shared_library);
~LoadedPackage();
bool FindEntry(uint8_t type_idx, uint16_t entry_idx, const ResTable_config& config,
FindEntryResult* out_entry) const;
// Finds the entry with the specified type name and entry name. The names are in UTF-16 because
// the underlying ResStringPool API expects this. For now this is acceptable, but since
// the default policy in AAPT2 is to build UTF-8 string pools, this needs to change.
// Returns a partial resource ID, with the package ID left as 0x00. The caller is responsible
// for patching the correct package ID to the resource ID.
uint32_t FindEntryByName(const std::u16string& type_name, const std::u16string& entry_name) const;
// Returns the string pool where type names are stored.
inline const ResStringPool* GetTypeStringPool() const {
return &type_string_pool_;
}
// Returns the string pool where the names of resource entries are stored.
inline const ResStringPool* GetKeyStringPool() const {
return &key_string_pool_;
}
inline const std::string& GetPackageName() const {
return package_name_;
}
inline int GetPackageId() const {
return package_id_;
}
// Returns true if this package is dynamic (shared library) and needs to have an ID assigned.
inline bool IsDynamic() const {
return dynamic_;
}
// Returns true if this package originates from a system provided resource.
inline bool IsSystem() const {
return system_;
}
// Returns true if this package is from an overlay ApkAssets.
inline bool IsOverlay() const {
return overlay_;
}
// Returns the map of package name to package ID used in this LoadedPackage. At runtime, a
// package could have been assigned a different package ID than what this LoadedPackage was
// compiled with. AssetManager rewrites the package IDs so that they are compatible at runtime.
inline const std::vector<DynamicPackageEntry>& GetDynamicPackageMap() const {
return dynamic_package_map_;
}
// Populates a set of ResTable_config structs, possibly excluding configurations defined for
// the mipmap type.
void CollectConfigurations(bool exclude_mipmap, std::set<ResTable_config>* out_configs) const;
// Populates a set of strings representing locales.
// If `canonicalize` is set to true, each locale is transformed into its canonical format
// before being inserted into the set. This may cause some equivalent locales to de-dupe.
void CollectLocales(bool canonicalize, std::set<std::string>* out_locales) const;
private:
DISALLOW_COPY_AND_ASSIGN(LoadedPackage);
LoadedPackage();
bool FindEntry(const util::unique_cptr<TypeSpec>& type_spec_ptr, uint16_t entry_idx,
const ResTable_config& config, FindEntryResult* out_entry) const;
ResStringPool type_string_pool_;
ResStringPool key_string_pool_;
std::string package_name_;
int package_id_ = -1;
int type_id_offset_ = 0;
bool dynamic_ = false;
bool system_ = false;
bool overlay_ = false;
ByteBucketArray<util::unique_cptr<TypeSpec>> type_specs_;
std::vector<DynamicPackageEntry> dynamic_package_map_;
};
// Read-only view into a resource table. This class validates all data
// when loading, including offsets and lengths.
class LoadedArsc {
public:
// Load a resource table from memory pointed to by `data` of size `len`.
// The lifetime of `data` must out-live the LoadedArsc returned from this method.
// If `system` is set to true, the LoadedArsc is considered as a system provided resource.
// If `load_as_shared_library` is set to true, the application package (0x7f) is treated
// as a shared library (0x00). When loaded into an AssetManager, the package will be assigned an
// ID.
static std::unique_ptr<const LoadedArsc> Load(const StringPiece& data,
const LoadedIdmap* loaded_idmap = nullptr,
bool system = false,
bool load_as_shared_library = false);
// Create an empty LoadedArsc. This is used when an APK has no resources.arsc.
static std::unique_ptr<const LoadedArsc> CreateEmpty();
// Returns the string pool where all string resource values
// (Res_value::dataType == Res_value::TYPE_STRING) are indexed.
inline const ResStringPool* GetStringPool() const {
return &global_string_pool_;
}
// Finds the resource with ID `resid` with the best value for configuration `config`.
// The parameter `out_entry` will be filled with the resulting resource entry.
// The resource entry can be a simple entry (ResTable_entry) or a complex bag
// (ResTable_entry_map).
bool FindEntry(uint32_t resid, const ResTable_config& config, FindEntryResult* out_entry) const;
// Gets a pointer to the name of the package in `resid`, or nullptr if the package doesn't exist.
const LoadedPackage* GetPackageForId(uint32_t resid) const;
// Returns true if this is a system provided resource.
inline bool IsSystem() const {
return system_;
}
// Returns a vector of LoadedPackage pointers, representing the packages in this LoadedArsc.
inline const std::vector<std::unique_ptr<const LoadedPackage>>& GetPackages() const {
return packages_;
}
private:
DISALLOW_COPY_AND_ASSIGN(LoadedArsc);
LoadedArsc() = default;
bool LoadTable(const Chunk& chunk, const LoadedIdmap* loaded_idmap, bool load_as_shared_library);
ResStringPool global_string_pool_;
std::vector<std::unique_ptr<const LoadedPackage>> packages_;
bool system_ = false;
};
} // namespace android
#endif /* LOADEDARSC_H_ */