19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// Copyright 2006 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// Build resource files from raw assets.
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "Main.h"
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "AaptAssets.h"
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "StringPool.h"
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "XMLNode.h"
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "ResourceTable.h"
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "Images.h"
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
138a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin#include "CrunchCache.h"
148a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin#include "FileFinder.h"
158a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin#include "CacheUpdater.h"
168a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin
17c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown#include <utils/WorkQueue.h>
18c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown
19f51125d8429ffa71c57ba6fbdca9effc72642a9bRaphael#if HAVE_PRINTF_ZD
20f51125d8429ffa71c57ba6fbdca9effc72642a9bRaphael#  define ZD "%zd"
21f51125d8429ffa71c57ba6fbdca9effc72642a9bRaphael#  define ZD_TYPE ssize_t
22f51125d8429ffa71c57ba6fbdca9effc72642a9bRaphael#else
23f51125d8429ffa71c57ba6fbdca9effc72642a9bRaphael#  define ZD "%ld"
24f51125d8429ffa71c57ba6fbdca9effc72642a9bRaphael#  define ZD_TYPE long
25f51125d8429ffa71c57ba6fbdca9effc72642a9bRaphael#endif
26f51125d8429ffa71c57ba6fbdca9effc72642a9bRaphael
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define NOISY(x) // x
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
29c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown// Number of threads to use for preprocessing images.
30c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brownstatic const size_t MAX_THREADS = 4;
31c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ==========================================================================
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ==========================================================================
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ==========================================================================
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass PackageInfo
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic:
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    PackageInfo()
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ~PackageInfo()
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t parsePackage(const sp<AaptGroup>& grp);
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ==========================================================================
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ==========================================================================
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ==========================================================================
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic String8 parseResourceName(const String8& leaf)
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* firstDot = strchr(leaf.string(), '.');
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const char* str = leaf.string();
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (firstDot) {
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return String8(str, firstDot-str);
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return String8(str);
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectResourceTypeSet::ResourceTypeSet()
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    :RefBase(),
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     KeyedVector<String8,sp<AaptGroup> >()
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
719bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah GaskinFilePathStore::FilePathStore()
729bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin    :RefBase(),
739bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin     Vector<String8>()
749bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin{
759bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin}
769bf34ca6f85309c65b0ebdf614cb8266401b49baJosiah Gaskin
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectclass ResourceDirIterator
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic:
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ResourceDirIterator(const sp<ResourceTypeSet>& set, const String8& resType)
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        : mResType(resType), mSet(set), mSetPos(0), mGroupPos(0)
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    inline const sp<AaptGroup>& getGroup() const { return mGroup; }
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    inline const sp<AaptFile>& getFile() const { return mFile; }
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    inline const String8& getBaseName() const { return mBaseName; }
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    inline const String8& getLeafName() const { return mLeafName; }
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    inline String8 getPath() const { return mPath; }
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    inline const ResTable_config& getParams() const { return mParams; }
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    enum {
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        EOD = 1
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ssize_t next()
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (true) {
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sp<AaptGroup> group;
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sp<AaptFile> file;
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Try to get next file in this current group.
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mGroup != NULL && mGroupPos < mGroup->getFiles().size()) {
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                group = mGroup;
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                file = group->getFiles().valueAt(mGroupPos++);
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Try to get the next group/file in this directory
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (mSetPos < mSet->size()) {
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mGroup = group = mSet->valueAt(mSetPos++);
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (group->getFiles().size() < 1) {
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    continue;
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                file = group->getFiles().valueAt(0);
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mGroupPos = 1;
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // All done!
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return EOD;
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFile = file;
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String8 leaf(group->getLeaf());
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLeafName = String8(leaf);
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mParams = file->getGroupEntry().toParams();
12727b28b3f62bd3b54fa13acd5d035940b9be464f3Tobias Haamel            NOISY(printf("Dir %s: mcc=%d mnc=%d lang=%c%c cnt=%c%c orient=%d ui=%d density=%d touch=%d key=%d inp=%d nav=%d\n",
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                   group->getPath().string(), mParams.mcc, mParams.mnc,
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                   mParams.language[0] ? mParams.language[0] : '-',
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                   mParams.language[1] ? mParams.language[1] : '-',
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                   mParams.country[0] ? mParams.country[0] : '-',
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                   mParams.country[1] ? mParams.country[1] : '-',
13327b28b3f62bd3b54fa13acd5d035940b9be464f3Tobias Haamel                   mParams.orientation, mParams.uiMode,
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                   mParams.density, mParams.touchscreen, mParams.keyboard,
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                   mParams.inputFlags, mParams.navigation));
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPath = "res";
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPath.appendPath(file->getGroupEntry().toDirName(mResType));
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPath.appendPath(leaf);
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mBaseName = parseResourceName(leaf);
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mBaseName == "") {
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                fprintf(stderr, "Error: malformed resource filename %s\n",
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        file->getPrintableSource().string());
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return UNKNOWN_ERROR;
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            NOISY(printf("file name=%s\n", mBaseName.string()));
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return NO_ERROR;
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectprivate:
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 mResType;
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const sp<ResourceTypeSet> mSet;
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t mSetPos;
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp<AaptGroup> mGroup;
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t mGroupPos;
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp<AaptFile> mFile;
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 mBaseName;
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 mLeafName;
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 mPath;
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ResTable_config mParams;
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ==========================================================================
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ==========================================================================
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ==========================================================================
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbool isValidResourceType(const String8& type)
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
174f31161a0e71c0446283610e9bf7a11e0be12bd5eDianne Hackborn    return type == "anim" || type == "animator" || type == "interpolator"
175f31161a0e71c0446283610e9bf7a11e0be12bd5eDianne Hackborn        || type == "drawable" || type == "layout"
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        || type == "values" || type == "xml" || type == "raw"
1777c71023b7f5aafac09bd2f0425fccb5fe2d22b27Kenny Root        || type == "color" || type == "menu" || type == "mipmap";
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic sp<AaptFile> getResourceFile(const sp<AaptAssets>& assets, bool makeIfNecessary=true)
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp<AaptGroup> group = assets->getFiles().valueFor(String8("resources.arsc"));
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp<AaptFile> file;
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (group != NULL) {
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        file = group->getFiles().valueFor(AaptGroupEntry());
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (file != NULL) {
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return file;
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!makeIfNecessary) {
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return assets->addFile(String8("resources.arsc"), AaptGroupEntry(), String8(),
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            NULL, String8());
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
198b5ef7ee1644b099498ddd29c1d051e7ee26ccfd3Kenny Rootstatic status_t parsePackage(Bundle* bundle, const sp<AaptAssets>& assets,
199b5ef7ee1644b099498ddd29c1d051e7ee26ccfd3Kenny Root    const sp<AaptGroup>& grp)
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (grp->getFiles().size() != 1) {
202dd931864209eac0b4182d7a0d1ca965fcc3b8c03Marco Nelissen        fprintf(stderr, "warning: Multiple AndroidManifest.xml files found, using %s\n",
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                grp->getFiles().valueAt(0)->getPrintableSource().string());
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp<AaptFile> file = grp->getFiles().valueAt(0);
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ResXMLTree block;
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t err = parseXMLResource(file, &block);
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (err != NO_ERROR) {
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return err;
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //printXMLBlock(&block);
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ResXMLTree::event_code_t code;
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while ((code=block.next()) != ResXMLTree::START_TAG
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project           && code != ResXMLTree::END_DOCUMENT
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project           && code != ResXMLTree::BAD_DOCUMENT) {
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t len;
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (code != ResXMLTree::START_TAG) {
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "%s:%d: No start tag found\n",
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                file->getPrintableSource().string(), block.getLineNumber());
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return UNKNOWN_ERROR;
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (strcmp16(block.getElementName(&len), String16("manifest").string()) != 0) {
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "%s:%d: Invalid start tag %s, expected <manifest>\n",
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                file->getPrintableSource().string(), block.getLineNumber(),
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                String8(block.getElementName(&len)).string());
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return UNKNOWN_ERROR;
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ssize_t nameIndex = block.indexOfAttribute(NULL, "package");
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (nameIndex < 0) {
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "%s:%d: <manifest> does not have package attribute.\n",
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                file->getPrintableSource().string(), block.getLineNumber());
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return UNKNOWN_ERROR;
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    assets->setPackage(String8(block.getAttributeStringValue(nameIndex, &len)));
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
243b5ef7ee1644b099498ddd29c1d051e7ee26ccfd3Kenny Root    String16 uses_sdk16("uses-sdk");
244b5ef7ee1644b099498ddd29c1d051e7ee26ccfd3Kenny Root    while ((code=block.next()) != ResXMLTree::END_DOCUMENT
245b5ef7ee1644b099498ddd29c1d051e7ee26ccfd3Kenny Root           && code != ResXMLTree::BAD_DOCUMENT) {
246b5ef7ee1644b099498ddd29c1d051e7ee26ccfd3Kenny Root        if (code == ResXMLTree::START_TAG) {
247b5ef7ee1644b099498ddd29c1d051e7ee26ccfd3Kenny Root            if (strcmp16(block.getElementName(&len), uses_sdk16.string()) == 0) {
2485a8ec761213d723fc3a6a92250e5e855605046a6Kenny Root                ssize_t minSdkIndex = block.indexOfAttribute(RESOURCES_ANDROID_NAMESPACE,
249b5ef7ee1644b099498ddd29c1d051e7ee26ccfd3Kenny Root                                                             "minSdkVersion");
250b5ef7ee1644b099498ddd29c1d051e7ee26ccfd3Kenny Root                if (minSdkIndex >= 0) {
2517ff20e30c50cf1d47a7eaacd71665a1d2f4ecdc4Kenny Root                    const uint16_t* minSdk16 = block.getAttributeStringValue(minSdkIndex, &len);
2527ff20e30c50cf1d47a7eaacd71665a1d2f4ecdc4Kenny Root                    const char* minSdk8 = strdup(String8(minSdk16).string());
2531741cd4904414b5b4e768953a8f1abb3f0ef0a0aKenny Root                    bundle->setManifestMinSdkVersion(minSdk8);
254b5ef7ee1644b099498ddd29c1d051e7ee26ccfd3Kenny Root                }
255b5ef7ee1644b099498ddd29c1d051e7ee26ccfd3Kenny Root            }
256b5ef7ee1644b099498ddd29c1d051e7ee26ccfd3Kenny Root        }
257b5ef7ee1644b099498ddd29c1d051e7ee26ccfd3Kenny Root    }
258b5ef7ee1644b099498ddd29c1d051e7ee26ccfd3Kenny Root
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NO_ERROR;
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ==========================================================================
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ==========================================================================
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ==========================================================================
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic status_t makeFileResources(Bundle* bundle, const sp<AaptAssets>& assets,
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                  ResourceTable* table,
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                  const sp<ResourceTypeSet>& set,
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                  const char* resType)
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 type8(resType);
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String16 type16(resType);
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bool hasErrors = false;
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ResourceDirIterator it(set, String8(resType));
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ssize_t res;
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while ((res=it.next()) == NO_ERROR) {
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (bundle->getVerbose()) {
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            printf("    (new resource id %s from %s)\n",
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                   it.getBaseName().string(), it.getFile()->getPrintableSource().string());
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String16 baseName(it.getBaseName());
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const char16_t* str = baseName.string();
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const char16_t* const end = str + baseName.size();
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (str < end) {
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!((*str >= 'a' && *str <= 'z')
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    || (*str >= '0' && *str <= '9')
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    || *str == '_' || *str == '.')) {
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                fprintf(stderr, "%s: Invalid file name: must contain only [a-z0-9_.]\n",
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        it.getPath().string());
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                hasErrors = true;
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            str++;
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String8 resPath = it.getPath();
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        resPath.convertToResPath();
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        table->addEntry(SourcePos(it.getPath(), 0), String16(assets->getPackage()),
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        type16,
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        baseName,
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        String16(resPath),
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        NULL,
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        &it.getParams());
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        assets->addResource(it.getLeafName(), resPath, it.getFile(), type8);
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return hasErrors ? UNKNOWN_ERROR : NO_ERROR;
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
310c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brownclass PreProcessImageWorkUnit : public WorkQueue::WorkUnit {
311c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brownpublic:
312c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown    PreProcessImageWorkUnit(const Bundle* bundle, const sp<AaptAssets>& assets,
313c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown            const sp<AaptFile>& file, volatile bool* hasErrors) :
314c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown            mBundle(bundle), mAssets(assets), mFile(file), mHasErrors(hasErrors) {
315c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown    }
316c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown
317c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown    virtual bool run() {
318c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown        status_t status = preProcessImage(mBundle, mAssets, mFile, NULL);
319c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown        if (status) {
320c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown            *mHasErrors = true;
321c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown        }
322c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown        return true; // continue even if there are errors
323c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown    }
324c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown
325c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brownprivate:
326c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown    const Bundle* mBundle;
327c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown    sp<AaptAssets> mAssets;
328c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown    sp<AaptFile> mFile;
329c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown    volatile bool* mHasErrors;
330c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown};
331c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown
332c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brownstatic status_t preProcessImages(const Bundle* bundle, const sp<AaptAssets>& assets,
3337c71023b7f5aafac09bd2f0425fccb5fe2d22b27Kenny Root                          const sp<ResourceTypeSet>& set, const char* type)
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
335c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown    volatile bool hasErrors = false;
3368a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    ssize_t res = NO_ERROR;
3378a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin    if (bundle->getUseCrunchCache() == false) {
338c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown        WorkQueue wq(MAX_THREADS, false);
33984be06e4ce0778fbf0c1ac72f94795ef8433439bXavier Ducrohet        ResourceDirIterator it(set, String8(type));
3408a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin        while ((res=it.next()) == NO_ERROR) {
341c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown            PreProcessImageWorkUnit* w = new PreProcessImageWorkUnit(
342c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown                    bundle, assets, it.getFile(), &hasErrors);
343c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown            status_t status = wq.schedule(w);
344c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown            if (status) {
345c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown                fprintf(stderr, "preProcessImages failed: schedule() returned %d\n", status);
3468a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin                hasErrors = true;
347c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown                delete w;
348c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown                break;
3498a39da80b33691b0c82458c3b7727e13ff71277eJosiah Gaskin            }
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
351c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown        status_t status = wq.finish();
352c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown        if (status) {
353c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown            fprintf(stderr, "preProcessImages failed: finish() returned %d\n", status);
354c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown            hasErrors = true;
355c0f7366a15655c6973ea21029f1997f24c006ccaJeff Brown        }
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3573547f859d4a4e90eea52e9caf686c69a6e015b85Daniel Sandler    return (hasErrors || (res < NO_ERROR)) ? UNKNOWN_ERROR : NO_ERROR;
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t postProcessImages(const sp<AaptAssets>& assets,
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                           ResourceTable* table,
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                           const sp<ResourceTypeSet>& set)
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ResourceDirIterator it(set, String8("drawable"));
3653547f859d4a4e90eea52e9caf686c69a6e015b85Daniel Sandler    bool hasErrors = false;
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ssize_t res;
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while ((res=it.next()) == NO_ERROR) {
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        res = postProcessImage(assets, table, it.getFile());
3693547f859d4a4e90eea52e9caf686c69a6e015b85Daniel Sandler        if (res < NO_ERROR) {
3703547f859d4a4e90eea52e9caf686c69a6e015b85Daniel Sandler            hasErrors = true;
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3743547f859d4a4e90eea52e9caf686c69a6e015b85Daniel Sandler    return (hasErrors || (res < NO_ERROR)) ? UNKNOWN_ERROR : NO_ERROR;
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void collect_files(const sp<AaptDir>& dir,
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        KeyedVector<String8, sp<ResourceTypeSet> >* resources)
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const DefaultKeyedVector<String8, sp<AaptGroup> >& groups = dir->getFiles();
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int N = groups.size();
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (int i=0; i<N; i++) {
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String8 leafName = groups.keyAt(i);
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const sp<AaptGroup>& group = groups.valueAt(i);
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> >& files
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                = group->getFiles();
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (files.size() == 0) {
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            continue;
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String8 resType = files.valueAt(0)->getResourceType();
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ssize_t index = resources->indexOfKey(resType);
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (index < 0) {
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sp<ResourceTypeSet> set = new ResourceTypeSet();
399e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn            NOISY(printf("Creating new resource type set for leaf %s with group %s (%p)\n",
400e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn                    leafName.string(), group->getPath().string(), group.get()));
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            set->add(leafName, group);
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            resources->add(resType, set);
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sp<ResourceTypeSet> set = resources->valueAt(index);
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            index = set->indexOfKey(leafName);
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (index < 0) {
407e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn                NOISY(printf("Adding to resource type set for leaf %s group %s (%p)\n",
408e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn                        leafName.string(), group->getPath().string(), group.get()));
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                set->add(leafName, group);
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sp<AaptGroup> existingGroup = set->valueAt(index);
412e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn                NOISY(printf("Extending to resource type set for leaf %s group %s (%p)\n",
413e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn                        leafName.string(), group->getPath().string(), group.get()));
414e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn                for (size_t j=0; j<files.size(); j++) {
415e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn                    NOISY(printf("Adding file %s in group %s resType %s\n",
416e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn                        files.valueAt(j)->getSourceFile().string(),
417e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn                        files.keyAt(j).toDirName(String8()).string(),
418e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn                        resType.string()));
419e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn                    status_t err = existingGroup->addFile(files.valueAt(j));
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void collect_files(const sp<AaptAssets>& ass,
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        KeyedVector<String8, sp<ResourceTypeSet> >* resources)
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const Vector<sp<AaptDir> >& dirs = ass->resDirs();
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int N = dirs.size();
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    for (int i=0; i<N; i++) {
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sp<AaptDir> d = dirs.itemAt(i);
434e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn        NOISY(printf("Collecting dir #%d %p: %s, leaf %s\n", i, d.get(), d->getPath().string(),
435e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn                d->getLeaf().string()));
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        collect_files(d, resources);
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // don't try to include the res dir
439e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn        NOISY(printf("Removing dir leaf %s\n", d->getLeaf().string()));
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ass->removeDir(d->getLeaf());
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectenum {
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ATTR_OKAY = -1,
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ATTR_NOT_FOUND = -2,
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ATTR_LEADING_SPACES = -3,
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ATTR_TRAILING_SPACES = -4
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
450cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackbornstatic int validateAttr(const String8& path, const ResTable& table,
451cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn        const ResXMLParser& parser,
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const char* ns, const char* attr, const char* validChars, bool required)
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t len;
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ssize_t index = parser.indexOfAttribute(ns, attr);
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const uint16_t* str;
458cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn    Res_value value;
459cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn    if (index >= 0 && parser.getAttributeValue(index, &value) >= 0) {
460cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn        const ResStringPool* pool = &parser.getStrings();
461cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn        if (value.dataType == Res_value::TYPE_REFERENCE) {
462cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn            uint32_t specFlags = 0;
463cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn            int strIdx;
464cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn            if ((strIdx=table.resolveReference(&value, 0x10000000, NULL, &specFlags)) < 0) {
465cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn                fprintf(stderr, "%s:%d: Tag <%s> attribute %s references unknown resid 0x%08x.\n",
466cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn                        path.string(), parser.getLineNumber(),
467cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn                        String8(parser.getElementName(&len)).string(), attr,
468cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn                        value.data);
469cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn                return ATTR_NOT_FOUND;
470cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn            }
471cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn
472cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn            pool = table.getTableStringBlock(strIdx);
473cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn            #if 0
474cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn            if (pool != NULL) {
475cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn                str = pool->stringAt(value.data, &len);
476cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn            }
477cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn            printf("***** RES ATTR: %s specFlags=0x%x strIdx=%d: %s\n", attr,
478cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn                    specFlags, strIdx, str != NULL ? String8(str).string() : "???");
479cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn            #endif
480cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn            if ((specFlags&~ResTable_typeSpec::SPEC_PUBLIC) != 0 && false) {
481cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn                fprintf(stderr, "%s:%d: Tag <%s> attribute %s varies by configurations 0x%x.\n",
482cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn                        path.string(), parser.getLineNumber(),
483cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn                        String8(parser.getElementName(&len)).string(), attr,
484cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn                        specFlags);
485cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn                return ATTR_NOT_FOUND;
486cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn            }
487cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn        }
488cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn        if (value.dataType == Res_value::TYPE_STRING) {
489cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn            if (pool == NULL) {
490cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn                fprintf(stderr, "%s:%d: Tag <%s> attribute %s has no string block.\n",
491cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn                        path.string(), parser.getLineNumber(),
492cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn                        String8(parser.getElementName(&len)).string(), attr);
493cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn                return ATTR_NOT_FOUND;
494cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn            }
495cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn            if ((str=pool->stringAt(value.data, &len)) == NULL) {
496cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn                fprintf(stderr, "%s:%d: Tag <%s> attribute %s has corrupt string value.\n",
497cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn                        path.string(), parser.getLineNumber(),
498cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn                        String8(parser.getElementName(&len)).string(), attr);
499cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn                return ATTR_NOT_FOUND;
500cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn            }
501cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn        } else {
502cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn            fprintf(stderr, "%s:%d: Tag <%s> attribute %s has invalid type %d.\n",
503cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn                    path.string(), parser.getLineNumber(),
504cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn                    String8(parser.getElementName(&len)).string(), attr,
505cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn                    value.dataType);
506cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn            return ATTR_NOT_FOUND;
507cf244ada58539ce857ec041d7288d0271204fbb6Dianne Hackborn        }
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (validChars) {
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (size_t i=0; i<len; i++) {
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                uint16_t c = str[i];
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                const char* p = validChars;
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                bool okay = false;
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                while (*p) {
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (c == *p) {
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        okay = true;
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    p++;
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!okay) {
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    fprintf(stderr, "%s:%d: Tag <%s> attribute %s has invalid character '%c'.\n",
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            path.string(), parser.getLineNumber(),
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            String8(parser.getElementName(&len)).string(), attr, (char)str[i]);
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return (int)i;
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (*str == ' ') {
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "%s:%d: Tag <%s> attribute %s can not start with a space.\n",
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    path.string(), parser.getLineNumber(),
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    String8(parser.getElementName(&len)).string(), attr);
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ATTR_LEADING_SPACES;
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (str[len-1] == ' ') {
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fprintf(stderr, "%s:%d: Tag <%s> attribute %s can not end with a space.\n",
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    path.string(), parser.getLineNumber(),
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    String8(parser.getElementName(&len)).string(), attr);
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ATTR_TRAILING_SPACES;
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return ATTR_OKAY;
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (required) {
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fprintf(stderr, "%s:%d: Tag <%s> missing required attribute %s.\n",
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                path.string(), parser.getLineNumber(),
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                String8(parser.getElementName(&len)).string(), attr);
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return ATTR_NOT_FOUND;
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return ATTR_OKAY;
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void checkForIds(const String8& path, ResXMLParser& parser)
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ResXMLTree::event_code_t code;
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while ((code=parser.next()) != ResXMLTree::END_DOCUMENT
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project           && code > ResXMLTree::BAD_DOCUMENT) {
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (code == ResXMLTree::START_TAG) {
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ssize_t index = parser.indexOfAttribute(NULL, "id");
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (index >= 0) {
559dd931864209eac0b4182d7a0d1ca965fcc3b8c03Marco Nelissen                fprintf(stderr, "%s:%d: warning: found plain 'id' attribute; did you mean the new 'android:id' name?\n",
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        path.string(), parser.getLineNumber());
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
566832528f92c8d6995318777ead009da20963bcf7aRobert Greenwaltstatic bool applyFileOverlay(Bundle *bundle,
567832528f92c8d6995318777ead009da20963bcf7aRobert Greenwalt                             const sp<AaptAssets>& assets,
56883f4c0994fd34f9b35eeb2c14908d9e6c2e15930Xavier Ducrohet                             sp<ResourceTypeSet> *baseSet,
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                             const char *resType)
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
571832528f92c8d6995318777ead009da20963bcf7aRobert Greenwalt    if (bundle->getVerbose()) {
572832528f92c8d6995318777ead009da20963bcf7aRobert Greenwalt        printf("applyFileOverlay for %s\n", resType);
573832528f92c8d6995318777ead009da20963bcf7aRobert Greenwalt    }
574832528f92c8d6995318777ead009da20963bcf7aRobert Greenwalt
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Replace any base level files in this category with any found from the overlay
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Also add any found only in the overlay.
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp<AaptAssets> overlay = assets->getOverlay();
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String8 resTypeString(resType);
579fa5c7e1dfede7e26260789dd2de5175497e9659bRobert Greenwalt
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // work through the linked list of overlays
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while (overlay.get()) {
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        KeyedVector<String8, sp<ResourceTypeSet> >* overlayRes = overlay->getResources();
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // get the overlay resources of the requested type
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ssize_t index = overlayRes->indexOfKey(resTypeString);
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (index >= 0) {
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sp<ResourceTypeSet> overlaySet = overlayRes->valueAt(index);
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // for each of the resources, check for a match in the previously built
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // non-overlay "baseset".
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            size_t overlayCount = overlaySet->size();
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (size_t overlayIndex=0; overlayIndex<overlayCount; overlayIndex++) {
593832528f92c8d6995318777ead009da20963bcf7aRobert Greenwalt                if (bundle->getVerbose()) {
594832528f92c8d6995318777ead009da20963bcf7aRobert Greenwalt                    printf("trying overlaySet Key=%s\n",overlaySet->keyAt(overlayIndex).string());
595832528f92c8d6995318777ead009da20963bcf7aRobert Greenwalt                }
59683f4c0994fd34f9b35eeb2c14908d9e6c2e15930Xavier Ducrohet                size_t baseIndex = UNKNOWN_ERROR;
59783f4c0994fd34f9b35eeb2c14908d9e6c2e15930Xavier Ducrohet                if (baseSet->get() != NULL) {
59883f4c0994fd34f9b35eeb2c14908d9e6c2e15930Xavier Ducrohet                    baseIndex = (*baseSet)->indexOfKey(overlaySet->keyAt(overlayIndex));
59983f4c0994fd34f9b35eeb2c14908d9e6c2e15930Xavier Ducrohet                }
600fa5c7e1dfede7e26260789dd2de5175497e9659bRobert Greenwalt                if (baseIndex < UNKNOWN_ERROR) {
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // look for same flavor.  For a given file (strings.xml, for example)
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // there may be a locale specific or other flavors - we want to match
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // the same flavor.
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    sp<AaptGroup> overlayGroup = overlaySet->valueAt(overlayIndex);
60583f4c0994fd34f9b35eeb2c14908d9e6c2e15930Xavier Ducrohet                    sp<AaptGroup> baseGroup = (*baseSet)->valueAt(baseIndex);
606832528f92c8d6995318777ead009da20963bcf7aRobert Greenwalt
607832528f92c8d6995318777ead009da20963bcf7aRobert Greenwalt                    DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> > overlayFiles =
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            overlayGroup->getFiles();
609832528f92c8d6995318777ead009da20963bcf7aRobert Greenwalt                    if (bundle->getVerbose()) {
610832528f92c8d6995318777ead009da20963bcf7aRobert Greenwalt                        DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> > baseFiles =
611832528f92c8d6995318777ead009da20963bcf7aRobert Greenwalt                                baseGroup->getFiles();
612832528f92c8d6995318777ead009da20963bcf7aRobert Greenwalt                        for (size_t i=0; i < baseFiles.size(); i++) {
613f51125d8429ffa71c57ba6fbdca9effc72642a9bRaphael                            printf("baseFile " ZD " has flavor %s\n", (ZD_TYPE) i,
614832528f92c8d6995318777ead009da20963bcf7aRobert Greenwalt                                    baseFiles.keyAt(i).toString().string());
615832528f92c8d6995318777ead009da20963bcf7aRobert Greenwalt                        }
616832528f92c8d6995318777ead009da20963bcf7aRobert Greenwalt                        for (size_t i=0; i < overlayFiles.size(); i++) {
617f51125d8429ffa71c57ba6fbdca9effc72642a9bRaphael                            printf("overlayFile " ZD " has flavor %s\n", (ZD_TYPE) i,
618832528f92c8d6995318777ead009da20963bcf7aRobert Greenwalt                                    overlayFiles.keyAt(i).toString().string());
619832528f92c8d6995318777ead009da20963bcf7aRobert Greenwalt                        }
620832528f92c8d6995318777ead009da20963bcf7aRobert Greenwalt                    }
621832528f92c8d6995318777ead009da20963bcf7aRobert Greenwalt
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    size_t overlayGroupSize = overlayFiles.size();
623832528f92c8d6995318777ead009da20963bcf7aRobert Greenwalt                    for (size_t overlayGroupIndex = 0;
624832528f92c8d6995318777ead009da20963bcf7aRobert Greenwalt                            overlayGroupIndex<overlayGroupSize;
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            overlayGroupIndex++) {
626832528f92c8d6995318777ead009da20963bcf7aRobert Greenwalt                        size_t baseFileIndex =
627832528f92c8d6995318777ead009da20963bcf7aRobert Greenwalt                                baseGroup->getFiles().indexOfKey(overlayFiles.
628832528f92c8d6995318777ead009da20963bcf7aRobert Greenwalt                                keyAt(overlayGroupIndex));
629e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn                        if (baseFileIndex < UNKNOWN_ERROR) {
630832528f92c8d6995318777ead009da20963bcf7aRobert Greenwalt                            if (bundle->getVerbose()) {
631f51125d8429ffa71c57ba6fbdca9effc72642a9bRaphael                                printf("found a match (" ZD ") for overlay file %s, for flavor %s\n",
632f51125d8429ffa71c57ba6fbdca9effc72642a9bRaphael                                        (ZD_TYPE) baseFileIndex,
633832528f92c8d6995318777ead009da20963bcf7aRobert Greenwalt                                        overlayGroup->getLeaf().string(),
634832528f92c8d6995318777ead009da20963bcf7aRobert Greenwalt                                        overlayFiles.keyAt(overlayGroupIndex).toString().string());
635832528f92c8d6995318777ead009da20963bcf7aRobert Greenwalt                            }
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            baseGroup->removeFile(baseFileIndex);
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } else {
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // didn't find a match fall through and add it..
639e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn                            if (true || bundle->getVerbose()) {
640e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn                                printf("nothing matches overlay file %s, for flavor %s\n",
641e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn                                        overlayGroup->getLeaf().string(),
642e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn                                        overlayFiles.keyAt(overlayGroupIndex).toString().string());
643e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn                            }
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        baseGroup->addFile(overlayFiles.valueAt(overlayGroupIndex));
64664551b2e0e52fe89c360b1951acc528d94ebaf7aDianne Hackborn                        assets->addGroupEntry(overlayFiles.keyAt(overlayGroupIndex));
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
64983f4c0994fd34f9b35eeb2c14908d9e6c2e15930Xavier Ducrohet                    if (baseSet->get() == NULL) {
65083f4c0994fd34f9b35eeb2c14908d9e6c2e15930Xavier Ducrohet                        *baseSet = new ResourceTypeSet();
65183f4c0994fd34f9b35eeb2c14908d9e6c2e15930Xavier Ducrohet                        assets->getResources()->add(String8(resType), *baseSet);
65283f4c0994fd34f9b35eeb2c14908d9e6c2e15930Xavier Ducrohet                    }
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // this group doesn't exist (a file that's only in the overlay)
65483f4c0994fd34f9b35eeb2c14908d9e6c2e15930Xavier Ducrohet                    (*baseSet)->add(overlaySet->keyAt(overlayIndex),
65558c27a0a03f573791935116fa35f6a7c8bf93896Dianne Hackborn                            overlaySet->valueAt(overlayIndex));
65664551b2e0e52fe89c360b1951acc528d94ebaf7aDianne Hackborn                    // make sure all flavors are defined in the resources.
65764551b2e0e52fe89c360b1951acc528d94ebaf7aDianne Hackborn                    sp<AaptGroup> overlayGroup = overlaySet->valueAt(overlayIndex);
658832528f92c8d6995318777ead009da20963bcf7aRobert Greenwalt                    DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> > overlayFiles =
65964551b2e0e52fe89c360b1951acc528d94ebaf7aDianne Hackborn                            overlayGroup->getFiles();
66064551b2e0e52fe89c360b1951acc528d94ebaf7aDianne Hackborn                    size_t overlayGroupSize = overlayFiles.size();
661832528f92c8d6995318777ead009da20963bcf7aRobert Greenwalt                    for (size_t overlayGroupIndex = 0;
662832528f92c8d6995318777ead009da20963bcf7aRobert Greenwalt                            overlayGroupIndex<overlayGroupSize;
66364551b2e0e52fe89c360b1951acc528d94ebaf7aDianne Hackborn                            overlayGroupIndex++) {
66464551b2e0e52fe89c360b1951acc528d94ebaf7aDianne Hackborn                        assets->addGroupEntry(overlayFiles.keyAt(overlayGroupIndex));
66564551b2e0e52fe89c360b1951acc528d94ebaf7aDianne Hackborn                    }
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // this overlay didn't have resources for this type
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // try next overlay
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        overlay = overlay->getOverlay();
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
673fa5c7e1dfede7e26260789dd2de5175497e9659bRobert Greenwalt    return true;
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6767714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet/*
6777714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet * Inserts an attribute in a given node, only if the attribute does not
6787714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet * exist.
6797714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet * If errorOnFailedInsert is true, and the attribute already exists, returns false.
6807714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet * Returns true otherwise, even if the attribute already exists.
6817714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet */
6827714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohetbool addTagAttribute(const sp<XMLNode>& node, const char* ns8,
6837714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet        const char* attr8, const char* value, bool errorOnFailedInsert)
68462da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn{
68562da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn    if (value == NULL) {
6867714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet        return true;
68762da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn    }
6887714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet
68962da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn    const String16 ns(ns8);
69062da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn    const String16 attr(attr8);
6917714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet
69262da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn    if (node->getAttribute(ns, attr) != NULL) {
6937714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet        if (errorOnFailedInsert) {
6947714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet            fprintf(stderr, "Error: AndroidManifest.xml already defines %s (in %s);"
6957714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet                            " cannot insert new value %s.\n",
6967714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet                    String8(attr).string(), String8(ns).string(), value);
6977714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet            return false;
6987714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet        }
6997714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet
700ed9830999aede5e827b31446f91ad90a37b8bba9Kenny Root        fprintf(stderr, "Warning: AndroidManifest.xml already defines %s (in %s);"
701ed9830999aede5e827b31446f91ad90a37b8bba9Kenny Root                        " using existing value in manifest.\n",
70262da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn                String8(attr).string(), String8(ns).string());
7037714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet
7047714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet        // don't stop the build.
7057714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet        return true;
70662da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn    }
70762da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn
70862da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn    node->addAttribute(ns, attr, String16(value));
7097714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet    return true;
71062da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn}
71162da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn
712ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackbornstatic void fullyQualifyClassName(const String8& package, sp<XMLNode> node,
713ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn        const String16& attrName) {
7142fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton    XMLNode::attribute_entry* attr = node->editAttribute(
715ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn            String16("http://schemas.android.com/apk/res/android"), attrName);
7162fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton    if (attr != NULL) {
7172fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton        String8 name(attr->string);
7182fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton
7192fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton        // asdf     --> package.asdf
7202fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton        // .asdf  .a.b  --> package.asdf package.a.b
7212fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton        // asdf.adsf --> asdf.asdf
7222fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton        String8 className;
7232fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton        const char* p = name.string();
7242fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton        const char* q = strchr(p, '.');
7252fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton        if (p == q) {
7262fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton            className += package;
7272fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton            className += name;
7282fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton        } else if (q == NULL) {
7292fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton            className += package;
7302fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton            className += ".";
7312fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton            className += name;
7322fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton        } else {
7332fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton            className += name;
7342fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton        }
7352fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton        NOISY(printf("Qualifying class '%s' to '%s'", name.string(), className.string()));
7362fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton        attr->string.setTo(String16(className));
7372fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton    }
7382fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton}
7392fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton
74062da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackbornstatus_t massageManifest(Bundle* bundle, sp<XMLNode> root)
74162da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn{
74262da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn    root = root->searchElement(String16(), String16("manifest"));
74362da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn    if (root == NULL) {
74462da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn        fprintf(stderr, "No <manifest> tag.\n");
74562da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn        return UNKNOWN_ERROR;
74662da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn    }
7477714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet
7487714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet    bool errorOnFailedInsert = bundle->getErrorOnFailedInsert();
7497714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet
7507714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet    if (!addTagAttribute(root, RESOURCES_ANDROID_NAMESPACE, "versionCode",
7517714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet            bundle->getVersionCode(), errorOnFailedInsert)) {
7527714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet        return UNKNOWN_ERROR;
7537714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet    }
7547714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet    if (!addTagAttribute(root, RESOURCES_ANDROID_NAMESPACE, "versionName",
7557714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet            bundle->getVersionName(), errorOnFailedInsert)) {
7567714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet        return UNKNOWN_ERROR;
7577714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet    }
75862da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn
75962da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn    if (bundle->getMinSdkVersion() != NULL
76062da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn            || bundle->getTargetSdkVersion() != NULL
76162da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn            || bundle->getMaxSdkVersion() != NULL) {
76262da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn        sp<XMLNode> vers = root->getChildElement(String16(), String16("uses-sdk"));
76362da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn        if (vers == NULL) {
76462da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn            vers = XMLNode::newElement(root->getFilename(), String16(), String16("uses-sdk"));
76562da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn            root->insertChildAt(vers, 0);
76662da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn        }
76762da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn
7687714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet        if (!addTagAttribute(vers, RESOURCES_ANDROID_NAMESPACE, "minSdkVersion",
7697714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet                bundle->getMinSdkVersion(), errorOnFailedInsert)) {
7707714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet            return UNKNOWN_ERROR;
7717714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet        }
7727714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet        if (!addTagAttribute(vers, RESOURCES_ANDROID_NAMESPACE, "targetSdkVersion",
7737714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet                bundle->getTargetSdkVersion(), errorOnFailedInsert)) {
7747714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet            return UNKNOWN_ERROR;
7757714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet        }
7767714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet        if (!addTagAttribute(vers, RESOURCES_ANDROID_NAMESPACE, "maxSdkVersion",
7777714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet                bundle->getMaxSdkVersion(), errorOnFailedInsert)) {
7787714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet            return UNKNOWN_ERROR;
7797714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet        }
78062da8461ed5317fe78ae5e3793662694e7fc99a3Dianne Hackborn    }
7812fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton
7826487b099231b1e5d36ae37a921399b028b3b3ad9Xavier Ducrohet    if (bundle->getDebugMode()) {
7836487b099231b1e5d36ae37a921399b028b3b3ad9Xavier Ducrohet        sp<XMLNode> application = root->getChildElement(String16(), String16("application"));
7846487b099231b1e5d36ae37a921399b028b3b3ad9Xavier Ducrohet        if (application != NULL) {
7857714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet            if (!addTagAttribute(application, RESOURCES_ANDROID_NAMESPACE, "debuggable", "true",
7867714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet                    errorOnFailedInsert)) {
7877714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet                return UNKNOWN_ERROR;
7887714a2429b192c88e134ff67b969121bbaeb5457Xavier Ducrohet            }
7896487b099231b1e5d36ae37a921399b028b3b3ad9Xavier Ducrohet        }
7906487b099231b1e5d36ae37a921399b028b3b3ad9Xavier Ducrohet    }
7916487b099231b1e5d36ae37a921399b028b3b3ad9Xavier Ducrohet
7922fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton    // Deal with manifest package name overrides
7932fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton    const char* manifestPackageNameOverride = bundle->getManifestPackageNameOverride();
7942fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton    if (manifestPackageNameOverride != NULL) {
7952fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton        // Update the actual package name
7962fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton        XMLNode::attribute_entry* attr = root->editAttribute(String16(), String16("package"));
7972fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton        if (attr == NULL) {
7982fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton            fprintf(stderr, "package name is required with --rename-manifest-package.\n");
7992fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton            return UNKNOWN_ERROR;
8002fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton        }
8012fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton        String8 origPackage(attr->string);
8022fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton        attr->string.setTo(String16(manifestPackageNameOverride));
8032fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton        NOISY(printf("Overriding package '%s' to be '%s'\n", origPackage.string(), manifestPackageNameOverride));
8042fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton
8052fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton        // Make class names fully qualified
8062fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton        sp<XMLNode> application = root->getChildElement(String16(), String16("application"));
8072fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton        if (application != NULL) {
808ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn            fullyQualifyClassName(origPackage, application, String16("name"));
809b0381efaf71e917214cec78ed1c35eb688454e93Dianne Hackborn            fullyQualifyClassName(origPackage, application, String16("backupAgent"));
8102fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton
8112fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton            Vector<sp<XMLNode> >& children = const_cast<Vector<sp<XMLNode> >&>(application->getChildren());
8122fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton            for (size_t i = 0; i < children.size(); i++) {
8132fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton                sp<XMLNode> child = children.editItemAt(i);
8142fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton                String8 tag(child->getElementName());
8152fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton                if (tag == "activity" || tag == "service" || tag == "receiver" || tag == "provider") {
816ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn                    fullyQualifyClassName(origPackage, child, String16("name"));
817ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn                } else if (tag == "activity-alias") {
818ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn                    fullyQualifyClassName(origPackage, child, String16("name"));
819ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn                    fullyQualifyClassName(origPackage, child, String16("targetActivity"));
8202fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton                }
8212fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton            }
8222fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton        }
8232fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton    }
8242fee0ed6eb99b211efa06f095a41268a2021214aJeff Hamilton
825ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn    // Deal with manifest package name overrides
826ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn    const char* instrumentationPackageNameOverride = bundle->getInstrumentationPackageNameOverride();
827ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn    if (instrumentationPackageNameOverride != NULL) {
828ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn        // Fix up instrumentation targets.
829ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn        Vector<sp<XMLNode> >& children = const_cast<Vector<sp<XMLNode> >&>(root->getChildren());
830ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn        for (size_t i = 0; i < children.size(); i++) {
831ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn            sp<XMLNode> child = children.editItemAt(i);
832ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn            String8 tag(child->getElementName());
833ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn            if (tag == "instrumentation") {
834ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn                XMLNode::attribute_entry* attr = child->editAttribute(
835ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn                        String16("http://schemas.android.com/apk/res/android"), String16("targetPackage"));
836ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn                if (attr != NULL) {
837ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn                    attr->string.setTo(String16(instrumentationPackageNameOverride));
838ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn                }
839ef05e076ced1a32c5c0aaee28403779834adb2baDianne Hackborn            }
840ef05e076ced1a32c5c0aaee28403779834adb2ba