113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross#include "idmap.h"
213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross#include <androidfw/AssetManager.h>
413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross#include <androidfw/ResourceTypes.h>
5ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include <utils/ByteOrder.h>
613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross#include <utils/String8.h>
713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross#include <fcntl.h>
913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross#include <sys/mman.h>
1013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross#include <sys/stat.h>
1113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
1213221c9cffdb289851411bdc73a9a5236fcb9291Colin Crossusing namespace android;
1313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
1413221c9cffdb289851411bdc73a9a5236fcb9291Colin Crossnamespace {
15f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski    static const uint32_t IDMAP_MAGIC = 0x504D4449;
1613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    static const size_t PATH_LENGTH = 256;
1713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
1813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    void printe(const char *fmt, ...);
1913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
2013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    class IdmapBuffer {
2113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        private:
22f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            const char* buf_;
2313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross            size_t len_;
24f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            size_t pos_;
2513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        public:
26f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            IdmapBuffer() : buf_((const char *)MAP_FAILED), len_(0), pos_(0) {}
2713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
2813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross            ~IdmapBuffer() {
2913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                if (buf_ != MAP_FAILED) {
30f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    munmap(const_cast<char*>(buf_), len_);
3113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                }
3213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross            }
3313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
34f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            status_t init(const char *idmap_path) {
3513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                struct stat st;
3613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                int fd;
3713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
3813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                if (stat(idmap_path, &st) < 0) {
3913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                    printe("failed to stat idmap '%s': %s\n", idmap_path, strerror(errno));
40f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    return UNKNOWN_ERROR;
4113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                }
4213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                len_ = st.st_size;
4313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                if ((fd = TEMP_FAILURE_RETRY(open(idmap_path, O_RDONLY))) < 0) {
4413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                    printe("failed to open idmap '%s': %s\n", idmap_path, strerror(errno));
45f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    return UNKNOWN_ERROR;
4613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                }
47f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                if ((buf_ = (const char*)mmap(NULL, len_, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) {
4813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                    close(fd);
4913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                    printe("failed to mmap idmap: %s\n", strerror(errno));
50f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    return UNKNOWN_ERROR;
5113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                }
5213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                close(fd);
53f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                return NO_ERROR;
5413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross            }
5513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
56f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            status_t nextUint32(uint32_t* i) {
5713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                if (!buf_) {
5813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                    printe("failed to read next uint32_t: buffer not initialized\n");
59f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    return UNKNOWN_ERROR;
6013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                }
61f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
62f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                if (pos_ + sizeof(uint32_t) > len_) {
6313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                    printe("failed to read next uint32_t: end of buffer reached at pos=0x%08x\n",
6413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                            pos_);
65f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    return UNKNOWN_ERROR;
66f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                }
67f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
68f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                if ((reinterpret_cast<uintptr_t>(buf_ + pos_) & 0x3) != 0) {
69f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    printe("failed to read next uint32_t: not aligned on 4-byte boundary\n");
70f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    return UNKNOWN_ERROR;
7113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                }
72f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
73f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                *i = dtohl(*reinterpret_cast<const uint32_t*>(buf_ + pos_));
74f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                pos_ += sizeof(uint32_t);
75f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                return NO_ERROR;
7613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross            }
7713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
78f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            status_t nextUint16(uint16_t* i) {
79f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                if (!buf_) {
80f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    printe("failed to read next uint16_t: buffer not initialized\n");
81f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    return UNKNOWN_ERROR;
82f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                }
83f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
84f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                if (pos_ + sizeof(uint16_t) > len_) {
85f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    printe("failed to read next uint16_t: end of buffer reached at pos=0x%08x\n",
86f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                            pos_);
87f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    return UNKNOWN_ERROR;
88f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                }
89f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
90f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                if ((reinterpret_cast<uintptr_t>(buf_ + pos_) & 0x1) != 0) {
91f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    printe("failed to read next uint32_t: not aligned on 2-byte boundary\n");
92f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    return UNKNOWN_ERROR;
93f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                }
94f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
95f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                *i = dtohs(*reinterpret_cast<const uint16_t*>(buf_ + pos_));
96f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                pos_ += sizeof(uint16_t);
97f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                return NO_ERROR;
98f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            }
99f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
100f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            status_t nextPath(char *b) {
10113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                if (!buf_) {
10213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                    printe("failed to read next path: buffer not initialized\n");
103f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    return UNKNOWN_ERROR;
10413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                }
10513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                if (pos_ + PATH_LENGTH > len_) {
10613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                    printe("failed to read next path: end of buffer reached at pos=0x%08x\n", pos_);
107f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    return UNKNOWN_ERROR;
10813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                }
10913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                memcpy(b, buf_ + pos_, PATH_LENGTH);
11013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                pos_ += PATH_LENGTH;
111f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                return NO_ERROR;
11213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross            }
11313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    };
11413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
115f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski    void printe(const char *fmt, ...) {
11613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        va_list ap;
11713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
11813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        va_start(ap, fmt);
11913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        fprintf(stderr, "error: ");
12013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        vfprintf(stderr, fmt, ap);
12113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        va_end(ap);
12213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    }
12313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
124f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski    void print_header() {
125f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        printf("SECTION      ENTRY        VALUE      COMMENT\n");
12613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    }
12713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
128f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski    void print(const char *section, const char *subsection, uint32_t value, const char *fmt, ...) {
12913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        va_list ap;
13013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
13113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        va_start(ap, fmt);
132f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        printf("%-12s %-12s 0x%08x ", section, subsection, value);
13313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        vprintf(fmt, ap);
13413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        printf("\n");
13513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        va_end(ap);
13613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    }
13713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
138f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski    void print_path(const char *section, const char *subsection, const char *fmt, ...) {
13913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        va_list ap;
14013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
14113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        va_start(ap, fmt);
142f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        printf("%-12s %-12s .......... ", section, subsection);
14313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        vprintf(fmt, ap);
14413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        printf("\n");
14513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        va_end(ap);
14613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    }
14713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
148f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski    status_t resource_metadata(const AssetManager& am, uint32_t res_id,
149f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            String8 *package, String8 *type, String8 *name) {
15013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        const ResTable& rt = am.getResources();
15113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        struct ResTable::resource_name data;
15213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        if (!rt.getResourceName(res_id, false, &data)) {
15313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross            printe("failed to get resource name id=0x%08x\n", res_id);
154f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            return UNKNOWN_ERROR;
15513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        }
156cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe        if (package != NULL) {
15713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross            *package = String8(String16(data.package, data.packageLen));
15813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        }
159cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe        if (type != NULL) {
16013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross            *type = String8(String16(data.type, data.typeLen));
16113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        }
162cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe        if (name != NULL) {
16313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross            *name = String8(String16(data.name, data.nameLen));
16413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        }
165f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        return NO_ERROR;
16613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    }
16713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
168f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski    status_t parse_idmap_header(IdmapBuffer& buf, AssetManager& am) {
169f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        uint32_t i;
17013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        char path[PATH_LENGTH];
17113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
172f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        status_t err = buf.nextUint32(&i);
173f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        if (err != NO_ERROR) {
174f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            return err;
175f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        }
176f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
17713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        if (i != IDMAP_MAGIC) {
17813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross            printe("not an idmap file: actual magic constant 0x%08x does not match expected magic "
17913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                    "constant 0x%08x\n", i, IDMAP_MAGIC);
180f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            return UNKNOWN_ERROR;
18113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        }
182f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
18313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        print_header();
184f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        print("IDMAP HEADER", "magic", i, "");
185f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
186f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        err = buf.nextUint32(&i);
187f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        if (err != NO_ERROR) {
188f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            return err;
189f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        }
190f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        print("", "version", i, "");
19113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
192f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        err = buf.nextUint32(&i);
193f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        if (err != NO_ERROR) {
194f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            return err;
195f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        }
196f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        print("", "base crc", i, "");
19713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
198f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        err = buf.nextUint32(&i);
199f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        if (err != NO_ERROR) {
200f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            return err;
201f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        }
202f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        print("", "overlay crc", i, "");
20313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
204f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        err = buf.nextPath(path);
205f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        if (err != NO_ERROR) {
20613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross            // printe done from IdmapBuffer::nextPath
207f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            return err;
20813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        }
209f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        print_path("", "base path", "%s", path);
210f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
21113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        if (!am.addAssetPath(String8(path), NULL)) {
21213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross            printe("failed to add '%s' as asset path\n", path);
213f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            return UNKNOWN_ERROR;
21413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        }
21513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
216f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        err = buf.nextPath(path);
217f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        if (err != NO_ERROR) {
21813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross            // printe done from IdmapBuffer::nextPath
219f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            return err;
22013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        }
221f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        print_path("", "overlay path", "%s", path);
22213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
223f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        return NO_ERROR;
22413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    }
22513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
226f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski    status_t parse_data(IdmapBuffer& buf, const AssetManager& am) {
227f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        const uint32_t packageId = am.getResources().getBasePackageId(0);
22813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
229f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        uint16_t data16;
230f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        status_t err = buf.nextUint16(&data16);
231f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        if (err != NO_ERROR) {
232f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            return err;
233f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        }
234f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        print("DATA HEADER", "target pkg", static_cast<uint32_t>(data16), "");
23513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
236f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        err = buf.nextUint16(&data16);
237f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        if (err != NO_ERROR) {
238f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            return err;
23913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        }
240f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        print("", "types count", static_cast<uint32_t>(data16), "");
24113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
242f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        uint32_t typeCount = static_cast<uint32_t>(data16);
243f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        while (typeCount > 0) {
244f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            typeCount--;
245f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
246f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            err = buf.nextUint16(&data16);
247f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            if (err != NO_ERROR) {
248f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                return err;
249f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            }
250f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            const uint32_t targetTypeId = static_cast<uint32_t>(data16);
251f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            print("DATA BLOCK", "target type", targetTypeId, "");
25213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
253f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            err = buf.nextUint16(&data16);
254f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            if (err != NO_ERROR) {
255f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                return err;
256f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            }
257f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            print("", "overlay type", static_cast<uint32_t>(data16), "");
258f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
259f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            err = buf.nextUint16(&data16);
260f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            if (err != NO_ERROR) {
261f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                return err;
262f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            }
263f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            const uint32_t entryCount = static_cast<uint32_t>(data16);
264f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            print("", "entry count", entryCount, "");
265f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
266f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            err = buf.nextUint16(&data16);
267f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            if (err != NO_ERROR) {
268f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                return err;
269f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            }
270f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            const uint32_t entryOffset = static_cast<uint32_t>(data16);
271f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            print("", "entry offset", entryOffset, "");
272f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
273f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            for (uint32_t i = 0; i < entryCount; i++) {
274f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                uint32_t data32;
275f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                err = buf.nextUint32(&data32);
276f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                if (err != NO_ERROR) {
277f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    return err;
27813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                }
279f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
280f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                uint32_t resID = (packageId << 24) | (targetTypeId << 16) | (entryOffset + i);
281f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                String8 type;
282f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                String8 name;
283f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                err = resource_metadata(am, resID, NULL, &type, &name);
284f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                if (err != NO_ERROR) {
285f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    return err;
286f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                }
287f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                print("", "entry", data32, "%s/%s", type.string(), name.string());
28813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross            }
28913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        }
29013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
291f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        return NO_ERROR;
29213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    }
29313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross}
29413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
295f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinskiint idmap_inspect(const char *idmap_path) {
29613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    IdmapBuffer buf;
29713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    if (buf.init(idmap_path) < 0) {
29813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        // printe done from IdmapBuffer::init
29913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        return EXIT_FAILURE;
30013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    }
30113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    AssetManager am;
302f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski    if (parse_idmap_header(buf, am) != NO_ERROR) {
30313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        // printe done from parse_idmap_header
30413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        return EXIT_FAILURE;
30513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    }
306f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski    if (parse_data(buf, am) != NO_ERROR) {
30713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        // printe done from parse_data_header
30813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        return EXIT_FAILURE;
30913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    }
31013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    return EXIT_SUCCESS;
31113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross}
312