diff options
-rw-r--r-- | core/java/android/content/res/AssetManager.java | 18 | ||||
-rw-r--r-- | core/jni/android_util_AssetManager.cpp | 6 | ||||
-rw-r--r-- | include/androidfw/AssetManager.h | 7 | ||||
-rw-r--r-- | include/androidfw/ResourceTypes.h | 12 | ||||
-rw-r--r-- | libs/androidfw/AssetManager.cpp | 8 | ||||
-rw-r--r-- | libs/androidfw/ResourceTypes.cpp | 52 | ||||
-rw-r--r-- | libs/androidfw/tests/Android.mk | 1 | ||||
-rw-r--r-- | libs/androidfw/tests/AppAsLib_test.cpp | 53 | ||||
-rw-r--r-- | libs/androidfw/tests/data/appaslib/R.h | 38 | ||||
-rw-r--r-- | tools/aapt/Bundle.h | 4 | ||||
-rw-r--r-- | tools/aapt/Command.cpp | 6 | ||||
-rw-r--r-- | tools/aapt/Main.cpp | 6 |
12 files changed, 169 insertions, 42 deletions
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java index c248a9ee9b21..04c690b8334b 100644 --- a/core/java/android/content/res/AssetManager.java +++ b/core/java/android/content/res/AssetManager.java @@ -610,14 +610,28 @@ public final class AssetManager implements AutoCloseable { * {@hide} */ public final int addAssetPath(String path) { + return addAssetPathInternal(path, false); + } + + /** + * Add an application assets to the asset manager and loading it as shared library. + * This can be either a directory or ZIP file. Not for use by applications. Returns + * the cookie of the added asset, or 0 on failure. + * {@hide} + */ + public final int addAssetPathAsSharedLibrary(String path) { + return addAssetPathInternal(path, true); + } + + private final int addAssetPathInternal(String path, boolean appAsLib) { synchronized (this) { - int res = addAssetPathNative(path); + int res = addAssetPathNative(path, appAsLib); makeStringBlocks(mStringBlocks); return res; } } - private native final int addAssetPathNative(String path); + private native final int addAssetPathNative(String path, boolean appAsLib); /** * Add a set of assets to overlay an already added set of assets. diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp index 9aa544fb4e9d..7ca0654f9656 100644 --- a/core/jni/android_util_AssetManager.cpp +++ b/core/jni/android_util_AssetManager.cpp @@ -510,7 +510,7 @@ static jlong android_content_AssetManager_getAssetRemainingLength(JNIEnv* env, j } static jint android_content_AssetManager_addAssetPath(JNIEnv* env, jobject clazz, - jstring path) + jstring path, jboolean appAsLib) { ScopedUtfChars path8(env, path); if (path8.c_str() == NULL) { @@ -523,7 +523,7 @@ static jint android_content_AssetManager_addAssetPath(JNIEnv* env, jobject clazz } int32_t cookie; - bool res = am->addAssetPath(String8(path8.c_str()), &cookie); + bool res = am->addAssetPath(String8(path8.c_str()), &cookie, appAsLib); return (res) ? static_cast<jint>(cookie) : 0; } @@ -2138,7 +2138,7 @@ static JNINativeMethod gAssetManagerMethods[] = { (void*) android_content_AssetManager_getAssetLength }, { "getAssetRemainingLength", "(J)J", (void*) android_content_AssetManager_getAssetRemainingLength }, - { "addAssetPathNative", "(Ljava/lang/String;)I", + { "addAssetPathNative", "(Ljava/lang/String;Z)I", (void*) android_content_AssetManager_addAssetPath }, { "addOverlayPathNative", "(Ljava/lang/String;)I", (void*) android_content_AssetManager_addOverlayPath }, diff --git a/include/androidfw/AssetManager.h b/include/androidfw/AssetManager.h index 0cfd2b103d23..3d4e47d84c65 100644 --- a/include/androidfw/AssetManager.h +++ b/include/androidfw/AssetManager.h @@ -93,13 +93,14 @@ public: * look in multiple places for assets. It can be either a directory (for * finding assets as raw files on the disk) or a ZIP file. This newly * added asset path will be examined first when searching for assets, - * before any that were previously added. + * before any that were previously added, the assets are added as shared + * library if appAsLib is true. * * Returns "true" on success, "false" on failure. If 'cookie' is non-NULL, * then on success, *cookie is set to the value corresponding to the * newly-added asset source. */ - bool addAssetPath(const String8& path, int32_t* cookie); + bool addAssetPath(const String8& path, int32_t* cookie, bool appAsLib=false); bool addOverlayPath(const String8& path, int32_t* cookie); /* @@ -280,7 +281,7 @@ private: const ResTable* getResTable(bool required = true) const; void setLocaleLocked(const char* locale); void updateResourceParamsLocked() const; - bool appendPathToResTable(const asset_path& ap) const; + bool appendPathToResTable(const asset_path& ap, bool appAsLib=false) const; Asset* openIdmapLocked(const struct asset_path& ap) const; diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h index eff1f5f4e7d4..49b6333e8a4d 100644 --- a/include/androidfw/ResourceTypes.h +++ b/include/androidfw/ResourceTypes.h @@ -1505,7 +1505,7 @@ struct ResTable_lib_entry class DynamicRefTable { public: - DynamicRefTable(uint8_t packageId); + DynamicRefTable(uint8_t packageId, bool appAsLib); // Loads an unmapped reference table from the package. status_t load(const ResTable_lib_header* const header); @@ -1530,6 +1530,7 @@ private: const uint8_t mAssignedPackageId; uint8_t mLookupTable[256]; KeyedVector<String16, uint8_t> mEntries; + bool mAppAsLib; }; bool U16StringToInt(const char16_t* s, size_t len, Res_value* outValue); @@ -1547,10 +1548,11 @@ public: status_t add(const void* data, size_t size, const int32_t cookie=-1, bool copyData=false); status_t add(const void* data, size_t size, const void* idmapData, size_t idmapDataSize, - const int32_t cookie=-1, bool copyData=false); + const int32_t cookie=-1, bool copyData=false, bool appAsLib=false); status_t add(Asset* asset, const int32_t cookie=-1, bool copyData=false); - status_t add(Asset* asset, Asset* idmapAsset, const int32_t cookie=-1, bool copyData=false); + status_t add(Asset* asset, Asset* idmapAsset, const int32_t cookie=-1, bool copyData=false, + bool appAsLib=false); status_t add(ResTable* src); status_t addEmpty(const int32_t cookie); @@ -1858,7 +1860,7 @@ private: typedef Vector<Type*> TypeList; status_t addInternal(const void* data, size_t size, const void* idmapData, size_t idmapDataSize, - const int32_t cookie, bool copyData); + bool appAsLib, const int32_t cookie, bool copyData); ssize_t getResourcePackageIndex(uint32_t resID) const; @@ -1871,7 +1873,7 @@ private: size_t nameLen, uint32_t* outTypeSpecFlags) const; status_t parsePackage( - const ResTable_package* const pkg, const Header* const header); + const ResTable_package* const pkg, const Header* const header, bool appAsLib); void print_value(const Package* pkg, const Res_value& value) const; diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp index 623ea896626b..8a03b94492d8 100644 --- a/libs/androidfw/AssetManager.cpp +++ b/libs/androidfw/AssetManager.cpp @@ -176,7 +176,7 @@ AssetManager::~AssetManager(void) delete[] mVendor; } -bool AssetManager::addAssetPath(const String8& path, int32_t* cookie) +bool AssetManager::addAssetPath(const String8& path, int32_t* cookie, bool appAsLib) { AutoMutex _l(mLock); @@ -238,7 +238,7 @@ bool AssetManager::addAssetPath(const String8& path, int32_t* cookie) #endif if (mResources != NULL) { - appendPathToResTable(ap); + appendPathToResTable(ap, appAsLib); } return true; @@ -610,7 +610,7 @@ FileType AssetManager::getFileType(const char* fileName) return kFileTypeRegular; } -bool AssetManager::appendPathToResTable(const asset_path& ap) const { +bool AssetManager::appendPathToResTable(const asset_path& ap, bool appAsLib) const { // skip those ap's that correspond to system overlays if (ap.isSystemOverlay) { return true; @@ -685,7 +685,7 @@ bool AssetManager::appendPathToResTable(const asset_path& ap) const { mResources->add(sharedRes); } else { ALOGV("Parsing resources for %s", ap.path.string()); - mResources->add(ass, idmap, nextEntryIdx + 1, !shared); + mResources->add(ass, idmap, nextEntryIdx + 1, !shared, appAsLib); } onlyEmptyResources = false; diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp index 37de89ac53b6..21b543eefa01 100644 --- a/libs/androidfw/ResourceTypes.cpp +++ b/libs/androidfw/ResourceTypes.cpp @@ -3080,13 +3080,13 @@ struct ResTable::Package // table that defined the package); the ones after are skins on top of it. struct ResTable::PackageGroup { - PackageGroup(ResTable* _owner, const String16& _name, uint32_t _id) + PackageGroup(ResTable* _owner, const String16& _name, uint32_t _id, bool appAsLib) : owner(_owner) , name(_name) , id(_id) , largestTypeId(0) , bags(NULL) - , dynamicRefTable(static_cast<uint8_t>(_id)) + , dynamicRefTable(static_cast<uint8_t>(_id), appAsLib) { } ~PackageGroup() { @@ -3532,7 +3532,7 @@ ResTable::ResTable(const void* data, size_t size, const int32_t cookie, bool cop { memset(&mParams, 0, sizeof(mParams)); memset(mPackageMap, 0, sizeof(mPackageMap)); - addInternal(data, size, NULL, 0, cookie, copyData); + addInternal(data, size, NULL, 0, false, cookie, copyData); LOG_FATAL_IF(mError != NO_ERROR, "Error parsing resource table"); if (kDebugTableSuperNoisy) { ALOGI("Creating ResTable %p\n", this); @@ -3553,12 +3553,12 @@ inline ssize_t ResTable::getResourcePackageIndex(uint32_t resID) const } status_t ResTable::add(const void* data, size_t size, const int32_t cookie, bool copyData) { - return addInternal(data, size, NULL, 0, cookie, copyData); + return addInternal(data, size, NULL, 0, false, cookie, copyData); } status_t ResTable::add(const void* data, size_t size, const void* idmapData, size_t idmapDataSize, - const int32_t cookie, bool copyData) { - return addInternal(data, size, idmapData, idmapDataSize, cookie, copyData); + const int32_t cookie, bool copyData, bool appAsLib) { + return addInternal(data, size, idmapData, idmapDataSize, appAsLib, cookie, copyData); } status_t ResTable::add(Asset* asset, const int32_t cookie, bool copyData) { @@ -3568,10 +3568,12 @@ status_t ResTable::add(Asset* asset, const int32_t cookie, bool copyData) { return UNKNOWN_ERROR; } - return addInternal(data, static_cast<size_t>(asset->getLength()), NULL, 0, cookie, copyData); + return addInternal(data, static_cast<size_t>(asset->getLength()), NULL, false, 0, cookie, + copyData); } -status_t ResTable::add(Asset* asset, Asset* idmapAsset, const int32_t cookie, bool copyData) { +status_t ResTable::add(Asset* asset, Asset* idmapAsset, const int32_t cookie, bool copyData, + bool appAsLib) { const void* data = asset->getBuffer(true); if (data == NULL) { ALOGW("Unable to get buffer of resource asset file"); @@ -3590,7 +3592,7 @@ status_t ResTable::add(Asset* asset, Asset* idmapAsset, const int32_t cookie, bo } return addInternal(data, static_cast<size_t>(asset->getLength()), - idmapData, idmapSize, cookie, copyData); + idmapData, idmapSize, appAsLib, cookie, copyData); } status_t ResTable::add(ResTable* src) @@ -3603,7 +3605,7 @@ status_t ResTable::add(ResTable* src) for (size_t i=0; i<src->mPackageGroups.size(); i++) { PackageGroup* srcPg = src->mPackageGroups[i]; - PackageGroup* pg = new PackageGroup(this, srcPg->name, srcPg->id); + PackageGroup* pg = new PackageGroup(this, srcPg->name, srcPg->id, false); for (size_t j=0; j<srcPg->packages.size(); j++) { pg->packages.add(srcPg->packages[j]); } @@ -3644,7 +3646,7 @@ status_t ResTable::addEmpty(const int32_t cookie) { } status_t ResTable::addInternal(const void* data, size_t dataSize, const void* idmapData, size_t idmapDataSize, - const int32_t cookie, bool copyData) + bool appAsLib, const int32_t cookie, bool copyData) { if (!data) { return NO_ERROR; @@ -3747,7 +3749,7 @@ status_t ResTable::addInternal(const void* data, size_t dataSize, const void* id return (mError=BAD_TYPE); } - if (parsePackage((ResTable_package*)chunk, header) != NO_ERROR) { + if (parsePackage((ResTable_package*)chunk, header, appAsLib) != NO_ERROR) { return mError; } curPackage++; @@ -5935,7 +5937,7 @@ status_t ResTable::getEntry( } status_t ResTable::parsePackage(const ResTable_package* const pkg, - const Header* const header) + const Header* const header, bool appAsLib) { const uint8_t* base = (const uint8_t*)pkg; status_t err = validate_chunk(&pkg->header, sizeof(*pkg) - sizeof(pkg->typeIdOffset), @@ -5983,7 +5985,7 @@ status_t ResTable::parsePackage(const ResTable_package* const pkg, if (id >= 256) { LOG_ALWAYS_FATAL("Package id out of range"); return NO_ERROR; - } else if (id == 0) { + } else if (id == 0 || appAsLib) { // This is a library so assign an ID id = mNextPackageId++; } @@ -6016,7 +6018,7 @@ status_t ResTable::parsePackage(const ResTable_package* const pkg, char16_t tmpName[sizeof(pkg->name)/sizeof(pkg->name[0])]; strcpy16_dtoh(tmpName, pkg->name, sizeof(pkg->name)/sizeof(pkg->name[0])); - group = new PackageGroup(this, String16(tmpName), id); + group = new PackageGroup(this, String16(tmpName), id, appAsLib); if (group == NULL) { delete package; return (mError=NO_MEMORY); @@ -6228,8 +6230,9 @@ status_t ResTable::parsePackage(const ResTable_package* const pkg, return NO_ERROR; } -DynamicRefTable::DynamicRefTable(uint8_t packageId) +DynamicRefTable::DynamicRefTable(uint8_t packageId, bool appAsLib) : mAssignedPackageId(packageId) + , mAppAsLib(appAsLib) { memset(mLookupTable, 0, sizeof(mLookupTable)); @@ -6314,16 +6317,18 @@ status_t DynamicRefTable::lookupResourceId(uint32_t* resId) const { uint32_t res = *resId; size_t packageId = Res_GETPACKAGE(res) + 1; - if (packageId == APP_PACKAGE_ID) { + if (packageId == APP_PACKAGE_ID && !mAppAsLib) { // No lookup needs to be done, app package IDs are absolute. return NO_ERROR; } - if (packageId == 0) { + if (packageId == 0 || (packageId == APP_PACKAGE_ID && mAppAsLib)) { // The package ID is 0x00. That means that a shared library is accessing - // its own local resource, so we fix up the resource with the calling - // package ID. - *resId |= ((uint32_t) mAssignedPackageId) << 24; + // its own local resource. + // Or if app resource is loaded as shared library, the resource which has + // app package Id is local resources. + // so we fix up those resources with the calling package ID. + *resId = (0xFFFFFF & (*resId)) | (((uint32_t) mAssignedPackageId) << 24); return NO_ERROR; } @@ -6345,7 +6350,10 @@ status_t DynamicRefTable::lookupResourceId(uint32_t* resId) const { } status_t DynamicRefTable::lookupResourceValue(Res_value* value) const { - if (value->dataType != Res_value::TYPE_DYNAMIC_REFERENCE) { + if (value->dataType != Res_value::TYPE_DYNAMIC_REFERENCE && + (value->dataType != Res_value::TYPE_REFERENCE || !mAppAsLib)) { + // If the package is loaded as shared library, the resource reference + // also need to be fixed. return NO_ERROR; } diff --git a/libs/androidfw/tests/Android.mk b/libs/androidfw/tests/Android.mk index a353575b4073..2bc026b79ca2 100644 --- a/libs/androidfw/tests/Android.mk +++ b/libs/androidfw/tests/Android.mk @@ -21,6 +21,7 @@ LOCAL_PATH:= $(call my-dir) testFiles := \ + AppAsLib_test.cpp \ AttributeFinder_test.cpp \ ByteBucketArray_test.cpp \ Config_test.cpp \ diff --git a/libs/androidfw/tests/AppAsLib_test.cpp b/libs/androidfw/tests/AppAsLib_test.cpp new file mode 100644 index 000000000000..bdb0c3d38f6f --- /dev/null +++ b/libs/androidfw/tests/AppAsLib_test.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <androidfw/ResourceTypes.h> + +#include "data/basic/R.h" +#include "data/appaslib/R.h" + +#include <gtest/gtest.h> + +using namespace android; + +namespace { + +#include "data/basic/basic_arsc.h" + +TEST(AppAsLibTest, loadedAsApp) { + ResTable table; + ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len)); + + Res_value val; + ssize_t block = table.getResource(base::R::integer::number2, &val); + ASSERT_GE(block, 0); + ASSERT_EQ(Res_value::TYPE_REFERENCE, val.dataType); + ASSERT_EQ(base::R::array::integerArray1, val.data); +} + +TEST(AppAsLibTest, loadedAsSharedLib) { + ResTable table; + // Load as shared library. + ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len, NULL, 0, -1, false, true)); + + Res_value val; + ssize_t block = table.getResource(appaslib::R::integer::number2, &val); + ASSERT_GE(block, 0); + ASSERT_EQ(Res_value::TYPE_REFERENCE, val.dataType); + ASSERT_EQ(appaslib::R::array::integerArray1, val.data); +} + +} diff --git a/libs/androidfw/tests/data/appaslib/R.h b/libs/androidfw/tests/data/appaslib/R.h new file mode 100644 index 000000000000..f89d4bfdd15e --- /dev/null +++ b/libs/androidfw/tests/data/appaslib/R.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __APPASLIB_R_H +#define __APPASLIB_R_H + +namespace appaslib { +namespace R { + +namespace integer { + enum { + number2 = 0x02040001, // default + }; +} + +namespace array { + enum { + integerArray1 = 0x02060000, // default + }; +} + +} // namespace R +} // namespace appaslib + +#endif // __APPASLIB_R_H diff --git a/tools/aapt/Bundle.h b/tools/aapt/Bundle.h index cbe7c5dacc1e..c29bb482c159 100644 --- a/tools/aapt/Bundle.h +++ b/tools/aapt/Bundle.h @@ -66,6 +66,7 @@ public: mErrorOnMissingConfigEntry(false), mOutputTextSymbols(NULL), mSingleCrunchInputFile(NULL), mSingleCrunchOutputFile(NULL), mBuildSharedLibrary(false), + mBuildAppAsSharedLibrary(false), mArgc(0), mArgv(NULL) {} ~Bundle(void) {} @@ -206,6 +207,8 @@ public: void setSingleCrunchOutputFile(const char* val) { mSingleCrunchOutputFile = val; } bool getBuildSharedLibrary() const { return mBuildSharedLibrary; } void setBuildSharedLibrary(bool val) { mBuildSharedLibrary = val; } + bool getBuildAppAsSharedLibrary() const { return mBuildAppAsSharedLibrary; } + void setBuildAppAsSharedLibrary(bool val) { mBuildAppAsSharedLibrary = val; } void setNoVersionVectors(bool val) { mNoVersionVectors = val; } bool getNoVersionVectors() const { return mNoVersionVectors; } @@ -327,6 +330,7 @@ private: const char* mSingleCrunchInputFile; const char* mSingleCrunchOutputFile; bool mBuildSharedLibrary; + bool mBuildAppAsSharedLibrary; android::String8 mPlatformVersionCode; android::String8 mPlatformVersionName; diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp index d12ab3b725c8..21f47bc28ff3 100644 --- a/tools/aapt/Command.cpp +++ b/tools/aapt/Command.cpp @@ -2395,11 +2395,11 @@ int doPackage(Bundle* bundle) // Write the R.java file into the appropriate class directory // e.g. gen/com/foo/app/R.java err = writeResourceSymbols(bundle, assets, assets->getPackage(), true, - bundle->getBuildSharedLibrary()); + bundle->getBuildSharedLibrary() || bundle->getBuildAppAsSharedLibrary()); } else { const String8 customPkg(bundle->getCustomPackage()); err = writeResourceSymbols(bundle, assets, customPkg, true, - bundle->getBuildSharedLibrary()); + bundle->getBuildSharedLibrary() || bundle->getBuildAppAsSharedLibrary()); } if (err < 0) { goto bail; @@ -2414,7 +2414,7 @@ int doPackage(Bundle* bundle) while (packageString != NULL) { // Write the R.java file out with the correct package name err = writeResourceSymbols(bundle, assets, String8(packageString), true, - bundle->getBuildSharedLibrary()); + bundle->getBuildSharedLibrary() || bundle->getBuildAppAsSharedLibrary()); if (err < 0) { goto bail; } diff --git a/tools/aapt/Main.cpp b/tools/aapt/Main.cpp index bcf0d5e53c07..64112867a4b4 100644 --- a/tools/aapt/Main.cpp +++ b/tools/aapt/Main.cpp @@ -200,6 +200,9 @@ void usage(void) " --shared-lib\n" " Make a shared library resource package that can be loaded by an application\n" " at runtime to access the libraries resources. Implies --non-constant-id.\n" + " --app-as-shared-lib\n" + " Make an app resource package that also can be loaded as shared library at runtime.\n" + " Implies --non-constant-id.\n" " --error-on-failed-insert\n" " Forces aapt to return an error if it fails to insert values into the manifest\n" " with --debug-mode, --min-sdk-version, --target-sdk-version --version-code\n" @@ -668,6 +671,9 @@ int main(int argc, char* const argv[]) } else if (strcmp(cp, "-shared-lib") == 0) { bundle.setNonConstantId(true); bundle.setBuildSharedLibrary(true); + } else if (strcmp(cp, "-app-as-shared-lib") == 0) { + bundle.setNonConstantId(true); + bundle.setBuildAppAsSharedLibrary(true); } else if (strcmp(cp, "-no-crunch") == 0) { bundle.setUseCrunchCache(true); } else if (strcmp(cp, "-ignore-assets") == 0) { |