1.0 Resource Id Structure
An Android Resource id is a 32-bit integer. It comprises
- an 8-bit Package id [bits 24-31]
- an 8-bit Type id [bits 16-23]
- a 16-bit Entry index [bits 0-15]
The Package id identifies the Package chunk which contains the Resource.
The Type id identifies the type of the Resource and hence the corresponding Typespec chunk and
Type chunk or chunks which contain its value or value(s)
The Entry index identifies the individual Resource within the Typespec chunk and Type chunk(s).
1.1 Example
The four Resouce identifiers generated as part of the Resource Table example here break down as follows
Name | Value | Package id | Type id | Entry index |
---|---|---|---|---|
icon | 0x7f020000 |
0x7f |
2 |
0 |
main | 0x7f030000 |
0x7f |
3 |
0 |
hello | 0x7f040000 |
0x7f |
4 |
0 |
app_name | 0x7f040001 |
0x7f |
4 |
1 |
From this we can see that the icon
resource is of type 2, the main
resource is of type 3, and the hello
and app_name
resources are of type 4.
We know that the name of the Resource type with id i
can be found at the index i - 1
in the typeStrings StringPool Chunk
Looking at the Package chunk of the Resource Table example here we can see that the names corresponding to the type ids
- 2
- 3
- 4
are
- drawable
- layout
- string
respectively as we would expect.
2.0 Resource Value Lookup
To find the value of a Resource in a Resource Table given its id.
-
Extract the package id (
p
) the type id (t
) and the entry index (e
) from the given Resource id -
Find the Package chunk with id
p
. If there is no corresponding Package chunk then the Resource id is invalid. -
Find the Typespec chunk and associated Type chunk(s) with id
t
within the Package chunk. If there is no corresponding Typespec chunk then the Resource id is invalid. -
Check that the entry index
e
is a valid index into the entries in the Typespec chunk. If it is not then the Resource id is invalid.
At this point there are two possibilities, either there is a single Type chunk with the given id, or there are multiple Type chunks with the given id.
2.1 The Single Type Chunk Case
-
Lookup the offset
o
of the entry for the Resource with the given id at indexe
within the offsets table of the Type chunk -
Go to the offset
o
past the start of the entries in the Type chunk as specified by the fieldentriesStart
-
At this offset there will be either a simple or a complex resource entry which will specify the value of the Resource.
2.2 The Multiple Type Chunk Case
For each Type chunk
-
Lookup the offset
o
of the entry for the Resource with the given id at indexe
within the offsets table of the Type chunk -
If the value of offset
o
is0xFFFFFFFF
then there is no value for the Resource in this Type chunk. -
Otherwise the value cane be found in the same way as for the single Type chunk case above.
If we are looking for a value for a specifiec configuration then for each Type chunk that contains a value for the Resource we need to record the configuration associated with the value as stored in the config
field of the Type chunk.
Once we have collected all the available values for the Resource we then look for the closest match for the configuration we are interested in.
Exactly how you match configurations is left as an exercise for the reader.
2.3 Examples
2.3.1 Single Type Chunk Example
Given the id of the hello
Resource, in the Resource table example here, which is 0x7f040000
, then
p
is 127t
is 4e
is 0
Using the algorithm above we end up with the Typespec chunk with id 4 and a single associated Type chunk which looks like this
...
00000408 01 02 // type [TYPE]
0000040a 34 00 // header size
0000040c 5c 00 00 00 // chunk size
--------------------
00000410 04 // id
00000411 00 // 0
00000412 00 00 // 0
00000414 02 00 00 00 // entryCount
00000418 3c 00 00 00 // entriesStart (address 00000444)
0000041c 20 00 00 00 // config: size
00000420 00 00 00 00 // config: imsi
00000424 00 00 00 00 // config: locale
00000428 00 00 00 00 // config: screenType
0000042c 00 00 00 00 // config: input
00000430 00 00 00 00 // config: screenSize
00000434 00 00 00 00 // config: version
00000438 00 00 00 00 // config: screenConfig
++++++++++++++++++++
0000043c 00 00 00 00 // entry_index[0]
00000440 10 00 00 00 // entry_index[1]
00000444 08 00 // entry[0] size
00000446 00 00 // entry[0] flags
00000448 02 00 00 00 // entry[0] key
0000044c 08 00 // size
0000044e 00 // 0
0000044f 03 // dataType
00000450 04 00 00 00 // data
00000454 08 00 // entry[1] size
00000456 00 00 // entry[1] flags
00000458 03 00 00 00 // entry[1] key
0000045c 08 00 // size
0000045e 00 // 0
0000045f 03 // dataType
00000460 05 00 00 00 // data
==================== [End of TYPE]
...
The entry corresponding to the index 0 starts at 0x00000444
.
It is a simple entry, the flag FLAG_COMPLEX
is not set in the flags
field, which means that it is immediately followed by an instance of struct Res_value
. which specifies the value of the Resource.
The dataType
field is 3 which identifies it as as string. The data
field is 4, which, in the case of a value of type string, is the index of the string within the String pool chunk
Looking at the example the string at index 4 is
"Hello World, PendragonActivity!"
as we would expect
2.3.2 Muliple Type Chunk Example
Given the id of the icon
Resource () in the Resource table example here, which is 0x7f020000
, then
p
is 127t
is 2e
is 0
Using the algorithm above we end up with the Typespec chunk with id 2 and three associated Type chunks which look like this
...
000002bc 01 02 // type [TYPE]
000002be 34 00 // header size
000002c0 48 00 00 00 // chunk size
--------------------
000002c4 02 // id
000002c5 00 // 0
000002c6 00 00 // 0
000002c8 01 00 00 00 // entryCount
000002cc 38 00 00 00 // entriesStart (address 000002f4)
000002d0 20 00 00 00 // config: size
000002d4 00 00 00 00 // config: imsi
000002d8 00 00 00 00 // config: locale
000002dc 00 00 78 00 // config: screenType
000002e0 00 00 00 00 // config: input
000002e4 00 00 00 00 // config: screenSize
000002e8 04 00 00 00 // config: version
000002ec 00 00 00 00 // config: screenConfig
++++++++++++++++++++
000002f0 00 00 00 00 // entry_index[0]
000002f4 08 00 // entry[0] size
000002f6 00 00 // entry[0] flags
000002f8 00 00 00 00 // entry[0] key
000002fc 08 00 // size
000002fe 00 // 0
000002ff 03 // dataType
00000300 00 00 00 00 // data
==================== [End of TYPE]
00000304 01 02 // type [TYPE]
00000306 34 00 // header size
00000308 48 00 00 00 // chunk size
--------------------
0000030c 02 // id
0000030d 00 // 0
0000030e 00 00 // 0
00000310 01 00 00 00 // entryCount
00000314 38 00 00 00 // entriesStart (address 0000033c)
00000318 20 00 00 00 // config: size
0000031c 00 00 00 00 // config: imsi
00000320 00 00 00 00 // config: locale
00000324 00 00 a0 00 // config: screenType
00000328 00 00 00 00 // config: input
0000032c 00 00 00 00 // config: screenSize
00000330 04 00 00 00 // config: version
00000334 00 00 00 00 // config: screenConfig
++++++++++++++++++++
00000338 00 00 00 00 // entry_index[0]
0000033c 08 00 // entry[0] size
0000033e 00 00 // entry[0] flags
00000340 00 00 00 00 // entry[0] key
00000344 08 00 // size
00000346 00 // 0
00000347 03 // dataType
00000348 01 00 00 00 // data
==================== [End of TYPE]
0000034c 01 02 // type [TYPE]
0000034e 34 00 // header size
00000350 48 00 00 00 // chunk size
--------------------
00000354 02 // id
00000355 00 // 0
00000356 00 00 // 0
00000358 01 00 00 00 // entryCount
0000035c 38 00 00 00 // entriesStart (address 00000384)
00000360 20 00 00 00 // config: size
00000364 00 00 00 00 // config: imsi
00000368 00 00 00 00 // config: locale
0000036c 00 00 f0 00 // config: screenType
00000370 00 00 00 00 // config: input
00000374 00 00 00 00 // config: screenSize
00000378 04 00 00 00 // config: version
0000037c 00 00 00 00 // config: screenConfig
++++++++++++++++++++
00000380 00 00 00 00 // entry_index[0]
00000384 08 00 // entry[0] size
00000386 00 00 // entry[0] flags
00000388 00 00 00 00 // entry[0] key
0000038c 08 00 // size
0000038e 00 // 0
0000038f 03 // dataType
00000390 02 00 00 00 // data
==================== [End of TYPE]
...
The configurations stored in the Type chunks differ only in the screenType
field, the values of which are
0x78
0xa0
0xf0
respectively.
These values correspond to the anonymous enum values
-
DENSITY_LOW
-
DENSITY_MEDIUM
-
DENSITY_HIGH
In each Type chunk there is a single entry at index 0.
The entries start at
-
0x000002f4
-
0x0000033c
-
0x00000384
Each entry is a simple entry.
In each case the dataType
field of the value following the entry is 3 indicating that the data is a string.
The values of the data
fields of the values are
- 0
- 1
- 2
These are indexes into the String pool chunk.
Looking at the example we can see that the corresponding strings are
-
“res/drawable-ldpi/icon.png”
-
“res/drawable-mdpi/icon.png”
-
“res/drawable-hdpi/icon.png”
which is what we would expect given the configurations specified by the Type chunks.
Copyright (c) 2013 By Simon Lewis. All Rights Reserved.