Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support sparse flag #2885

Closed
wants to merge 1 commit into from
Closed

support sparse flag #2885

wants to merge 1 commit into from

Conversation

iamr0s
Copy link
Contributor

@iamr0s iamr0s commented Sep 19, 2022

ResourcesType.h (Android 7.1.2):

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;
};

Resources.h (Android 8.0.0):

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;
    
    enum {
        // If set, the entry is sparse, and encodes both the entry ID and offset into each entry,
        // and a binary search is used to find the key. Only available on platforms >= O.
        // Mark any types that use this with a v26 qualifier to prevent runtime issues on older
        // platforms.
        FLAG_SPARSE = 0x01,
    };
    uint8_t flags;

    // Must be 0.
    uint16_t reserved;
    
    // 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. This must always be last.
    ResTable_config config;
};

If set, we can read it by this way:

val offsetMap = mutableMapOf<Int, Int>()
for (i in 0 until header.entryCount)
    offsetMap[i] = reader.int

If set, the entry is sparse, and encodes both the entry ID and offset into each entry, so we can read it by this way

val offsetMap = mutableMapOf<Int, Int>()
for (i in 0 until header.entryCount)
    if (header.flags.isSparse) offsetMap[reader.uShort.toInt()] = (reader.uShort * 4u).toInt()
    else offsetMap[i] = reader.int

when FLAG_SPARSE is not set, we can get offset by read a int.
when FLAG_SPARSE is set, we can get entry id by read a unsigned short, then get offset by read a unsigned short;

@iBotPeaches
Copy link
Owner

Thanks for details and patch. I've kicked off CI process and will return to review more thoroughly.

@iBotPeaches
Copy link
Owner

thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants