class LoadedArsc
class ApkAssets
android.content.res.ApkAssets#ApkAssets()
private static final String FRAMEWORK_APK_PATH = “/system/framework/framework-res.apk”;
ResStringPool
what is RES_XML_TYPE
Res_value:
// The 'data' holds an index into the containing resource table's
// global value string pool.
TYPE_STRING = 0x03,
// The 'data' is a raw integer value of the form n..n.
TYPE_INT_DEC = 0x10,
// The 'data' is a raw integer value of the form #rrggbb.
TYPE_INT_COLOR_RGB8 = 0x1d,
#define Res_GETPACKAGE(id) ((id>>24)-1)
#define Res_GETTYPE(id) (((id>>16)&0xFF)-1)
#define Res_GETENTRY(id) (id&0xFFFF)
#define APP_PACKAGE_ID 0x7f
#define SYS_PACKAGE_ID 0x01
string id: 7f0e0024: 2131623972
package_id: 0x7f
type_idx: 0x0e 13
entry_index: 36
Step to get resource:
1 nativeGetResourceValue
2 AssetManager2::GetResource()
3 AssetManager2::FindEntry() :
first find PackageGroup by package_id , then call FindEntryInternal().
4 AssetManager2::FindEntryInternal()
get TypeSpec :
const TypeSpec* type_spec = loaded_package->GetTypeSpecByTypeIndex(type_idx);
struct ResTable_type
struct ResTable_entry
struct Res_value
What is std::unordered_map<uint8_t, TypeSpec> type_specs_;
ResTable::collectString
when to init package_ids_ ?
String type_idx: 13 :
const TypeSpec* type_spec = loaded_package->GetTypeSpecByTypeIndex(type_idx);
ResChunk_header type is : RES_TABLE_TYPE_TYPE = 0x0201,
Res_value data type is 3 : String
ResTable_entry and Res_value :
This is the beginning of information about an entry in the resource
table. It holds the reference to the name of this entry, and is
immediately followed by one of:
A Res_value structure, if FLAG_COMPLEX is -not- set.
An array of ResTable_map structures, if FLAG_COMPLEX is set.
These supply a set of name/value mappings of data.
const TypeSpec* type_spec = loaded_package->GetTypeSpecByTypeIndex(type_idx);
load apk step :
nativeLoad
STEP 1:
android_content_res_ApkAssets.cpp:
case FORMAT_APK: {
auto assets = MultiAssetsProvider::Create(std::move(loader_assets),
ZipAssetsProvider::Create(path.c_str(),
property_flags));
apk_assets = ApkAssets::Load(std::move(assets), property_flags);
break;
}
AssetsProvider open
finally to this function:
STEP 2:
resources_asset is the stream to read from .
std::unique_ptr<ApkAssets> ApkAssets::LoadImpl(std::unique_ptr<Asset> resources_asset,
std::unique_ptr<AssetsProvider> assets,
package_property_t property_flags,
std::unique_ptr<Asset> idmap_asset,
std::unique_ptr<LoadedIdmap> loaded_idmap) {
if (assets == nullptr ) {
return {};
}
std::unique_ptr<LoadedArsc> loaded_arsc;
if (resources_asset != nullptr) {
const auto data = resources_asset->getIncFsBuffer(true /* aligned */);
const size_t length = resources_asset->getLength();
if (!data || length == 0) {
LOG(ERROR) << "Failed to read resources table in APK '" << assets->GetDebugName() << "'.";
return {};
}
loaded_arsc = LoadedArsc::Load(data, length, loaded_idmap.get(), property_flags);
} else {
loaded_arsc = LoadedArsc::CreateEmpty();
}
if (loaded_arsc == nullptr) {
LOG(ERROR) << "Failed to load resources table in APK '" << assets->GetDebugName() << "'.";
return {};
}
return std::unique_ptr<ApkAssets>(new ApkAssets(std::move(resources_asset),
std::move(loaded_arsc), std::move(assets),
property_flags, std::move(idmap_asset),
std::move(loaded_idmap)));
}
call :
loaded_arsc = LoadedArsc::Load(data, length, loaded_idmap.get(), property_flags);
read into LoadedArsc.
STEP 3:
LoadedArsc::Load
the top Chunk type is : RES_TABLE_TYPE = 0x0002,
then call LoadedArsc::LoadTable
child chunk type is : RES_STRING_POOL_TYPE and RES_TABLE_PACKAGE_TYPE .
ChunkIterator iter(chunk.data_ptr(), chunk.data_size());
while (iter.HasNext()) {
const Chunk child_chunk = iter.Next();
switch (child_chunk.type()) {
case RES_STRING_POOL_TYPE:
// Only use the first string pool. Ignore others.
if (global_string_pool_->getError() == NO_INIT) {
status_t err = global_string_pool_->setTo(child_chunk.header<ResStringPool_header>(),
child_chunk.size());
if (err != NO_ERROR) {
LOG(ERROR) << "RES_STRING_POOL_TYPE corrupt.";
return false;
}
} else {
LOG(WARNING) << "Multiple RES_STRING_POOL_TYPEs found in RES_TABLE_TYPE.";
}
break;
case RES_TABLE_PACKAGE_TYPE: {
if (packages_seen + 1 > package_count) {
LOG(ERROR) << "More package chunks were found than the " << package_count
<< " declared in the header.";
return false;
}
packages_seen++;
std::unique_ptr<const LoadedPackage> loaded_package =
LoadedPackage::Load(child_chunk, property_flags);
if (!loaded_package) {
return false;
}
packages_.push_back(std::move(loaded_package));
} break;
default:
LOG(WARNING) << StringPrintf("Unknown chunk type '%02x'.", chunk.type());
break;
}
}
RES_STRING_POOL_TYPE call global_string_pool_->setTo ();
RES_TABLE_PACKAGE_TYPE create LoadedPackage and then put into packages_ .
STEP 4: LoadedArsc.cpp LoadedPackage
call static function LoadedPackage::Load()
type_string_pool_
key_string_pool_
loaded_package->type_specs_[type_id]
loaded_package->resource_ids_.set(type_spec->id, entry_count);
Type :
string: 0x0e;
drawable: 0x08;
integer:0x0a;
color:0x06;
todo:
/home/andy/aosp13/system/incremental_delivery/incfs/util/include/util/map_ptr.h