AAPT support for feature splits
This change allows the developer to add a base package for
which to build a feature split. The generated resource types
will begin after the base APK's defined types so as not
to collide or override resources.
Multiple features can be generated by first choosing an
arbitrary order for the features. Then for each feature,
the base APK and any preceding features are specified
with the --feature-of flags.
So with a base APK 'A' and features, 'B', and 'C',
'B' would be built with
aapt package [...] --feature-of A [...]
and 'C' would be built with
aapt package [...] --feature-of A --feature-of B [...]
Change-Id: I1be66e3f8df9a737b21c71f8a93685376c7e6780
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index 2028ff4..eead68c 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -1542,22 +1542,41 @@
status_t AaptAssets::buildIncludedResources(Bundle* bundle)
{
- if (!mHaveIncludedAssets) {
- // Add in all includes.
- const Vector<const char*>& incl = bundle->getPackageIncludes();
- const size_t N=incl.size();
- for (size_t i=0; i<N; i++) {
- if (bundle->getVerbose())
- printf("Including resources from package: %s\n", incl[i]);
- if (!mIncludedAssets.addAssetPath(String8(incl[i]), NULL)) {
- fprintf(stderr, "ERROR: Asset package include '%s' not found.\n",
- incl[i]);
- return UNKNOWN_ERROR;
- }
- }
- mHaveIncludedAssets = true;
+ if (mHaveIncludedAssets) {
+ return NO_ERROR;
}
+ // Add in all includes.
+ const Vector<String8>& includes = bundle->getPackageIncludes();
+ const size_t packageIncludeCount = includes.size();
+ for (size_t i = 0; i < packageIncludeCount; i++) {
+ if (bundle->getVerbose()) {
+ printf("Including resources from package: %s\n", includes[i].string());
+ }
+
+ if (!mIncludedAssets.addAssetPath(includes[i], NULL)) {
+ fprintf(stderr, "ERROR: Asset package include '%s' not found.\n",
+ includes[i].string());
+ return UNKNOWN_ERROR;
+ }
+ }
+
+ const String8& featureOfBase = bundle->getFeatureOfPackage();
+ if (!featureOfBase.isEmpty()) {
+ if (bundle->getVerbose()) {
+ printf("Including base feature resources from package: %s\n",
+ featureOfBase.string());
+ }
+
+ if (!mIncludedAssets.addAssetPath(featureOfBase, NULL)) {
+ fprintf(stderr, "ERROR: base feature package '%s' not found.\n",
+ featureOfBase.string());
+ return UNKNOWN_ERROR;
+ }
+ }
+
+ mHaveIncludedAssets = true;
+
return NO_ERROR;
}
diff --git a/tools/aapt/Bundle.h b/tools/aapt/Bundle.h
index ceb52a0..1439f14 100644
--- a/tools/aapt/Bundle.h
+++ b/tools/aapt/Bundle.h
@@ -159,12 +159,16 @@
const android::Vector<android::String8>& getSplitConfigurations() const { return mPartialConfigurations; }
const char* getResourceIntermediatesDir() const { return mResourceIntermediatesDir; }
void setResourceIntermediatesDir(const char* dir) { mResourceIntermediatesDir = dir; }
- const android::Vector<const char*>& getPackageIncludes() const { return mPackageIncludes; }
- void addPackageInclude(const char* file) { mPackageIncludes.add(file); }
+ const android::Vector<android::String8>& getPackageIncludes() const { return mPackageIncludes; }
+ void addPackageInclude(const char* file) { mPackageIncludes.add(android::String8(file)); }
const android::Vector<const char*>& getJarFiles() const { return mJarFiles; }
void addJarFile(const char* file) { mJarFiles.add(file); }
const android::Vector<const char*>& getNoCompressExtensions() const { return mNoCompressExtensions; }
void addNoCompressExtension(const char* ext) { mNoCompressExtensions.add(ext); }
+ void setFeatureOfPackage(const char* str) { mFeatureOfPackage = str; }
+ const android::String8& getFeatureOfPackage() const { return mFeatureOfPackage; }
+ void setFeatureAfterPackage(const char* str) { mFeatureAfterPackage = str; }
+ const android::String8& getFeatureAfterPackage() const { return mFeatureAfterPackage; }
const char* getManifestMinSdkVersion() const { return mManifestMinSdkVersion; }
void setManifestMinSdkVersion(const char* val) { mManifestMinSdkVersion = val; }
@@ -290,12 +294,14 @@
android::String8 mConfigurations;
android::String8 mPreferredDensity;
android::Vector<android::String8> mPartialConfigurations;
- android::Vector<const char*> mPackageIncludes;
+ android::Vector<android::String8> mPackageIncludes;
android::Vector<const char*> mJarFiles;
android::Vector<const char*> mNoCompressExtensions;
android::Vector<const char*> mAssetSourceDirs;
android::Vector<const char*> mResourceSourceDirs;
+ android::String8 mFeatureOfPackage;
+ android::String8 mFeatureAfterPackage;
const char* mManifestMinSdkVersion;
const char* mMinSdkVersion;
const char* mTargetSdkVersion;
diff --git a/tools/aapt/Main.cpp b/tools/aapt/Main.cpp
index 322d86c..736ae26 100644
--- a/tools/aapt/Main.cpp
+++ b/tools/aapt/Main.cpp
@@ -71,6 +71,7 @@
" [--product product1,product2,...] \\\n"
" [-c CONFIGS] [--preferred-configurations CONFIGS] \\\n"
" [--split CONFIGS [--split CONFIGS]] \\\n"
+ " [--feature-of package [--feature-after package]] \\\n"
" [raw-files-dir [raw-files-dir] ...] \\\n"
" [--output-text-symbols DIR]\n"
"\n"
@@ -167,6 +168,14 @@
" --split\n"
" Builds a separate split APK for the configurations listed. This can\n"
" be loaded alongside the base APK at runtime.\n"
+ " --feature-of\n"
+ " Builds a split APK that is a feature of the apk specified here. Resources\n"
+ " in the base APK can be referenced from the the feature APK.\n"
+ " --feature-after\n"
+ " An app can have multiple Feature Split APKs which must be totally ordered.\n"
+ " If --feature-of is specified, this flag specifies which Feature Split APK\n"
+ " comes before this one. The first Feature Split APK should not define\n"
+ " anything here.\n"
" --rename-manifest-package\n"
" Rewrite the manifest so that its package name is the package name\n"
" given here. Relative class names (for example .Foo) will be\n"
@@ -583,6 +592,24 @@
goto bail;
}
bundle.addSplitConfigurations(argv[0]);
+ } else if (strcmp(cp, "-feature-of") == 0) {
+ argc--;
+ argv++;
+ if (!argc) {
+ fprintf(stderr, "ERROR: No argument supplied for '--feature-of' option\n");
+ wantUsage = true;
+ goto bail;
+ }
+ bundle.setFeatureOfPackage(argv[0]);
+ } else if (strcmp(cp, "-feature-after") == 0) {
+ argc--;
+ argv++;
+ if (!argc) {
+ fprintf(stderr, "ERROR: No argument supplied for '--feature-after' option\n");
+ wantUsage = true;
+ goto bail;
+ }
+ bundle.setFeatureAfterPackage(argv[0]);
} else if (strcmp(cp, "-rename-manifest-package") == 0) {
argc--;
argv++;
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index 4f1d15e..033ff40 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -860,6 +860,18 @@
}
}
+ // Generate split name if feature is present.
+ const XMLNode::attribute_entry* attr = root->getAttribute(String16(), String16("featureName"));
+ if (attr != NULL) {
+ String16 splitName("feature_");
+ splitName.append(attr->string);
+ status_t err = root->addAttribute(String16(), String16("split"), splitName);
+ if (err != NO_ERROR) {
+ ALOGE("Failed to insert split name into AndroidManifest.xml");
+ return err;
+ }
+ }
+
return NO_ERROR;
}
@@ -968,7 +980,16 @@
NOISY(printf("Creating resources for package %s\n",
assets->getPackage().string()));
- ResourceTable table(bundle, String16(assets->getPackage()));
+ ResourceTable::PackageType packageType = ResourceTable::App;
+ if (bundle->getBuildSharedLibrary()) {
+ packageType = ResourceTable::SharedLibrary;
+ } else if (bundle->getExtending()) {
+ packageType = ResourceTable::System;
+ } else if (!bundle->getFeatureOfPackage().isEmpty()) {
+ packageType = ResourceTable::AppFeature;
+ }
+
+ ResourceTable table(bundle, String16(assets->getPackage()), packageType);
err = table.addIncludedResources(bundle, assets);
if (err != NO_ERROR) {
return err;
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index ac54638..cf1d4fd 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -1713,12 +1713,49 @@
return hasErrors ? UNKNOWN_ERROR : NO_ERROR;
}
-ResourceTable::ResourceTable(Bundle* bundle, const String16& assetsPackage)
- : mAssetsPackage(assetsPackage), mNextPackageId(1), mHaveAppPackage(false),
- mIsAppPackage(!bundle->getExtending()), mIsSharedLibrary(bundle->getBuildSharedLibrary()),
- mNumLocal(0),
- mBundle(bundle)
+ResourceTable::ResourceTable(Bundle* bundle, const String16& assetsPackage, ResourceTable::PackageType type)
+ : mAssetsPackage(assetsPackage)
+ , mPackageType(type)
+ , mTypeIdOffset(0)
+ , mNumLocal(0)
+ , mBundle(bundle)
{
+ ssize_t packageId = -1;
+ switch (mPackageType) {
+ case App:
+ case AppFeature:
+ packageId = 0x7f;
+ break;
+
+ case System:
+ packageId = 0x01;
+ break;
+
+ case SharedLibrary:
+ packageId = 0x00;
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+ sp<Package> package = new Package(mAssetsPackage, packageId);
+ mPackages.add(assetsPackage, package);
+ mOrderedPackages.add(package);
+
+ // Every resource table always has one first entry, the bag attributes.
+ const SourcePos unknown(String8("????"), 0);
+ getType(mAssetsPackage, String16("attr"), unknown);
+}
+
+static uint32_t findLargestTypeIdForPackage(const ResTable& table, const String16& packageName) {
+ const size_t basePackageCount = table.getBasePackageCount();
+ for (size_t i = 0; i < basePackageCount; i++) {
+ if (packageName == table.getBasePackageName(i)) {
+ return table.getLastTypeIdForPackage(i);
+ }
+ }
+ return 0;
}
status_t ResourceTable::addIncludedResources(Bundle* bundle, const sp<AaptAssets>& assets)
@@ -1728,59 +1765,22 @@
return err;
}
- // For future reference to included resources.
mAssets = assets;
+ mTypeIdOffset = findLargestTypeIdForPackage(assets->getIncludedResources(), mAssetsPackage);
- const ResTable& incl = assets->getIncludedResources();
-
- // Retrieve all the packages.
- const size_t N = incl.getBasePackageCount();
- for (size_t phase=0; phase<2; phase++) {
- for (size_t i=0; i<N; i++) {
- const String16 name = incl.getBasePackageName(i);
- uint32_t id = incl.getBasePackageId(i);
-
- // First time through: only add base packages (id
- // is not 0); second time through add the other
- // packages.
- if (phase != 0) {
- if (id != 0) {
- // Skip base packages -- already one.
- id = 0;
- } else {
- // Assign a dynamic id.
- id = mNextPackageId;
- }
- } else if (id != 0) {
- if (id == 127) {
- if (mHaveAppPackage) {
- fprintf(stderr, "Included resources have two application packages!\n");
- return UNKNOWN_ERROR;
- }
- mHaveAppPackage = true;
- }
- if (mNextPackageId > id) {
- fprintf(stderr, "Included base package ID %d already in use!\n", id);
- return UNKNOWN_ERROR;
- }
- }
- if (id != 0) {
- NOISY(fprintf(stderr, "Including package %s with ID=%d\n",
- String8(name).string(), id));
- sp<Package> p = new Package(name, id);
- mPackages.add(name, p);
- mOrderedPackages.add(p);
-
- if (id >= mNextPackageId) {
- mNextPackageId = id+1;
- }
- }
+ const String8& featureAfter = bundle->getFeatureAfterPackage();
+ if (!featureAfter.isEmpty()) {
+ AssetManager featureAssetManager;
+ if (!featureAssetManager.addAssetPath(featureAfter, NULL)) {
+ fprintf(stderr, "ERROR: Feature package '%s' not found.\n",
+ featureAfter.string());
+ return UNKNOWN_ERROR;
}
- }
- // Every resource table always has one first entry, the bag attributes.
- const SourcePos unknown(String8("????"), 0);
- sp<Type> attr = getType(mAssetsPackage, String16("attr"), unknown);
+ const ResTable& featureTable = featureAssetManager.getResources(false);
+ mTypeIdOffset = max(mTypeIdOffset,
+ findLargestTypeIdForPackage(featureTable, mAssetsPackage));
+ }
return NO_ERROR;
}
@@ -1820,24 +1820,16 @@
const int32_t format,
const bool overwrite)
{
- // Check for adding entries in other packages... for now we do
- // nothing. We need to do the right thing here to support skinning.
uint32_t rid = mAssets->getIncludedResources()
.identifierForName(name.string(), name.size(),
type.string(), type.size(),
package.string(), package.size());
if (rid != 0) {
- return NO_ERROR;
+ sourcePos.error("Resource entry %s/%s is already defined in package %s.",
+ String8(type).string(), String8(name).string(), String8(package).string());
+ return UNKNOWN_ERROR;
}
-#if 0
- if (name == String16("left")) {
- printf("Adding entry left: file=%s, line=%d, type=%s, value=%s\n",
- sourcePos.file.string(), sourcePos.line, String8(type).string(),
- String8(value).string());
- }
-#endif
-
sp<Entry> e = getEntry(package, type, name, sourcePos, overwrite,
params, doSetIndex);
if (e == NULL) {
@@ -1868,15 +1860,11 @@
type.string(), type.size(),
package.string(), package.size());
if (rid != 0) {
- return NO_ERROR;
+ sourcePos.error("Resource entry %s/%s is already defined in package %s.",
+ String8(type).string(), String8(name).string(), String8(package).string());
+ return UNKNOWN_ERROR;
}
-
-#if 0
- if (name == String16("left")) {
- printf("Adding bag left: file=%s, line=%d, type=%s\n",
- sourcePos.file.striing(), sourcePos.line, String8(type).string());
- }
-#endif
+
if (overlay && !mBundle->getAutoAddOverlay() && !hasBagOrEntry(package, type, name)) {
bool canAdd = false;
sp<Package> p = mPackages.valueFor(package);
@@ -2117,9 +2105,6 @@
uint32_t id = ResourceIdCache::lookup(package, type, name, onlyPublic);
if (id != 0) return id; // cache hit
- sp<Package> p = mPackages.valueFor(package);
- if (p == NULL) return 0;
-
// First look for this in the included resources...
uint32_t specFlags = 0;
uint32_t rid = mAssets->getIncludedResources()
@@ -2134,13 +2119,11 @@
}
}
- if (Res_INTERNALID(rid)) {
- return ResourceIdCache::store(package, type, name, onlyPublic, rid);
- }
- return ResourceIdCache::store(package, type, name, onlyPublic,
- Res_MAKEID(p->getAssignedId()-1, Res_GETTYPE(rid), Res_GETENTRY(rid)));
+ return ResourceIdCache::store(package, type, name, onlyPublic, rid);
}
+ sp<Package> p = mPackages.valueFor(package);
+ if (p == NULL) return 0;
sp<Type> t = p->getTypes().valueFor(type);
if (t == NULL) return 0;
sp<ConfigList> c = t->getConfigs().valueFor(name);
@@ -2294,9 +2277,12 @@
}
if (mAssetsPackage != package) {
- mCurrentXmlPos.warning("creating resource for external package %s: %s/%s.",
+ mCurrentXmlPos.error("creating resource for external package %s: %s/%s.",
String8(package).string(), String8(type).string(), String8(name).string());
- mCurrentXmlPos.printf("This will be an error in a future version of AAPT.");
+ if (package == String16("android")) {
+ mCurrentXmlPos.printf("did you mean to use @+id instead of @+android:id?");
+ }
+ return 0;
}
String16 value("false");
@@ -2479,6 +2465,7 @@
continue;
}
+ // This has no sense for packages being built as AppFeature (aka with a non-zero offset).
status_t err = p->applyPublicTypeOrder();
if (err != NO_ERROR && firstError == NO_ERROR) {
firstError = err;
@@ -2512,6 +2499,11 @@
}
}
+ uint32_t typeIdOffset = 0;
+ if (mPackageType == AppFeature && p->getName() == mAssetsPackage) {
+ typeIdOffset = mTypeIdOffset;
+ }
+
const SourcePos unknown(String8("????"), 0);
sp<Type> attr = p->getType(String16("attr"), unknown);
@@ -2527,7 +2519,7 @@
}
const size_t N = t->getOrderedConfigs().size();
- t->setIndex(ti+1);
+ t->setIndex(ti + 1 + typeIdOffset);
LOG_ALWAYS_FATAL_IF(ti == 0 && attr != t,
"First type is not attr!");
@@ -2599,7 +2591,7 @@
if (rid == 0) {
return UNKNOWN_ERROR;
}
- if (Res_GETPACKAGE(rid) == (size_t)(p->getAssignedId()-1)) {
+ if (Res_GETPACKAGE(rid) + 1 == p->getAssignedId()) {
typeSymbols->addSymbol(String8(c->getName()), rid, c->getPos());
String16 comment(c->getComment());
@@ -2608,11 +2600,6 @@
// String8(c->getName()).string(), String8(comment).string());
comment = c->getTypeComment();
typeSymbols->appendTypeComment(String8(c->getName()), comment);
- } else {
-#if 0
- printf("**** NO MATCH: 0x%08x vs 0x%08x\n",
- Res_GETPACKAGE(rid), p->getAssignedId());
-#endif
}
}
}
@@ -2749,7 +2736,7 @@
}
continue;
} else if (p->getAssignedId() == 0x00) {
- if (!bundle->getBuildSharedLibrary()) {
+ if (mPackageType != SharedLibrary) {
fprintf(stderr, "ERROR: Package %s can not have ID=0x00 unless building a shared library.",
String8(p->getName()).string());
return UNKNOWN_ERROR;
@@ -2761,15 +2748,24 @@
StringPool typeStrings(useUTF8);
StringPool keyStrings(useUTF8);
+ ssize_t stringsAdded = 0;
const size_t N = p->getOrderedTypes().size();
for (size_t ti=0; ti<N; ti++) {
sp<Type> t = p->getOrderedTypes().itemAt(ti);
if (t == NULL) {
typeStrings.add(String16("<empty>"), false);
+ stringsAdded++;
continue;
}
+
+ while (stringsAdded < t->getIndex() - 1) {
+ typeStrings.add(String16("<empty>"), false);
+ stringsAdded++;
+ }
+
const String16 typeName(t->getName());
typeStrings.add(typeName, false);
+ stringsAdded++;
// This is a hack to tweak the sorting order of the final strings,
// to put stuff that is generally not language-specific first.
@@ -2862,7 +2858,7 @@
memset(header, 0, sizeof(*header));
header->header.type = htods(RES_TABLE_PACKAGE_TYPE);
header->header.headerSize = htods(sizeof(*header));
- header->id = htodl(p->getAssignedId());
+ header->id = htodl(static_cast<uint32_t>(p->getAssignedId()));
strcpy16_htod(header->name, p->getName().string());
// Write the string blocks.
@@ -2902,7 +2898,9 @@
LOG_ALWAYS_FATAL_IF(t == NULL && typeName != String16("<empty>"),
"Type name %s not found",
String8(typeName).string());
-
+ if (t == NULL) {
+ continue;
+ }
const bool filterable = (typeName != mipmap16);
const size_t N = t != NULL ? t->getOrderedConfigs().size() : 0;
@@ -3062,21 +3060,25 @@
tHeader->header.size = htodl(data->getSize()-typeStart);
}
- bool missing_entry = false;
- const char* log_prefix = bundle->getErrorOnMissingConfigEntry() ?
- "error" : "warning";
- for (size_t i = 0; i < N; ++i) {
- if (!validResources[i]) {
- sp<ConfigList> c = t->getOrderedConfigs().itemAt(i);
- fprintf(stderr, "%s: no entries written for %s/%s (0x%08x)\n", log_prefix,
- String8(typeName).string(), String8(c->getName()).string(),
- Res_MAKEID(p->getAssignedId() - 1, ti, i));
- missing_entry = true;
+ // If we're building splits, then each invocation of the flattening
+ // step will have 'missing' entries. Don't warn/error for this case.
+ if (bundle->getSplitConfigurations().isEmpty()) {
+ bool missing_entry = false;
+ const char* log_prefix = bundle->getErrorOnMissingConfigEntry() ?
+ "error" : "warning";
+ for (size_t i = 0; i < N; ++i) {
+ if (!validResources[i]) {
+ sp<ConfigList> c = t->getOrderedConfigs().itemAt(i);
+ fprintf(stderr, "%s: no entries written for %s/%s (0x%08x)\n", log_prefix,
+ String8(typeName).string(), String8(c->getName()).string(),
+ Res_MAKEID(p->getAssignedId() - 1, ti, i));
+ missing_entry = true;
+ }
}
- }
- if (bundle->getErrorOnMissingConfigEntry() && missing_entry) {
- fprintf(stderr, "Error: Missing entries, quit!\n");
- return NOT_ENOUGH_DATA;
+ if (bundle->getErrorOnMissingConfigEntry() && missing_entry) {
+ fprintf(stderr, "Error: Missing entries, quit!\n");
+ return NOT_ENOUGH_DATA;
+ }
}
}
@@ -3819,8 +3821,8 @@
return hasError ? UNKNOWN_ERROR : NO_ERROR;
}
-ResourceTable::Package::Package(const String16& name, ssize_t includedId)
- : mName(name), mIncludedId(includedId),
+ResourceTable::Package::Package(const String16& name, size_t packageId)
+ : mName(name), mPackageId(packageId),
mTypeStringsMapping(0xffffffff),
mKeyStringsMapping(0xffffffff)
{
@@ -3945,26 +3947,10 @@
sp<ResourceTable::Package> ResourceTable::getPackage(const String16& package)
{
- sp<Package> p = mPackages.valueFor(package);
- if (p == NULL) {
- if (mIsAppPackage) {
- if (mHaveAppPackage) {
- fprintf(stderr, "Adding multiple application package resources; only one is allowed.\n"
- "Use -x to create extended resources.\n");
- return NULL;
- }
- mHaveAppPackage = true;
- p = new Package(package, mIsSharedLibrary ? 0 : 127);
- } else {
- p = new Package(package, mNextPackageId);
- }
- //printf("*** NEW PACKAGE: \"%s\" id=%d\n",
- // String8(package).string(), p->getAssignedId());
- mPackages.add(package, p);
- mOrderedPackages.add(p);
- mNextPackageId++;
+ if (package != mAssetsPackage) {
+ return NULL;
}
- return p;
+ return mPackages.valueFor(package);
}
sp<ResourceTable::Type> ResourceTable::getType(const String16& package,
@@ -3997,11 +3983,10 @@
sp<const ResourceTable::Entry> ResourceTable::getEntry(uint32_t resID,
const ResTable_config* config) const
{
- int pid = Res_GETPACKAGE(resID)+1;
+ size_t pid = Res_GETPACKAGE(resID)+1;
const size_t N = mOrderedPackages.size();
- size_t i;
sp<Package> p;
- for (i=0; i<N; i++) {
+ for (size_t i = 0; i < N; i++) {
sp<Package> check = mOrderedPackages[i];
if (check->getAssignedId() == pid) {
p = check;
diff --git a/tools/aapt/ResourceTable.h b/tools/aapt/ResourceTable.h
index a73993c..d4f47ef 100644
--- a/tools/aapt/ResourceTable.h
+++ b/tools/aapt/ResourceTable.h
@@ -74,11 +74,23 @@
class ResourceTable : public ResTable::Accessor
{
public:
+ // The type of package to build.
+ enum PackageType {
+ App,
+ System,
+ SharedLibrary,
+ AppFeature
+ };
+
class Package;
class Type;
class Entry;
- ResourceTable(Bundle* bundle, const String16& assetsPackage);
+ ResourceTable(Bundle* bundle, const String16& assetsPackage, PackageType type);
+
+ const String16& getAssetsPackage() const {
+ return mAssetsPackage;
+ }
status_t addIncludedResources(Bundle* bundle, const sp<AaptAssets>& assets);
@@ -448,7 +460,7 @@
class Package : public RefBase {
public:
- Package(const String16& name, ssize_t includedId=-1);
+ Package(const String16& name, size_t packageId);
virtual ~Package() { }
String16 getName() const { return mName; }
@@ -456,7 +468,7 @@
const SourcePos& pos,
bool doSetIndex = false);
- ssize_t getAssignedId() const { return mIncludedId; }
+ size_t getAssignedId() const { return mPackageId; }
const ResStringPool& getTypeStrings() const { return mTypeStrings; }
uint32_t indexOfTypeString(const String16& s) const { return mTypeStringsMapping.valueFor(s); }
@@ -479,7 +491,7 @@
DefaultKeyedVector<String16, uint32_t>* mappings);
const String16 mName;
- const ssize_t mIncludedId;
+ const size_t mPackageId;
DefaultKeyedVector<String16, sp<Type> > mTypes;
Vector<sp<Type> > mOrderedTypes;
sp<AaptFile> mTypeStringsData;
@@ -512,13 +524,11 @@
String16 mAssetsPackage;
+ PackageType mPackageType;
sp<AaptAssets> mAssets;
+ uint32_t mTypeIdOffset;
DefaultKeyedVector<String16, sp<Package> > mPackages;
Vector<sp<Package> > mOrderedPackages;
- uint32_t mNextPackageId;
- bool mHaveAppPackage;
- bool mIsAppPackage;
- bool mIsSharedLibrary;
size_t mNumLocal;
SourcePos mCurrentXmlPos;
Bundle* mBundle;