Just An Application

September 18, 2011

Android Internals: Resources – Part Seven: The Type Chunk

1.0 The Example

The Package chunk header does not explicitly specify the number of Type chunks present, nor is there any implicit indication as there is for TypeSpec chunks, but there are in fact five Type chunks present in the example.

    0000000 02 00 0c 00 64 04 00 00 01 00 00 00 01 00 1c 00
    0000010 d0 00 00 00 06 00 00 00 00 00 00 00 00 01 00 00
    0000020 34 00 00 00 00 00 00 00 00 00 00 00 1d 00 00 00
    0000030 3a 00 00 00 57 00 00 00 6d 00 00 00 8f 00 00 00
    0000040 1a 1a 72 65 73 2f 64 72 61 77 61 62 6c 65 2d 6c
    0000050 64 70 69 2f 69 63 6f 6e 2e 70 6e 67 00 1a 1a 72
    0000060 65 73 2f 64 72 61 77 61 62 6c 65 2d 6d 64 70 69
    0000070 2f 69 63 6f 6e 2e 70 6e 67 00 1a 1a 72 65 73 2f
    0000080 64 72 61 77 61 62 6c 65 2d 68 64 70 69 2f 69 63
    0000090 6f 6e 2e 70 6e 67 00 13 13 72 65 73 2f 6c 61 79
    00000a0 6f 75 74 2f 6d 61 69 6e 2e 78 6d 6c 00 1f 1f 48
    00000b0 65 6c 6c 6f 20 57 6f 72 6c 64 2c 20 50 65 6e 64
    00000c0 72 61 67 6f 6e 41 63 74 69 76 69 74 79 21 00 09
    00000d0 09 50 65 6e 64 72 61 67 6f 6e 00 00 00 02 1c 01
    00000e0 88 03 00 00 7f 00 00 00 78 00 70 00 65 00 72 00
    00000f0 2e 00 72 00 65 00 73 00 6f 00 75 00 72 00 63 00
    0000100 65 00 73 00 2e 00 70 00 65 00 6e 00 64 00 72 00
    0000110 61 00 67 00 6f 00 6e 00 00 00 00 00 00 00 00 00
    0000120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    *
    00001e0 00 00 00 00 00 00 00 00 1c 01 00 00 04 00 00 00
    00001f0 6c 01 00 00 04 00 00 00 01 00 1c 00 50 00 00 00
    0000200 04 00 00 00 00 00 00 00 00 01 00 00 2c 00 00 00
    0000210 00 00 00 00 00 00 00 00 07 00 00 00 12 00 00 00
    0000220 1b 00 00 00 04 04 61 74 74 72 00 08 08 64 72 61
    0000230 77 61 62 6c 65 00 06 06 6c 61 79 6f 75 74 00 06
    0000240 06 73 74 72 69 6e 67 00 01 00 1c 00 50 00 00 00
    0000250 04 00 00 00 00 00 00 00 00 01 00 00 2c 00 00 00
    0000260 00 00 00 00 00 00 00 00 07 00 00 00 0e 00 00 00
    0000270 16 00 00 00 04 04 69 63 6f 6e 00 04 04 6d 61 69
    0000280 6e 00 05 05 68 65 6c 6c 6f 00 08 08 61 70 70 5f
    0000290 6e 61 6d 65 00 00 00 00 02 02 10 00 10 00 00 00
    00002a0 01 00 00 00 00 00 00 00 02 02 10 00 14 00 00 00
    00002b0 02 00 00 00 01 00 00 00 00 01 00 00 01 02 34 00
    00002c0 48 00 00 00 02 00 00 00 01 00 00 00 38 00 00 00
    00002d0 20 00 00 00 00 00 00 00 00 00 00 00 00 00 78 00
    00002e0 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00
    00002f0 00 00 00 00 08 00 00 00 00 00 00 00 08 00 00 03
    0000300 00 00 00 00 01 02 34 00 48 00 00 00 02 00 00 00
    0000310 01 00 00 00 38 00 00 00 20 00 00 00 00 00 00 00
    0000320 00 00 00 00 00 00 a0 00 00 00 00 00 00 00 00 00
    0000330 04 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00
    0000340 00 00 00 00 08 00 00 03 01 00 00 00 01 02 34 00
    0000350 48 00 00 00 02 00 00 00 01 00 00 00 38 00 00 00
    0000360 20 00 00 00 00 00 00 00 00 00 00 00 00 00 f0 00
    0000370 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00
    0000380 00 00 00 00 08 00 00 00 00 00 00 00 08 00 00 03
    0000390 02 00 00 00 02 02 10 00 14 00 00 00 03 00 00 00
    00003a0 01 00 00 00 00 00 00 00 01 02 34 00 48 00 00 00
    00003b0 03 00 00 00 01 00 00 00 38 00 00 00 20 00 00 00
    00003c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00003d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00003e0 08 00 00 00 01 00 00 00 08 00 00 03 03 00 00 00
    00003f0 02 02 10 00 18 00 00 00 04 00 00 00 02 00 00 00
    0000400 00 00 00 00 00 00 00 00 01 02 34 00 5c 00 00 00
    0000410 04 00 00 00 02 00 00 00 3c 00 00 00 20 00 00 00
    0000420 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0000430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0000440 10 00 00 00 08 00 00 00 02 00 00 00 08 00 00 03
    0000450 04 00 00 00 08 00 00 00 03 00 00 00 08 00 00 03
    0000460 05 00 00 00                                    
    0000464

The bytes in blue are the Type chunk headers, the bytes in green the Type chunk bodies.

2.0 Type Chunks

A Type chunk contains all the values of a given type of Resource that are defined for a given configuration, for example, all the drawables defined for a specific screen density.

3.0 The Type Chunk Header

The format of a Type chunk header is defined by the following slightly misleadingly named C++ struct (see frameworks/base/include/ResourceTypes.h lines 1570-1596)

    struct ResTable_type
    {
        struct ResChunk_header header;

        enum {
            NO_ENTRY = 0xFFFFFFFF
        };
    
        // The type identifier this chunk is holding.  Type IDs start
        // at 1 (corresponding to the value of the type bits in a
        // resource identifier).  0 is invalid.
        uint8_t id;
    
        // Must be 0.
        uint8_t res0;
        // Must be 0.
        uint16_t res1;
    
        // Number of uint32_t entry indices that follow.
        uint32_t entryCount;

        // Offset from header where ResTable_entry data starts.
        uint32_t entriesStart;
    
        // Configuration this collection of entries is designed for.
        ResTable_config config;
    };

3.1 header

The header field is a struct ResChunk_header instance.

The header.type field is always 0x0201 (RES_TABLE_TYPE_TYPE).

The header.headerSize field is always 0x0034.

3.2 id

The id field specifies the numeric id of the Resource type represented by this chunk.

The id uniquely identifies the represented Resource type within the containing Package chunk.

The id also specifies the name of the Resource type. It is the string at index id - 1 in the typeStrings StringPool chunk in the containing Package chunk.

3.3 entryCount

The entryCount field specifies the number of Resources of this type.

3.4 entriesStart

The entriesStart field specifies the offset from the start of the chunk to the start of the entries in the body of the chunk which represent the Resource values.

3.5 config

The config field contains an instance of the following C++ struct (see frameworks/base/include/ResourceTypes.h lines 1570-1596)

    struct ResTable_config
    {
        // Number of bytes in this structure.
        uint32_t size;
    
        union {
            struct {
                // Mobile country code (from SIM).  0 means "any".
                uint16_t mcc;
                // Mobile network code (from SIM).  0 means "any".
                uint16_t mnc;
            };
            uint32_t imsi;
        };
    
        union {
            struct {
                //  means "any".  Otherwise, en, fr, etc.
                char language[2];
            
                //  means "any".  Otherwise, US, CA, etc.
                char country[2];
            };
            uint32_t locale;
        };
    
        // elided ...
	    
        union {
            struct {
                uint8_t  orientation;
                uint8_t  touchscreen;
                uint16_t density;
            };
            uint32_t screenType;
        };
    
        // elided ...
    
        union {
            struct {
                uint8_t keyboard;
                uint8_t navigation;
                uint8_t inputFlags;
                uint8_t inputPad0;
            };
            uint32_t input;
        };
    
        // elided ...
		
        union {
            struct {
                uint16_t screenWidth;
                uint16_t screenHeight;
            };
            uint32_t screenSize;
        };
    
        // elided ...
    
        union {
            struct {
                uint16_t sdkVersion;
                // For now minorVersion must always be 0!!!  Its meaning
                // is currently undefined.
                uint16_t minorVersion;
            };
            uint32_t version;
        };
    
        // elided ...
	
        union {
            struct {
                uint8_t screenLayout;
                uint8_t uiMode;
                uint8_t screenConfigPad1;
                uint8_t screenConfigPad2;
            };
            uint32_t screenConfig;
        };
    
        // elided ...
    }

Note: The definition includes a number of enum and inline function definitions which have been omitted for clarity.

This specifies the configuration which the values of the Resources in this Type chunk are defined for.

4.0 The Type Chunk Body

The body of a Type chunk consists of an offsets table and one or more Resource entry/value pairs.

4.1 The Offsets Table

The offsets table contains entryCount 32 bit integers, one for each Resource of this type that has been defined in the Package represented by the containing Package chunk.

The value for each Resource is either

  • the offset from the start of the Resource entries, as specified by entriesStart, at which the corresponding Resource entry/value pair can be found

if the Resource has a value defined for the configuration represented by the Type chunk, or

  • the value 0xFFFFFFFF as defined by the constant NO_ENTRY in the chunk header definition

otherwise.

4.2 Resource Entries

The Resource entry/value pairs follow the offsets table.

A Resource entry specifies the key (name) of the Resource. It is immediately followed by the value of that Resource.

5.0 The Example Annotated

5.1 Multiple Type Chunks

    ...

    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 three Type chunks above define the values of the icon drawable Resource for the the three screen densities low, medium, and high.

The corresponding TypeSpec chunk is here.

Screen density values are specified in configurations using the following anonymous enum members (see frameworks/base/native/include/android/configuration.h lines 41-43)

    ...

    ACONFIGURATION_DENSITY_DEFAULT = 0,
    ACONFIGURATION_DENSITY_LOW     = 120,
    ACONFIGURATION_DENSITY_MEDIUM  = 160,
    ACONFIGURATION_DENSITY_HIGH    = 240,

    ...

The screen density is specified by the high 16 bits of the screenType field of the configuration structure.

The screenType field of the configuration structure in the header of the first Type chunk (the four bytes starting at 000002dc) has the value 0x00780000. The top 16-bits of this are 0x0078 or 120.

Hence the first Type chunk starting at 000002bc specifies the value of the icon Resource for a low density screen.

Using the same reasoning shows that the second Type chunk starting at 00000304 specifies the value of the icon Resource for a medium density screen, and that the third Type chunk starting at 0000034c specifies the value of the icon Resource for a high density screen.

5.2 Type Chunk With Multiple Resource Entries

    ...

    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 Type chunk above defines the values for the string Resources hello and app_name for the default configuration.

The corresponding TypeSpec chunk is here.


Copyright (c) 2011 By Simon Lewis. All Rights Reserved.

Advertisements

4 Comments »

  1. […] Resource entries contained in a Type chunk body can be either simple or […]

    Pingback by Android Internals: Resources – Part Eight: Resource Entries And Values « Just An Application — September 22, 2011 @ 3:30 am

  2. […] Type id identifies the type of the Resource and hence the corresponding Typespec chunk and Type chunk or chunks which contain its value or […]

    Pingback by Android Internals: Resource Ids And Resource Lookup « Just An Application — January 22, 2013 @ 9:46 pm

  3. 3.1 The header.headerSize field is always 0x0034.

    Looks like 0x0038 now, because ResTable_config contains one field more today.

    Comment by Кирилл Ярин — January 27, 2014 @ 1:25 pm

    • Indeed.

      They have added the screenSizeOp field at some point after I wrote this.

      Thanks for that

      simon

      Comment by Simon Lewis — January 27, 2014 @ 3:26 pm


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: