inspect.cpp revision f90f2f8dc36e7243b85e0b6a7fd5a590893c827e
113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross#include "idmap.h"
213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross#include <androidfw/AssetManager.h>
413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross#include <androidfw/ResourceTypes.h>
513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross#include <utils/String8.h>
613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross#include <fcntl.h>
813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross#include <sys/mman.h>
913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross#include <sys/stat.h>
1013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
1113221c9cffdb289851411bdc73a9a5236fcb9291Colin Crossusing namespace android;
1213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
1313221c9cffdb289851411bdc73a9a5236fcb9291Colin Crossnamespace {
14f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski    static const uint32_t IDMAP_MAGIC = 0x504D4449;
1513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    static const size_t PATH_LENGTH = 256;
1613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
1713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    void printe(const char *fmt, ...);
1813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
1913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    class IdmapBuffer {
2013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        private:
21f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            const char* buf_;
2213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross            size_t len_;
23f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            size_t pos_;
2413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        public:
25f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            IdmapBuffer() : buf_((const char *)MAP_FAILED), len_(0), pos_(0) {}
2613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
2713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross            ~IdmapBuffer() {
2813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                if (buf_ != MAP_FAILED) {
29f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    munmap(const_cast<char*>(buf_), len_);
3013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                }
3113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross            }
3213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
33f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            status_t init(const char *idmap_path) {
3413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                struct stat st;
3513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                int fd;
3613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
3713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                if (stat(idmap_path, &st) < 0) {
3813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                    printe("failed to stat idmap '%s': %s\n", idmap_path, strerror(errno));
39f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    return UNKNOWN_ERROR;
4013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                }
4113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                len_ = st.st_size;
4213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                if ((fd = TEMP_FAILURE_RETRY(open(idmap_path, O_RDONLY))) < 0) {
4313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                    printe("failed to open idmap '%s': %s\n", idmap_path, strerror(errno));
44f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    return UNKNOWN_ERROR;
4513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                }
46f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                if ((buf_ = (const char*)mmap(NULL, len_, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) {
4713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                    close(fd);
4813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                    printe("failed to mmap idmap: %s\n", strerror(errno));
49f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    return UNKNOWN_ERROR;
5013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                }
5113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                close(fd);
52f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                return NO_ERROR;
5313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross            }
5413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
55f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            status_t nextUint32(uint32_t* i) {
5613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                if (!buf_) {
5713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                    printe("failed to read next uint32_t: buffer not initialized\n");
58f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    return UNKNOWN_ERROR;
5913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                }
60f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
61f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                if (pos_ + sizeof(uint32_t) > len_) {
6213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                    printe("failed to read next uint32_t: end of buffer reached at pos=0x%08x\n",
6313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                            pos_);
64f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    return UNKNOWN_ERROR;
65f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                }
66f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
67f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                if ((reinterpret_cast<uintptr_t>(buf_ + pos_) & 0x3) != 0) {
68f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    printe("failed to read next uint32_t: not aligned on 4-byte boundary\n");
69f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    return UNKNOWN_ERROR;
7013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                }
71f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
72f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                *i = dtohl(*reinterpret_cast<const uint32_t*>(buf_ + pos_));
73f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                pos_ += sizeof(uint32_t);
74f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                return NO_ERROR;
7513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross            }
7613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
77f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            status_t nextUint16(uint16_t* i) {
78f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                if (!buf_) {
79f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    printe("failed to read next uint16_t: buffer not initialized\n");
80f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    return UNKNOWN_ERROR;
81f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                }
82f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
83f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                if (pos_ + sizeof(uint16_t) > len_) {
84f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    printe("failed to read next uint16_t: end of buffer reached at pos=0x%08x\n",
85f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                            pos_);
86f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    return UNKNOWN_ERROR;
87f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                }
88f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
89f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                if ((reinterpret_cast<uintptr_t>(buf_ + pos_) & 0x1) != 0) {
90f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    printe("failed to read next uint32_t: not aligned on 2-byte boundary\n");
91f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    return UNKNOWN_ERROR;
92f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                }
93f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
94f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                *i = dtohs(*reinterpret_cast<const uint16_t*>(buf_ + pos_));
95f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                pos_ += sizeof(uint16_t);
96f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                return NO_ERROR;
97f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            }
98f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
99f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            status_t nextPath(char *b) {
10013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                if (!buf_) {
10113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                    printe("failed to read next path: buffer not initialized\n");
102f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    return UNKNOWN_ERROR;
10313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                }
10413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                if (pos_ + PATH_LENGTH > len_) {
10513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                    printe("failed to read next path: end of buffer reached at pos=0x%08x\n", pos_);
106f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    return UNKNOWN_ERROR;
10713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                }
10813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                memcpy(b, buf_ + pos_, PATH_LENGTH);
10913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                pos_ += PATH_LENGTH;
110f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                return NO_ERROR;
11113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross            }
11213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    };
11313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
114f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski    void printe(const char *fmt, ...) {
11513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        va_list ap;
11613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
11713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        va_start(ap, fmt);
11813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        fprintf(stderr, "error: ");
11913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        vfprintf(stderr, fmt, ap);
12013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        va_end(ap);
12113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    }
12213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
123f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski    void print_header() {
124f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        printf("SECTION      ENTRY        VALUE      COMMENT\n");
12513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    }
12613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
127f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski    void print(const char *section, const char *subsection, uint32_t value, const char *fmt, ...) {
12813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        va_list ap;
12913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
13013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        va_start(ap, fmt);
131f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        printf("%-12s %-12s 0x%08x ", section, subsection, value);
13213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        vprintf(fmt, ap);
13313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        printf("\n");
13413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        va_end(ap);
13513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    }
13613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
137f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski    void print_path(const char *section, const char *subsection, const char *fmt, ...) {
13813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        va_list ap;
13913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
14013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        va_start(ap, fmt);
141f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        printf("%-12s %-12s .......... ", section, subsection);
14213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        vprintf(fmt, ap);
14313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        printf("\n");
14413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        va_end(ap);
14513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    }
14613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
147f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski    status_t resource_metadata(const AssetManager& am, uint32_t res_id,
148f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            String8 *package, String8 *type, String8 *name) {
14913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        const ResTable& rt = am.getResources();
15013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        struct ResTable::resource_name data;
15113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        if (!rt.getResourceName(res_id, false, &data)) {
15213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross            printe("failed to get resource name id=0x%08x\n", res_id);
153f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            return UNKNOWN_ERROR;
15413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        }
15513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        if (package) {
15613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross            *package = String8(String16(data.package, data.packageLen));
15713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        }
15813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        if (type) {
15913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross            *type = String8(String16(data.type, data.typeLen));
16013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        }
16113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        if (name) {
16213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross            *name = String8(String16(data.name, data.nameLen));
16313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        }
164f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        return NO_ERROR;
16513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    }
16613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
167f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski    status_t parse_idmap_header(IdmapBuffer& buf, AssetManager& am) {
168f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        uint32_t i;
16913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        char path[PATH_LENGTH];
17013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
171f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        status_t err = buf.nextUint32(&i);
172f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        if (err != NO_ERROR) {
173f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            return err;
174f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        }
175f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
17613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        if (i != IDMAP_MAGIC) {
17713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross            printe("not an idmap file: actual magic constant 0x%08x does not match expected magic "
17813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                    "constant 0x%08x\n", i, IDMAP_MAGIC);
179f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            return UNKNOWN_ERROR;
18013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        }
181f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
18213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        print_header();
183f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        print("IDMAP HEADER", "magic", i, "");
184f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
185f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        err = buf.nextUint32(&i);
186f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        if (err != NO_ERROR) {
187f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            return err;
188f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        }
189f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        print("", "version", i, "");
19013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
191f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        err = buf.nextUint32(&i);
192f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        if (err != NO_ERROR) {
193f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            return err;
194f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        }
195f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        print("", "base crc", i, "");
19613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
197f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        err = buf.nextUint32(&i);
198f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        if (err != NO_ERROR) {
199f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            return err;
200f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        }
201f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        print("", "overlay crc", i, "");
20213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
203f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        err = buf.nextPath(path);
204f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        if (err != NO_ERROR) {
20513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross            // printe done from IdmapBuffer::nextPath
206f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            return err;
20713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        }
208f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        print_path("", "base path", "%s", path);
209f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
21013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        if (!am.addAssetPath(String8(path), NULL)) {
21113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross            printe("failed to add '%s' as asset path\n", path);
212f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            return UNKNOWN_ERROR;
21313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        }
21413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
215f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        err = buf.nextPath(path);
216f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        if (err != NO_ERROR) {
21713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross            // printe done from IdmapBuffer::nextPath
218f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            return err;
21913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        }
220f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        print_path("", "overlay path", "%s", path);
22113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
222f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        return NO_ERROR;
22313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    }
22413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
225f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski    status_t parse_data(IdmapBuffer& buf, const AssetManager& am) {
226f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        const uint32_t packageId = am.getResources().getBasePackageId(0);
22713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
228f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        uint16_t data16;
229f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        status_t err = buf.nextUint16(&data16);
230f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        if (err != NO_ERROR) {
231f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            return err;
232f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        }
233f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        print("DATA HEADER", "target pkg", static_cast<uint32_t>(data16), "");
23413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
235f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        err = buf.nextUint16(&data16);
236f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        if (err != NO_ERROR) {
237f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            return err;
23813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        }
239f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        print("", "types count", static_cast<uint32_t>(data16), "");
24013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
241f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        uint32_t typeCount = static_cast<uint32_t>(data16);
242f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        while (typeCount > 0) {
243f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            typeCount--;
244f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
245f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            err = buf.nextUint16(&data16);
246f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            if (err != NO_ERROR) {
247f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                return err;
248f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            }
249f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            const uint32_t targetTypeId = static_cast<uint32_t>(data16);
250f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            print("DATA BLOCK", "target type", targetTypeId, "");
25113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
252f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            err = buf.nextUint16(&data16);
253f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            if (err != NO_ERROR) {
254f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                return err;
255f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            }
256f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            print("", "overlay type", static_cast<uint32_t>(data16), "");
257f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
258f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            err = buf.nextUint16(&data16);
259f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            if (err != NO_ERROR) {
260f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                return err;
261f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            }
262f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            const uint32_t entryCount = static_cast<uint32_t>(data16);
263f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            print("", "entry count", entryCount, "");
264f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
265f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            err = buf.nextUint16(&data16);
266f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            if (err != NO_ERROR) {
267f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                return err;
268f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            }
269f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            const uint32_t entryOffset = static_cast<uint32_t>(data16);
270f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            print("", "entry offset", entryOffset, "");
271f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
272f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski            for (uint32_t i = 0; i < entryCount; i++) {
273f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                uint32_t data32;
274f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                err = buf.nextUint32(&data32);
275f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                if (err != NO_ERROR) {
276f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    return err;
27713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross                }
278f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski
279f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                uint32_t resID = (packageId << 24) | (targetTypeId << 16) | (entryOffset + i);
280f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                String8 type;
281f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                String8 name;
282f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                err = resource_metadata(am, resID, NULL, &type, &name);
283f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                if (err != NO_ERROR) {
284f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                    return err;
285f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                }
286f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski                print("", "entry", data32, "%s/%s", type.string(), name.string());
28713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross            }
28813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        }
28913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
290f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski        return NO_ERROR;
29113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    }
29213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross}
29313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross
294f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinskiint idmap_inspect(const char *idmap_path) {
29513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    IdmapBuffer buf;
29613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    if (buf.init(idmap_path) < 0) {
29713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        // printe done from IdmapBuffer::init
29813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        return EXIT_FAILURE;
29913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    }
30013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    AssetManager am;
301f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski    if (parse_idmap_header(buf, am) != NO_ERROR) {
30213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        // printe done from parse_idmap_header
30313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        return EXIT_FAILURE;
30413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    }
305f90f2f8dc36e7243b85e0b6a7fd5a590893c827eAdam Lesinski    if (parse_data(buf, am) != NO_ERROR) {
30613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        // printe done from parse_data_header
30713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross        return EXIT_FAILURE;
30813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    }
30913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross    return EXIT_SUCCESS;
31013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross}
311