Just An Application

September 19, 2011

Android Internals: Resources – Part Eight: Resource Entries And Values

1.0 Resource Entries

The Resource entries contained in a Type chunk body can be either simple or complex.

1.1 Simple Resource Entries

A simple Resource entry comprises an entry immediately followed by a value.

1.1.1 Entry

A simple Resource entry is an instance of the following C++ struct (see frameworks/base/include/ResourceTypes.h lines 1606-1623)

    struct ResTable_entry
    {
        // Number of bytes in this structure.
        uint16_t size;

        enum {
            // If set, this is a complex entry, holding a set of name/value
            // mappings.  It is followed by an array of ResTable_map structures.
            FLAG_COMPLEX = 0x0001,
            // If set, this resource has been declared public, so libraries
            // are allowed to reference it.
            FLAG_PUBLIC = 0x0002
        };
        uint16_t flags;
    
        // Reference into ResTable_package::keyStrings identifying this entry.
        struct ResStringPool_ref key;
    };

1.1.1.1 size

The size field specifies the size of the struct in bytes. The value is always 8.

1.1.1.2 flags

The flags field holds zero or more bit flags.

For a simple Resource entry the only possible flag is defined by the anonymous enum member FLAG_PUBLIC.

1.1.1.3 key

The key field specifies the name (or key if you prefer) of the Resource as an index into the keyStrings StringPool chunk of the containing Package chunk.

1.1.2 Value

A simple Resource value is an instance of the C++ struct Res_value (see below).

1.2 Complex Resource Entries

Complex Resource entries represent Resources which have structured or composite values.

An individual complex Resource entry comprises an entry immediately followed by one or more fields.

1.2.1 Naming

At this point it may be helpful to address the issue of naming which seems to have gone somewhat awry in this case.

The entry part of a complex Resource entry is an instance of the C++ struct ResTable_map_entry.

Each field is an instance of the C++ struct ResTable_map which is effectively a key/value pair.

Together the entry and the fields constitute, as the struct names tend to suggest, what is usually termed a map in the programming sense of the word.

Unfortunately the decision to have the name of the struct representing the entry end in the suffix _entry, presumably for consistency with the simple Resource entry case, means that the name of the struct representing a key/value pair, often termed a map entry, cannot.

The result is that the names are effectively the wrong way round which makes everything very confusing until you actually work out what is going on.

1.2.2 Entry

The struct ResTable_map_entry is defined as follows (see frameworks/base/include/ResourceTypes.h lines 1629-1635)

    struct ResTable_map_entry : public ResTable_entry
    {
        // Resource identifier of the parent mapping, or 0 if there is none.
        ResTable_ref parent;
        // Number of name/value pairs that follow for FLAG_COMPLEX.
        uint32_t count;
    };

1.2.2.1 size

The size field specifies the size of the struct in bytes. The value is always 16.

1.2.2.2 flags

The flags field holds one or more bit flags.

For a complex Resource entry the FLAG_COMPLEX flag is always set. The other possible flag is FLAG_PUBLIC.

1.2.2.3 key

The key field specifies the name (or key if you prefer) of the Resource as an index into the keyStrings StringPool chunk of the containing Package chunk.

1.2.2.4 parent

The parent field specifies the parent Resource, if any, of this Resource.

1.2.2.5 count

The count field specifies the number of key/value pairs that follow.

1.2.3 Fields

A complex Resource entry is immediately followed by count instances of the following C++ struct (see frameworks/base/include/ResourceTypes.h lines 1641-1724).

    struct ResTable_map
    {
        // ...elided
        ResTable_ref name;

        // ... elided

        // ... elided
	    
        // This mapping's value.
        Res_value value;
    };

1.2.2.1 name

The name field specifies the key part of the key/value pair.

A number of constant values for keys are specified by the following anonymous enum defined as part of the struct ResTable_map (see frameworks/base/include/ResourceTypes.h lines 1650-1672)

    enum {
        // This entry holds the attribute's type code.
        ATTR_TYPE = Res_MAKEINTERNAL(0),

        // For integral attributes, this is the minimum value it can hold.
        ATTR_MIN = Res_MAKEINTERNAL(1),

        // For integral attributes, this is the maximum value it can hold.
        ATTR_MAX = Res_MAKEINTERNAL(2),

        // Localization of this resource is can be encouraged or required with
        // an aapt flag if this is set
        ATTR_L10N = Res_MAKEINTERNAL(3),

        // for plural support, see android.content.res.PluralRules#attrForQuantity(int)
        ATTR_OTHER = Res_MAKEINTERNAL(4),
        ATTR_ZERO = Res_MAKEINTERNAL(5),
        ATTR_ONE = Res_MAKEINTERNAL(6),
        ATTR_TWO = Res_MAKEINTERNAL(7),
        ATTR_FEW = Res_MAKEINTERNAL(8),
        ATTR_MANY = Res_MAKEINTERNAL(9)
        
    };

Res_MAKEINTERNAL ia defined as a macro as follows (see frameworks/base/include/ResourceTypes.h line 215)

    #define Res_MAKEINTERNAL(entry) (0x01000000 | (entry&0xFFFF))

1.2.2.2 value

The value field is an instance of the C++ struct Res_value (see below).

2.0 Resource Values

A Resource value is an instance of the following C++ struct (see frameworks/base/include/ResourceTypes.h lines 224-333)

    struct Res_value
    {
        // Number of bytes in this structure.
        uint16_t size;

        // Always set to 0.
        uint8_t res0;
        
        // Type of the data value.
	
        // ... elided
	
       uint8_t dataType;
	
        // ... elided
		
        // The data for this item, as interpreted according to dataType.
        uint32_t data;

        // ... elided
    };

Note: the definition includes two anonymous enums which have been omitted for clarity.

2.1 Fields

2.1.1 size

The size field specifies the size of the entire struct in bytes. It always has the the value 8.

2.1.2 dataType

The dataType field specifies the type of the data field that follows.

The set of possible values for this field are specified by an anonymous enum (see section 2.2 below).

2.1.3 data

The semantics of the data field are dependent upon the value of the type field (see section 2.3 below).

2.2 Resource Value Types

The possible types of a Resource value are defined by the following anonymous C++ enum.

    enum {
        // Contains no data.
        TYPE_NULL = 0x00,
        // The 'data' holds a ResTable_ref, a reference to another resource
        // table entry.
        TYPE_REFERENCE = 0x01,
        // The 'data' holds an attribute resource identifier.
        TYPE_ATTRIBUTE = 0x02,
        // The 'data' holds an index into the containing resource table's
        // global value string pool.
        TYPE_STRING = 0x03,
        // The 'data' holds a single-precision floating point number.
        TYPE_FLOAT = 0x04,
        // The 'data' holds a complex number encoding a dimension value,
        // such as "100in".
        TYPE_DIMENSION = 0x05,
        // The 'data' holds a complex number encoding a fraction of a
        // container.
        TYPE_FRACTION = 0x06,

        // Beginning of integer flavors...
        TYPE_FIRST_INT = 0x10,

        // 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 0xn..n.
        TYPE_INT_HEX = 0x11,
        // The 'data' is either 0 or 1, for input "false" or "true" respectively.
        TYPE_INT_BOOLEAN = 0x12,

        // Beginning of color integer flavors...
        TYPE_FIRST_COLOR_INT = 0x1c,

        // The 'data' is a raw integer value of the form #aarrggbb.
        TYPE_INT_COLOR_ARGB8 = 0x1c,
        // The 'data' is a raw integer value of the form #rrggbb.
        TYPE_INT_COLOR_RGB8 = 0x1d,
        // The 'data' is a raw integer value of the form #argb.
        TYPE_INT_COLOR_ARGB4 = 0x1e,
        // The 'data' is a raw integer value of the form #rgb.
        TYPE_INT_COLOR_RGB4 = 0x1f,

        // ...end of integer flavors.
        TYPE_LAST_COLOR_INT = 0x1f,

        // ...end of integer flavors.
        TYPE_LAST_INT = 0x1f
    };

This definition is nested within the definition of struct Res_value (see frameworks/base/include/ResourceTypes.h lines 233-280).

2.3 Resource Value Data

The data field is a fixed size 32-bit integer. How it is interpreted depends upon the value of the type field.

Some of the possible interpretations are as

  • a boolean value

  • a float value

  • an integer value

  • an index into the Table chunk’s StringPool

  • a composite value

A number of constants used when the data is interpreted as a composite value are defined by the following anonymous C++ enum

   enum {
        // Where the unit type information is.  This gives us 16 possible
        // types, as defined below.
        COMPLEX_UNIT_SHIFT = 0,
        COMPLEX_UNIT_MASK = 0xf,

        // TYPE_DIMENSION: Value is raw pixels.
        COMPLEX_UNIT_PX = 0,
        // TYPE_DIMENSION: Value is Device Independent Pixels.
        COMPLEX_UNIT_DIP = 1,
        // TYPE_DIMENSION: Value is a Scaled device independent Pixels.
        COMPLEX_UNIT_SP = 2,
        // TYPE_DIMENSION: Value is in points.
        COMPLEX_UNIT_PT = 3,
        // TYPE_DIMENSION: Value is in inches.
        COMPLEX_UNIT_IN = 4,
        // TYPE_DIMENSION: Value is in millimeters.
        COMPLEX_UNIT_MM = 5,

        // TYPE_FRACTION: A basic fraction of the overall size.
        COMPLEX_UNIT_FRACTION = 0,
        // TYPE_FRACTION: A fraction of the parent size.
        COMPLEX_UNIT_FRACTION_PARENT = 1,

        // Where the radix information is, telling where the decimal place
        // appears in the mantissa.  This give us 4 possible fixed point
        // representations as defined below.
        COMPLEX_RADIX_SHIFT = 4,
        COMPLEX_RADIX_MASK = 0x3,

        // The mantissa is an integral number -- i.e., 0xnnnnnn.0
        COMPLEX_RADIX_23p0 = 0,
        // The mantissa magnitude is 16 bits -- i.e, 0xnnnn.nn
        COMPLEX_RADIX_16p7 = 1,
        // The mantissa magnitude is 8 bits -- i.e, 0xnn.nnnn
        COMPLEX_RADIX_8p15 = 2,
        // The mantissa magnitude is 0 bits -- i.e, 0x0.nnnnnn
        COMPLEX_RADIX_0p23 = 3,

        // Where the actual value is.  This gives us 23 bits of
        // precision.  The top bit is the sign.
        COMPLEX_MANTISSA_SHIFT = 8,
        COMPLEX_MANTISSA_MASK = 0xffffff
    };

This definition is nested within the definition of struct Res_value (see frameworks/base/include/ResourceTypes.h lines 284-326)

Advertisements

8 Comments »

  1. […] entry values both have a value type of TYPE_BOOLEAN as you would expect, but true is represented by the value 0xFFFFFFFF rather than 1 as specified by […]

    Pingback by Android Internals: Resources – Part Nine: Simple Resource Entry Examples « Just An Application — September 20, 2011 @ 4:34 am

  2. […] try and reduce the confusion resulting from the naming issues described here in what follows I am simply going to refer to instances of struct ResTable_map as […]

    Pingback by Android Internals: Resources – Part Ten: Complex Resource Entry Examples « Just An Application — September 22, 2011 @ 3:51 am

  3. […] typedValue is an instance of struct Res_value which specifies the value of the […]

    Pingback by Android Internals: Binary XML – Part Six: The XML Start Element Chunk « Just An Application — September 25, 2011 @ 7:11 am

  4. It’s fair to mention how references are resolved. From ResourceTypes.h:

    334 * This is a reference to a unique entry (a ResTable_entry structure)
    335 * in a resource table. The value is structured as: 0xpptteeee,
    336 * where pp is the package index, tt is the type index in that
    337 * package, and eeee is the entry index in that type. The package
    338 * and type values start at 1 for the first item, to help catch cases
    339 * where they have not been supplied.

    Comment by Pawel Veselov — November 21, 2011 @ 10:35 am

    • Thanks for the clarification. I’m trying to make a program (non-android) that tries to scan inside an .apk file and extract basic information, such as package name, app name, icon, etc.
      I’ve had success in parsing the androidmanifest.xml file. For some identifiers, it gives me these resourceID’s you’re referring to, like for the app name and the icon location inside the .apk (both strings AFAIK).
      I’m trying to write a simple parser for the resource file now, but it seems that I’ve hit a wall. My problem is that I can’t seem to locate successfully the resource from this ID. My search is like this: get the ID (eg. 0x7F02004), search for the 2nd package chunk, and then go to 4th entry/value pair and extract it. Did I get it right or am I looking just at a random position? I’m asking because, while I’m in the 2nd package chunk I can see that this chuck is for the strings.
      Thanks for the very detailed description!

      Comment by noctrex — January 21, 2013 @ 5:22 pm

      • I’ve just added a new post about Resource Ids and Resource lookup which hopefully will help

        simon

        Comment by Simon Lewis — January 22, 2013 @ 9:51 pm

  5. And also, though that says that ‘pp’ is “package index”, it’s frequently ‘7f’, which I assume is the package ID of the main application package. Whether it’s a magic number, or a exceptional reference.

    Comment by Pawel Veselov — November 21, 2011 @ 10:43 am

  6. […] this offset there will be either a simple or a complex resource entry which will specify the value of the […]

    Pingback by Android Internals: Resource Ids And Resource Lookup « Just An Application — January 22, 2013 @ 9:46 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

Create a free website or blog at WordPress.com.

%d bloggers like this: