1b62286e60c079936a5f1e5b0befd32d2d9bf1b3fMark Salyzyn#include <dirent.h> 24600dd053dbdbd4b95f3b11057a1cc55b99f9c77Narayan Kamath#include <inttypes.h> 30fbb60811076e6fcfd576287b6e6a16ac1a69c44Martin Wallgren#include <sys/file.h> 4b62286e60c079936a5f1e5b0befd32d2d9bf1b3fMark Salyzyn#include <sys/stat.h> 5b62286e60c079936a5f1e5b0befd32d2d9bf1b3fMark Salyzyn 613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross#include "idmap.h" 713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 80881a7445f9106e835486c5a697c01f4f18e619bDan Albert#include <memory> 913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross#include <androidfw/ResourceTypes.h> 1013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross#include <androidfw/StreamingZipInflater.h> 1113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross#include <androidfw/ZipFileRO.h> 1213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross#include <private/android_filesystem_config.h> // for AID_SYSTEM 1313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross#include <utils/SortedVector.h> 1413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross#include <utils/String16.h> 1513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross#include <utils/String8.h> 1613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 1713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross#define NO_OVERLAY_TAG (-1000) 1813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 1913221c9cffdb289851411bdc73a9a5236fcb9291Colin Crossusing namespace android; 2013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 2113221c9cffdb289851411bdc73a9a5236fcb9291Colin Crossnamespace { 2213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross struct Overlay { 2313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross Overlay() {} 2413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross Overlay(const String8& a, const String8& i, int p) : 2513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross apk_path(a), idmap_path(i), priority(p) {} 2613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 2713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross bool operator<(Overlay const& rhs) const 2813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross { 297197d91eb7dfbd0f5b065b56d4f391019e71d03aMårten Kongstad return rhs.priority > priority; 3013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 3113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 3213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross String8 apk_path; 3313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross String8 idmap_path; 3413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross int priority; 3513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross }; 3613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 3713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross bool writePackagesList(const char *filename, const SortedVector<Overlay>& overlayVector) 3813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross { 390fbb60811076e6fcfd576287b6e6a16ac1a69c44Martin Wallgren // the file is opened for appending so that it doesn't get truncated 400fbb60811076e6fcfd576287b6e6a16ac1a69c44Martin Wallgren // before we can guarantee mutual exclusion via the flock 410fbb60811076e6fcfd576287b6e6a16ac1a69c44Martin Wallgren FILE* fout = fopen(filename, "a"); 4213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (fout == NULL) { 4313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return false; 4413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 4513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 460fbb60811076e6fcfd576287b6e6a16ac1a69c44Martin Wallgren if (TEMP_FAILURE_RETRY(flock(fileno(fout), LOCK_EX)) != 0) { 470fbb60811076e6fcfd576287b6e6a16ac1a69c44Martin Wallgren fclose(fout); 480fbb60811076e6fcfd576287b6e6a16ac1a69c44Martin Wallgren return false; 490fbb60811076e6fcfd576287b6e6a16ac1a69c44Martin Wallgren } 500fbb60811076e6fcfd576287b6e6a16ac1a69c44Martin Wallgren 510fbb60811076e6fcfd576287b6e6a16ac1a69c44Martin Wallgren if (TEMP_FAILURE_RETRY(ftruncate(fileno(fout), 0)) != 0) { 520fbb60811076e6fcfd576287b6e6a16ac1a69c44Martin Wallgren TEMP_FAILURE_RETRY(flock(fileno(fout), LOCK_UN)); 530fbb60811076e6fcfd576287b6e6a16ac1a69c44Martin Wallgren fclose(fout); 540fbb60811076e6fcfd576287b6e6a16ac1a69c44Martin Wallgren return false; 550fbb60811076e6fcfd576287b6e6a16ac1a69c44Martin Wallgren } 560fbb60811076e6fcfd576287b6e6a16ac1a69c44Martin Wallgren 5713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross for (size_t i = 0; i < overlayVector.size(); ++i) { 5813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross const Overlay& overlay = overlayVector[i]; 5913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross fprintf(fout, "%s %s\n", overlay.apk_path.string(), overlay.idmap_path.string()); 6013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 6113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 620fbb60811076e6fcfd576287b6e6a16ac1a69c44Martin Wallgren TEMP_FAILURE_RETRY(fflush(fout)); 630fbb60811076e6fcfd576287b6e6a16ac1a69c44Martin Wallgren TEMP_FAILURE_RETRY(flock(fileno(fout), LOCK_UN)); 6413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross fclose(fout); 6513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 6613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross // Make file world readable since Zygote (running as root) will read 6713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross // it when creating the initial AssetManger object 6813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross const mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; // 0644 6913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (chmod(filename, mode) == -1) { 7013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross unlink(filename); 7113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return false; 7213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 7313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 7413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return true; 7513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 7613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 7713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross String8 flatten_path(const char *path) 7813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross { 7913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross String16 tmp(path); 8013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross tmp.replaceAll('/', '@'); 8113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return String8(tmp); 8213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 8313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 8413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross int parse_overlay_tag(const ResXMLTree& parser, const char *target_package_name) 8513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross { 8613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross const size_t N = parser.getAttributeCount(); 8713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross String16 target; 8813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross int priority = -1; 8913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross for (size_t i = 0; i < N; ++i) { 9013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross size_t len; 9113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross String16 key(parser.getAttributeName(i, &len)); 9213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (key == String16("targetPackage")) { 936698749dd4d4d6513b26aa9071af290b956b68a7Dan Albert const char16_t *p = parser.getAttributeStringValue(i, &len); 94cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe if (p != NULL) { 9513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross target = String16(p, len); 9613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 9713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } else if (key == String16("priority")) { 9813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross Res_value v; 9913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (parser.getAttributeValue(i, &v) == sizeof(Res_value)) { 10013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross priority = v.data; 10113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (priority < 0 || priority > 9999) { 10213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return -1; 10313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 10413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 10513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 10613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 10713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (target == String16(target_package_name)) { 10813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return priority; 10913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 11013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return NO_OVERLAY_TAG; 11113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 11213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 11313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross int parse_manifest(const void *data, size_t size, const char *target_package_name) 11413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross { 115de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski ResXMLTree parser; 116de898ff42912bd7ca1bfb099cd439562496765a4Adam Lesinski parser.setTo(data, size); 11713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (parser.getError() != NO_ERROR) { 11813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross ALOGD("%s failed to init xml parser, error=0x%08x\n", __FUNCTION__, parser.getError()); 11913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return -1; 12013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 12113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 12213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross ResXMLParser::event_code_t type; 12313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross do { 12413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross type = parser.next(); 12513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (type == ResXMLParser::START_TAG) { 12613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross size_t len; 12713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross String16 tag(parser.getElementName(&len)); 12813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (tag == String16("overlay")) { 12913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return parse_overlay_tag(parser, target_package_name); 13013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 13113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 13213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } while (type != ResXMLParser::BAD_DOCUMENT && type != ResXMLParser::END_DOCUMENT); 13313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 13413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return NO_OVERLAY_TAG; 13513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 13613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 13713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross int parse_apk(const char *path, const char *target_package_name) 13813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross { 1390881a7445f9106e835486c5a697c01f4f18e619bDan Albert std::unique_ptr<ZipFileRO> zip(ZipFileRO::open(path)); 14013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (zip.get() == NULL) { 14113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross ALOGW("%s: failed to open zip %s\n", __FUNCTION__, path); 14213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return -1; 14313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 14413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross ZipEntryRO entry; 14513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if ((entry = zip->findEntryByName("AndroidManifest.xml")) == NULL) { 14613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross ALOGW("%s: failed to find entry AndroidManifest.xml\n", __FUNCTION__); 14713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return -1; 14813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 1494600dd053dbdbd4b95f3b11057a1cc55b99f9c77Narayan Kamath uint32_t uncompLen = 0; 1504600dd053dbdbd4b95f3b11057a1cc55b99f9c77Narayan Kamath uint16_t method; 15113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (!zip->getEntryInfo(entry, &method, &uncompLen, NULL, NULL, NULL, NULL)) { 15213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross ALOGW("%s: failed to read entry info\n", __FUNCTION__); 15313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return -1; 15413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 15513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (method != ZipFileRO::kCompressDeflated) { 1564600dd053dbdbd4b95f3b11057a1cc55b99f9c77Narayan Kamath ALOGW("%s: cannot handle zip compression method %" PRIu16 "\n", __FUNCTION__, method); 15713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return -1; 15813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 15913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross FileMap *dataMap = zip->createEntryFileMap(entry); 160cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe if (dataMap == NULL) { 16113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross ALOGW("%s: failed to create FileMap\n", __FUNCTION__); 16213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return -1; 16313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 16413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross char *buf = new char[uncompLen]; 16513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (NULL == buf) { 1664600dd053dbdbd4b95f3b11057a1cc55b99f9c77Narayan Kamath ALOGW("%s: failed to allocate %" PRIu32 " byte\n", __FUNCTION__, uncompLen); 167688ff4cf0f93d1a886437884f23874e5595d59a3Narayan Kamath delete dataMap; 16813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return -1; 16913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 17013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross StreamingZipInflater inflater(dataMap, uncompLen); 17113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (inflater.read(buf, uncompLen) < 0) { 1724600dd053dbdbd4b95f3b11057a1cc55b99f9c77Narayan Kamath ALOGW("%s: failed to inflate %" PRIu32 " byte\n", __FUNCTION__, uncompLen); 17313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross delete[] buf; 174688ff4cf0f93d1a886437884f23874e5595d59a3Narayan Kamath delete dataMap; 17513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return -1; 17613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 17713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 1784600dd053dbdbd4b95f3b11057a1cc55b99f9c77Narayan Kamath int priority = parse_manifest(buf, static_cast<size_t>(uncompLen), target_package_name); 17913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross delete[] buf; 180688ff4cf0f93d1a886437884f23874e5595d59a3Narayan Kamath delete dataMap; 18113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return priority; 18213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 18313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross} 18413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 18583ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstadint idmap_scan(const char *target_package_name, const char *target_apk_path, 18683ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad const char *idmap_dir, const android::Vector<const char *> *overlay_dirs) 18713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross{ 18813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross String8 filename = String8(idmap_dir); 18913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross filename.appendPath("overlays.list"); 19013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 19113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross SortedVector<Overlay> overlayVector; 19283ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad const size_t N = overlay_dirs->size(); 19383ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad for (size_t i = 0; i < N; ++i) { 19483ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad const char *overlay_dir = overlay_dirs->itemAt(i); 19583ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad DIR *dir = opendir(overlay_dir); 19683ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad if (dir == NULL) { 19783ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad return EXIT_FAILURE; 19883ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad } 19983ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad 20083ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad struct dirent *dirent; 20183ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad while ((dirent = readdir(dir)) != NULL) { 20283ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad struct stat st; 20383ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad char overlay_apk_path[PATH_MAX + 1]; 20483ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad snprintf(overlay_apk_path, PATH_MAX, "%s/%s", overlay_dir, dirent->d_name); 20583ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad if (stat(overlay_apk_path, &st) < 0) { 20683ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad continue; 20783ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad } 20883ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad if (!S_ISREG(st.st_mode)) { 20983ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad continue; 21083ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad } 21113221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 21283ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad int priority = parse_apk(overlay_apk_path, target_package_name); 21383ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad if (priority < 0) { 21483ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad continue; 21583ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad } 21613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 21783ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad String8 idmap_path(idmap_dir); 21883ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad idmap_path.appendPath(flatten_path(overlay_apk_path + 1)); 21983ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad idmap_path.append("@idmap"); 22013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 22183ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad if (idmap_create_path(target_apk_path, overlay_apk_path, idmap_path.string()) != 0) { 22283ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad ALOGE("error: failed to create idmap for target=%s overlay=%s idmap=%s\n", 22383ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad target_apk_path, overlay_apk_path, idmap_path.string()); 22483ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad continue; 22583ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad } 22683ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad 22783ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad Overlay overlay(String8(overlay_apk_path), idmap_path, priority); 22883ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad overlayVector.add(overlay); 22913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 23013221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 23183ab0d7c1824f3a29e41af8a95a954c73f48c287Mårten Kongstad closedir(dir); 23213221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 23313221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 23413221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross if (!writePackagesList(filename.string(), overlayVector)) { 23513221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return EXIT_FAILURE; 23613221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross } 23713221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross 23813221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross return EXIT_SUCCESS; 23913221c9cffdb289851411bdc73a9a5236fcb9291Colin Cross} 240