Loading libs/androidfw/AssetManager.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -349,7 +349,7 @@ bool AssetManager::createIdmap(const char* targetApkPath, const char* overlayApk goto exit; } } ret = tables[0].createIdmap(tables[1], targetCrc, overlayCrc, ret = tables[1].createIdmap(tables[0], targetCrc, overlayCrc, targetApkPath, overlayApkPath, (void**)outData, outSize) == NO_ERROR; } Loading libs/androidfw/ResourceTypes.cpp +131 −121 Original line number Diff line number Diff line Loading @@ -26,7 +26,9 @@ #include <algorithm> #include <limits> #include <map> #include <memory> #include <set> #include <type_traits> #include <android-base/macros.h> Loading Loading @@ -7033,170 +7035,178 @@ status_t DynamicRefTable::lookupResourceValue(Res_value* value) const { return NO_ERROR; } struct IdmapTypeMap { ssize_t overlayTypeId; size_t entryOffset; Vector<uint32_t> entryMap; struct IdmapMatchingResources { void Add(uint32_t targetResId, uint32_t overlayResId) { uint8_t targetTypeid = Res_GETTYPE(targetResId); if (typeMappings.find(targetTypeid) == typeMappings.end()) { typeMappings.emplace(targetTypeid, std::set<std::pair<uint32_t, uint32_t>>()); } auto& entries = typeMappings[targetTypeid]; entries.insert(std::make_pair(targetResId, overlayResId)); } void FixPadding() { for (auto ti = typeMappings.cbegin(); ti != typeMappings.cend(); ++ti) { uint32_t last_seen = 0xffffffff; size_t total_entries = 0; for (auto ei = ti->second.cbegin(); ei != ti->second.cend(); ++ei) { assert(last_seen == 0xffffffff || last_seen < ei->first); entryPadding[ei->first] = (last_seen == 0xffffffff) ? 0 : ei->first - last_seen - 1; last_seen = ei->first; total_entries += 1 + entryPadding[ei->first]; } numberOfEntriesIncludingPadding[ti->first] = total_entries; } } // resource type ID in context of target -> set of resource entries mapping target -> overlay std::map<uint8_t, std::set<std::pair<uint32_t, uint32_t>>> typeMappings; // resource ID in context of target -> trailing padding for that resource (call FixPadding // before use) std::map<uint32_t, size_t> entryPadding; // resource type ID in context of target -> total number of entries, including padding entries, // for that type (call FixPadding before use) std::map<uint8_t, size_t> numberOfEntriesIncludingPadding; }; status_t ResTable::createIdmap(const ResTable& overlay, status_t ResTable::createIdmap(const ResTable& targetResTable, uint32_t targetCrc, uint32_t overlayCrc, const char* targetPath, const char* overlayPath, void** outData, size_t* outSize) const { // see README for details on the format of map if (mPackageGroups.size() == 0) { ALOGW("idmap: target package has no package groups, cannot create idmap\n"); if (targetPath == NULL || overlayPath == NULL || outData == NULL || outSize == NULL) { ALOGE("idmap: unexpected NULL parameter"); return UNKNOWN_ERROR; } if (mPackageGroups[0]->packages.size() == 0) { ALOGW("idmap: target package has no packages in its first package group, " "cannot create idmap\n"); if (strlen(targetPath) > 255) { ALOGE("idmap: target path exceeds idmap file format limit of 255 chars"); return UNKNOWN_ERROR; } if (strlen(overlayPath) > 255) { ALOGE("idmap: overlay path exceeds idmap file format limit of 255 chars"); return UNKNOWN_ERROR; } if (mPackageGroups.size() == 0 || mPackageGroups[0]->packages.size() == 0) { ALOGE("idmap: invalid overlay package"); return UNKNOWN_ERROR; } if (targetResTable.mPackageGroups.size() == 0 || targetResTable.mPackageGroups[0]->packages.size() == 0) { ALOGE("idmap: invalid target package"); return UNKNOWN_ERROR; } // The number of resources overlaid that were not explicitly marked overlayable. size_t forcedOverlayCount = 0u; KeyedVector<uint8_t, IdmapTypeMap> map; // overlaid packages are assumed to contain only one package group const PackageGroup* pg = mPackageGroups[0]; // starting size is header *outSize = ResTable::IDMAP_HEADER_SIZE_BYTES; const ResTable_package* targetPackageStruct = targetResTable.mPackageGroups[0]->packages[0]->package; const size_t tmpNameSize = arraysize(targetPackageStruct->name); char16_t tmpName[tmpNameSize]; strcpy16_dtoh(tmpName, targetPackageStruct->name, tmpNameSize); const String16 targetPackageName(tmpName); // target package id and number of types in map *outSize += 2 * sizeof(uint16_t); const PackageGroup* packageGroup = mPackageGroups[0]; // overlay packages are assumed to contain only one package group const ResTable_package* overlayPackageStruct = overlay.mPackageGroups[0]->packages[0]->package; char16_t tmpName[sizeof(overlayPackageStruct->name)/sizeof(overlayPackageStruct->name[0])]; strcpy16_dtoh(tmpName, overlayPackageStruct->name, sizeof(overlayPackageStruct->name)/sizeof(overlayPackageStruct->name[0])); const String16 overlayPackage(tmpName); // the number of resources overlaid that were not explicitly marked overlayable size_t forcedOverlayCount = 0u; for (size_t typeIndex = 0; typeIndex < pg->types.size(); ++typeIndex) { const TypeList& typeList = pg->types[typeIndex]; // find the resources that exist in both packages IdmapMatchingResources matchingResources; for (size_t typeIndex = 0; typeIndex < packageGroup->types.size(); ++typeIndex) { const TypeList& typeList = packageGroup->types[typeIndex]; if (typeList.isEmpty()) { continue; } const Type* typeConfigs = typeList[0]; IdmapTypeMap typeMap; typeMap.overlayTypeId = -1; typeMap.entryOffset = 0; for (size_t entryIndex = 0; entryIndex < typeConfigs->entryCount; ++entryIndex) { uint32_t resID = Res_MAKEID(pg->id - 1, typeIndex, entryIndex); resource_name resName; if (!this->getResourceName(resID, false, &resName)) { if (typeMap.entryMap.isEmpty()) { typeMap.entryOffset++; } uint32_t overlay_resid = Res_MAKEID(packageGroup->id - 1, typeIndex, entryIndex); resource_name current_res; if (!getResourceName(overlay_resid, false, ¤t_res)) { continue; } uint32_t typeSpecFlags = 0u; const String16 overlayType(resName.type, resName.typeLen); const String16 overlayName(resName.name, resName.nameLen); uint32_t overlayResID = overlay.identifierForName(overlayName.string(), overlayName.size(), overlayType.string(), overlayType.size(), overlayPackage.string(), overlayPackage.size(), const uint32_t target_resid = targetResTable.identifierForName( current_res.name, current_res.nameLen, current_res.type, current_res.typeLen, targetPackageName.string(), targetPackageName.size(), &typeSpecFlags); if (overlayResID == 0) { // No such target resource was found. if (typeMap.entryMap.isEmpty()) { typeMap.entryOffset++; } if (target_resid == 0) { continue; } // Now that we know this is being overlaid, check if it can be, and emit a warning if // it can't. if ((dtohl(typeConfigs->typeSpecFlags[entryIndex]) & ResTable_typeSpec::SPEC_OVERLAYABLE) == 0) { forcedOverlayCount++; ++forcedOverlayCount; } if (typeMap.overlayTypeId == -1) { typeMap.overlayTypeId = Res_GETTYPE(overlayResID) + 1; matchingResources.Add(target_resid, overlay_resid); } if (Res_GETTYPE(overlayResID) + 1 != static_cast<size_t>(typeMap.overlayTypeId)) { ALOGE("idmap: can't mix type ids in entry map. Resource 0x%08x maps to 0x%08x" " but entries should map to resources of type %02zx", resID, overlayResID, typeMap.overlayTypeId); return BAD_TYPE; } if (typeMap.entryOffset + typeMap.entryMap.size() < entryIndex) { // pad with 0xffffffff's (indicating non-existing entries) before adding this entry size_t index = typeMap.entryMap.size(); size_t numItems = entryIndex - (typeMap.entryOffset + index); if (typeMap.entryMap.insertAt(0xffffffff, index, numItems) < 0) { return NO_MEMORY; } } typeMap.entryMap.add(Res_GETENTRY(overlayResID)); if (matchingResources.typeMappings.empty()) { ALOGE("idmap: no matching resources"); return UNKNOWN_ERROR; } if (!typeMap.entryMap.isEmpty()) { if (map.add(static_cast<uint8_t>(typeIndex), typeMap) < 0) { return NO_MEMORY; } *outSize += (4 * sizeof(uint16_t)) + (typeMap.entryMap.size() * sizeof(uint32_t)); } } matchingResources.FixPadding(); if (map.isEmpty()) { ALOGW("idmap: no resources in overlay package present in base package"); return UNKNOWN_ERROR; // write idmap *outSize = ResTable::IDMAP_HEADER_SIZE_BYTES; // magic, version, target and overlay crc *outSize += 2 * sizeof(uint16_t); // target package id, type count const auto typesEnd = matchingResources.typeMappings.cend(); for (auto ti = matchingResources.typeMappings.cbegin(); ti != typesEnd; ++ti) { *outSize += 4 * sizeof(uint16_t); // target type, overlay type, entry count, entry offset *outSize += matchingResources.numberOfEntriesIncludingPadding[ti->first] * sizeof(uint32_t); // entries } if ((*outData = malloc(*outSize)) == NULL) { return NO_MEMORY; } uint32_t* data = (uint32_t*)*outData; *data++ = htodl(IDMAP_MAGIC); *data++ = htodl(ResTable::IDMAP_CURRENT_VERSION); *data++ = htodl(targetCrc); *data++ = htodl(overlayCrc); const char* paths[] = { targetPath, overlayPath }; for (int j = 0; j < 2; ++j) { char* p = (char*)data; const char* path = paths[j]; const size_t I = strlen(path); if (I > 255) { ALOGV("path exceeds expected 255 characters: %s\n", path); return UNKNOWN_ERROR; } // write idmap header uint32_t* data = reinterpret_cast<uint32_t*>(*outData); *data++ = htodl(IDMAP_MAGIC); // write: magic *data++ = htodl(ResTable::IDMAP_CURRENT_VERSION); // write: version *data++ = htodl(targetCrc); // write: target crc *data++ = htodl(overlayCrc); // write: overlay crc char* charData = reinterpret_cast<char*>(data); size_t pathLen = strlen(targetPath); for (size_t i = 0; i < 256; ++i) { *p++ = i < I ? path[i] : '\0'; *charData++ = i < pathLen ? targetPath[i] : '\0'; // write: target path } data += 256 / sizeof(uint32_t); pathLen = strlen(overlayPath); for (size_t i = 0; i < 256; ++i) { *charData++ = i < pathLen ? overlayPath[i] : '\0'; // write: overlay path } const size_t mapSize = map.size(); data += (2 * 256) / sizeof(uint32_t); // write idmap data header uint16_t* typeData = reinterpret_cast<uint16_t*>(data); *typeData++ = htods(pg->id); *typeData++ = htods(mapSize); for (size_t i = 0; i < mapSize; ++i) { uint8_t targetTypeId = map.keyAt(i); const IdmapTypeMap& typeMap = map[i]; *typeData++ = htods(targetTypeId + 1); *typeData++ = htods(typeMap.overlayTypeId); *typeData++ = htods(typeMap.entryMap.size()); *typeData++ = htods(typeMap.entryOffset); const size_t entryCount = typeMap.entryMap.size(); uint32_t* entries = reinterpret_cast<uint32_t*>(typeData); for (size_t j = 0; j < entryCount; j++) { entries[j] = htodl(typeMap.entryMap[j]); *typeData++ = htods(targetPackageStruct->id); // write: target package id *typeData++ = htods(static_cast<uint16_t>(matchingResources.typeMappings.size())); // write: type count // write idmap data for (auto ti = matchingResources.typeMappings.cbegin(); ti != typesEnd; ++ti) { const size_t entryCount = matchingResources.numberOfEntriesIncludingPadding[ti->first]; auto ei = ti->second.cbegin(); *typeData++ = htods(Res_GETTYPE(ei->first) + 1); // write: target type id *typeData++ = htods(Res_GETTYPE(ei->second) + 1); // write: overlay type id *typeData++ = htods(entryCount); // write: entry count *typeData++ = htods(Res_GETENTRY(ei->first)); // write: (target) entry offset uint32_t *entryData = reinterpret_cast<uint32_t*>(typeData); for (; ei != ti->second.cend(); ++ei) { const size_t padding = matchingResources.entryPadding[ei->first]; for (size_t i = 0; i < padding; ++i) { *entryData++ = htodl(0xffffffff); // write: padding } *entryData++ = htodl(Res_GETENTRY(ei->second)); // write: (overlay) entry } typeData += entryCount * 2; } Loading libs/androidfw/include/androidfw/ResourceTypes.h +1 −1 Original line number Diff line number Diff line Loading @@ -1990,7 +1990,7 @@ public: // Return value: on success: NO_ERROR; caller is responsible for free-ing // outData (using free(3)). On failure, any status_t value other than // NO_ERROR; the caller should not free outData. status_t createIdmap(const ResTable& overlay, status_t createIdmap(const ResTable& targetResTable, uint32_t targetCrc, uint32_t overlayCrc, const char* targetPath, const char* overlayPath, void** outData, size_t* outSize) const; Loading libs/androidfw/tests/Idmap_test.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -40,7 +40,7 @@ class IdmapTest : public ::testing::Test { ASSERT_EQ(NO_ERROR, overlay_table.add(overlay_data_.data(), overlay_data_.size())); char target_name[256] = "com.android.basic"; ASSERT_EQ(NO_ERROR, target_table_.createIdmap(overlay_table, 0, 0, target_name, target_name, ASSERT_EQ(NO_ERROR, overlay_table.createIdmap(target_table_, 0, 0, target_name, target_name, &data_, &data_size_)); } Loading Loading
libs/androidfw/AssetManager.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -349,7 +349,7 @@ bool AssetManager::createIdmap(const char* targetApkPath, const char* overlayApk goto exit; } } ret = tables[0].createIdmap(tables[1], targetCrc, overlayCrc, ret = tables[1].createIdmap(tables[0], targetCrc, overlayCrc, targetApkPath, overlayApkPath, (void**)outData, outSize) == NO_ERROR; } Loading
libs/androidfw/ResourceTypes.cpp +131 −121 Original line number Diff line number Diff line Loading @@ -26,7 +26,9 @@ #include <algorithm> #include <limits> #include <map> #include <memory> #include <set> #include <type_traits> #include <android-base/macros.h> Loading Loading @@ -7033,170 +7035,178 @@ status_t DynamicRefTable::lookupResourceValue(Res_value* value) const { return NO_ERROR; } struct IdmapTypeMap { ssize_t overlayTypeId; size_t entryOffset; Vector<uint32_t> entryMap; struct IdmapMatchingResources { void Add(uint32_t targetResId, uint32_t overlayResId) { uint8_t targetTypeid = Res_GETTYPE(targetResId); if (typeMappings.find(targetTypeid) == typeMappings.end()) { typeMappings.emplace(targetTypeid, std::set<std::pair<uint32_t, uint32_t>>()); } auto& entries = typeMappings[targetTypeid]; entries.insert(std::make_pair(targetResId, overlayResId)); } void FixPadding() { for (auto ti = typeMappings.cbegin(); ti != typeMappings.cend(); ++ti) { uint32_t last_seen = 0xffffffff; size_t total_entries = 0; for (auto ei = ti->second.cbegin(); ei != ti->second.cend(); ++ei) { assert(last_seen == 0xffffffff || last_seen < ei->first); entryPadding[ei->first] = (last_seen == 0xffffffff) ? 0 : ei->first - last_seen - 1; last_seen = ei->first; total_entries += 1 + entryPadding[ei->first]; } numberOfEntriesIncludingPadding[ti->first] = total_entries; } } // resource type ID in context of target -> set of resource entries mapping target -> overlay std::map<uint8_t, std::set<std::pair<uint32_t, uint32_t>>> typeMappings; // resource ID in context of target -> trailing padding for that resource (call FixPadding // before use) std::map<uint32_t, size_t> entryPadding; // resource type ID in context of target -> total number of entries, including padding entries, // for that type (call FixPadding before use) std::map<uint8_t, size_t> numberOfEntriesIncludingPadding; }; status_t ResTable::createIdmap(const ResTable& overlay, status_t ResTable::createIdmap(const ResTable& targetResTable, uint32_t targetCrc, uint32_t overlayCrc, const char* targetPath, const char* overlayPath, void** outData, size_t* outSize) const { // see README for details on the format of map if (mPackageGroups.size() == 0) { ALOGW("idmap: target package has no package groups, cannot create idmap\n"); if (targetPath == NULL || overlayPath == NULL || outData == NULL || outSize == NULL) { ALOGE("idmap: unexpected NULL parameter"); return UNKNOWN_ERROR; } if (mPackageGroups[0]->packages.size() == 0) { ALOGW("idmap: target package has no packages in its first package group, " "cannot create idmap\n"); if (strlen(targetPath) > 255) { ALOGE("idmap: target path exceeds idmap file format limit of 255 chars"); return UNKNOWN_ERROR; } if (strlen(overlayPath) > 255) { ALOGE("idmap: overlay path exceeds idmap file format limit of 255 chars"); return UNKNOWN_ERROR; } if (mPackageGroups.size() == 0 || mPackageGroups[0]->packages.size() == 0) { ALOGE("idmap: invalid overlay package"); return UNKNOWN_ERROR; } if (targetResTable.mPackageGroups.size() == 0 || targetResTable.mPackageGroups[0]->packages.size() == 0) { ALOGE("idmap: invalid target package"); return UNKNOWN_ERROR; } // The number of resources overlaid that were not explicitly marked overlayable. size_t forcedOverlayCount = 0u; KeyedVector<uint8_t, IdmapTypeMap> map; // overlaid packages are assumed to contain only one package group const PackageGroup* pg = mPackageGroups[0]; // starting size is header *outSize = ResTable::IDMAP_HEADER_SIZE_BYTES; const ResTable_package* targetPackageStruct = targetResTable.mPackageGroups[0]->packages[0]->package; const size_t tmpNameSize = arraysize(targetPackageStruct->name); char16_t tmpName[tmpNameSize]; strcpy16_dtoh(tmpName, targetPackageStruct->name, tmpNameSize); const String16 targetPackageName(tmpName); // target package id and number of types in map *outSize += 2 * sizeof(uint16_t); const PackageGroup* packageGroup = mPackageGroups[0]; // overlay packages are assumed to contain only one package group const ResTable_package* overlayPackageStruct = overlay.mPackageGroups[0]->packages[0]->package; char16_t tmpName[sizeof(overlayPackageStruct->name)/sizeof(overlayPackageStruct->name[0])]; strcpy16_dtoh(tmpName, overlayPackageStruct->name, sizeof(overlayPackageStruct->name)/sizeof(overlayPackageStruct->name[0])); const String16 overlayPackage(tmpName); // the number of resources overlaid that were not explicitly marked overlayable size_t forcedOverlayCount = 0u; for (size_t typeIndex = 0; typeIndex < pg->types.size(); ++typeIndex) { const TypeList& typeList = pg->types[typeIndex]; // find the resources that exist in both packages IdmapMatchingResources matchingResources; for (size_t typeIndex = 0; typeIndex < packageGroup->types.size(); ++typeIndex) { const TypeList& typeList = packageGroup->types[typeIndex]; if (typeList.isEmpty()) { continue; } const Type* typeConfigs = typeList[0]; IdmapTypeMap typeMap; typeMap.overlayTypeId = -1; typeMap.entryOffset = 0; for (size_t entryIndex = 0; entryIndex < typeConfigs->entryCount; ++entryIndex) { uint32_t resID = Res_MAKEID(pg->id - 1, typeIndex, entryIndex); resource_name resName; if (!this->getResourceName(resID, false, &resName)) { if (typeMap.entryMap.isEmpty()) { typeMap.entryOffset++; } uint32_t overlay_resid = Res_MAKEID(packageGroup->id - 1, typeIndex, entryIndex); resource_name current_res; if (!getResourceName(overlay_resid, false, ¤t_res)) { continue; } uint32_t typeSpecFlags = 0u; const String16 overlayType(resName.type, resName.typeLen); const String16 overlayName(resName.name, resName.nameLen); uint32_t overlayResID = overlay.identifierForName(overlayName.string(), overlayName.size(), overlayType.string(), overlayType.size(), overlayPackage.string(), overlayPackage.size(), const uint32_t target_resid = targetResTable.identifierForName( current_res.name, current_res.nameLen, current_res.type, current_res.typeLen, targetPackageName.string(), targetPackageName.size(), &typeSpecFlags); if (overlayResID == 0) { // No such target resource was found. if (typeMap.entryMap.isEmpty()) { typeMap.entryOffset++; } if (target_resid == 0) { continue; } // Now that we know this is being overlaid, check if it can be, and emit a warning if // it can't. if ((dtohl(typeConfigs->typeSpecFlags[entryIndex]) & ResTable_typeSpec::SPEC_OVERLAYABLE) == 0) { forcedOverlayCount++; ++forcedOverlayCount; } if (typeMap.overlayTypeId == -1) { typeMap.overlayTypeId = Res_GETTYPE(overlayResID) + 1; matchingResources.Add(target_resid, overlay_resid); } if (Res_GETTYPE(overlayResID) + 1 != static_cast<size_t>(typeMap.overlayTypeId)) { ALOGE("idmap: can't mix type ids in entry map. Resource 0x%08x maps to 0x%08x" " but entries should map to resources of type %02zx", resID, overlayResID, typeMap.overlayTypeId); return BAD_TYPE; } if (typeMap.entryOffset + typeMap.entryMap.size() < entryIndex) { // pad with 0xffffffff's (indicating non-existing entries) before adding this entry size_t index = typeMap.entryMap.size(); size_t numItems = entryIndex - (typeMap.entryOffset + index); if (typeMap.entryMap.insertAt(0xffffffff, index, numItems) < 0) { return NO_MEMORY; } } typeMap.entryMap.add(Res_GETENTRY(overlayResID)); if (matchingResources.typeMappings.empty()) { ALOGE("idmap: no matching resources"); return UNKNOWN_ERROR; } if (!typeMap.entryMap.isEmpty()) { if (map.add(static_cast<uint8_t>(typeIndex), typeMap) < 0) { return NO_MEMORY; } *outSize += (4 * sizeof(uint16_t)) + (typeMap.entryMap.size() * sizeof(uint32_t)); } } matchingResources.FixPadding(); if (map.isEmpty()) { ALOGW("idmap: no resources in overlay package present in base package"); return UNKNOWN_ERROR; // write idmap *outSize = ResTable::IDMAP_HEADER_SIZE_BYTES; // magic, version, target and overlay crc *outSize += 2 * sizeof(uint16_t); // target package id, type count const auto typesEnd = matchingResources.typeMappings.cend(); for (auto ti = matchingResources.typeMappings.cbegin(); ti != typesEnd; ++ti) { *outSize += 4 * sizeof(uint16_t); // target type, overlay type, entry count, entry offset *outSize += matchingResources.numberOfEntriesIncludingPadding[ti->first] * sizeof(uint32_t); // entries } if ((*outData = malloc(*outSize)) == NULL) { return NO_MEMORY; } uint32_t* data = (uint32_t*)*outData; *data++ = htodl(IDMAP_MAGIC); *data++ = htodl(ResTable::IDMAP_CURRENT_VERSION); *data++ = htodl(targetCrc); *data++ = htodl(overlayCrc); const char* paths[] = { targetPath, overlayPath }; for (int j = 0; j < 2; ++j) { char* p = (char*)data; const char* path = paths[j]; const size_t I = strlen(path); if (I > 255) { ALOGV("path exceeds expected 255 characters: %s\n", path); return UNKNOWN_ERROR; } // write idmap header uint32_t* data = reinterpret_cast<uint32_t*>(*outData); *data++ = htodl(IDMAP_MAGIC); // write: magic *data++ = htodl(ResTable::IDMAP_CURRENT_VERSION); // write: version *data++ = htodl(targetCrc); // write: target crc *data++ = htodl(overlayCrc); // write: overlay crc char* charData = reinterpret_cast<char*>(data); size_t pathLen = strlen(targetPath); for (size_t i = 0; i < 256; ++i) { *p++ = i < I ? path[i] : '\0'; *charData++ = i < pathLen ? targetPath[i] : '\0'; // write: target path } data += 256 / sizeof(uint32_t); pathLen = strlen(overlayPath); for (size_t i = 0; i < 256; ++i) { *charData++ = i < pathLen ? overlayPath[i] : '\0'; // write: overlay path } const size_t mapSize = map.size(); data += (2 * 256) / sizeof(uint32_t); // write idmap data header uint16_t* typeData = reinterpret_cast<uint16_t*>(data); *typeData++ = htods(pg->id); *typeData++ = htods(mapSize); for (size_t i = 0; i < mapSize; ++i) { uint8_t targetTypeId = map.keyAt(i); const IdmapTypeMap& typeMap = map[i]; *typeData++ = htods(targetTypeId + 1); *typeData++ = htods(typeMap.overlayTypeId); *typeData++ = htods(typeMap.entryMap.size()); *typeData++ = htods(typeMap.entryOffset); const size_t entryCount = typeMap.entryMap.size(); uint32_t* entries = reinterpret_cast<uint32_t*>(typeData); for (size_t j = 0; j < entryCount; j++) { entries[j] = htodl(typeMap.entryMap[j]); *typeData++ = htods(targetPackageStruct->id); // write: target package id *typeData++ = htods(static_cast<uint16_t>(matchingResources.typeMappings.size())); // write: type count // write idmap data for (auto ti = matchingResources.typeMappings.cbegin(); ti != typesEnd; ++ti) { const size_t entryCount = matchingResources.numberOfEntriesIncludingPadding[ti->first]; auto ei = ti->second.cbegin(); *typeData++ = htods(Res_GETTYPE(ei->first) + 1); // write: target type id *typeData++ = htods(Res_GETTYPE(ei->second) + 1); // write: overlay type id *typeData++ = htods(entryCount); // write: entry count *typeData++ = htods(Res_GETENTRY(ei->first)); // write: (target) entry offset uint32_t *entryData = reinterpret_cast<uint32_t*>(typeData); for (; ei != ti->second.cend(); ++ei) { const size_t padding = matchingResources.entryPadding[ei->first]; for (size_t i = 0; i < padding; ++i) { *entryData++ = htodl(0xffffffff); // write: padding } *entryData++ = htodl(Res_GETENTRY(ei->second)); // write: (overlay) entry } typeData += entryCount * 2; } Loading
libs/androidfw/include/androidfw/ResourceTypes.h +1 −1 Original line number Diff line number Diff line Loading @@ -1990,7 +1990,7 @@ public: // Return value: on success: NO_ERROR; caller is responsible for free-ing // outData (using free(3)). On failure, any status_t value other than // NO_ERROR; the caller should not free outData. status_t createIdmap(const ResTable& overlay, status_t createIdmap(const ResTable& targetResTable, uint32_t targetCrc, uint32_t overlayCrc, const char* targetPath, const char* overlayPath, void** outData, size_t* outSize) const; Loading
libs/androidfw/tests/Idmap_test.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -40,7 +40,7 @@ class IdmapTest : public ::testing::Test { ASSERT_EQ(NO_ERROR, overlay_table.add(overlay_data_.data(), overlay_data_.size())); char target_name[256] = "com.android.basic"; ASSERT_EQ(NO_ERROR, target_table_.createIdmap(overlay_table, 0, 0, target_name, target_name, ASSERT_EQ(NO_ERROR, overlay_table.createIdmap(target_table_, 0, 0, target_name, target_name, &data_, &data_size_)); } Loading