|  | /* | 
|  | * Copyright (C) 2006 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. | 
|  | */ | 
|  |  | 
|  | // | 
|  | // Asset management class.  AssetManager objects are thread-safe. | 
|  | // | 
|  | #ifndef __LIBS_ASSETMANAGER_H | 
|  | #define __LIBS_ASSETMANAGER_H | 
|  |  | 
|  | #include <utils/Asset.h> | 
|  | #include <utils/AssetDir.h> | 
|  | #include <utils/KeyedVector.h> | 
|  | #include <utils/String8.h> | 
|  | #include <utils/Vector.h> | 
|  | #include <utils/String16.h> | 
|  | #include <utils/ZipFileRO.h> | 
|  | #include <utils/threads.h> | 
|  |  | 
|  | /* | 
|  | * Native-app access is via the opaque typedef struct AAssetManager in the C namespace. | 
|  | */ | 
|  | #ifdef __cplusplus | 
|  | extern "C" { | 
|  | #endif | 
|  |  | 
|  | struct AAssetManager { }; | 
|  |  | 
|  | #ifdef __cplusplus | 
|  | }; | 
|  | #endif | 
|  |  | 
|  |  | 
|  | /* | 
|  | * Now the proper C++ android-namespace definitions | 
|  | */ | 
|  |  | 
|  | namespace android { | 
|  |  | 
|  | class Asset;        // fwd decl for things that include Asset.h first | 
|  | class ResTable; | 
|  | struct ResTable_config; | 
|  |  | 
|  | /* | 
|  | * Every application that uses assets needs one instance of this.  A | 
|  | * single instance may be shared across multiple threads, and a single | 
|  | * thread may have more than one instance (the latter is discouraged). | 
|  | * | 
|  | * The purpose of the AssetManager is to create Asset objects.  To do | 
|  | * this efficiently it may cache information about the locations of | 
|  | * files it has seen.  This can be controlled with the "cacheMode" | 
|  | * argument. | 
|  | * | 
|  | * The asset hierarchy may be examined like a filesystem, using | 
|  | * AssetDir objects to peruse a single directory. | 
|  | */ | 
|  | class AssetManager : public AAssetManager { | 
|  | public: | 
|  | typedef enum CacheMode { | 
|  | CACHE_UNKNOWN = 0, | 
|  | CACHE_OFF,          // don't try to cache file locations | 
|  | CACHE_DEFER,        // construct cache as pieces are needed | 
|  | //CACHE_SCAN,         // scan full(!) asset hierarchy at init() time | 
|  | } CacheMode; | 
|  |  | 
|  | AssetManager(CacheMode cacheMode = CACHE_OFF); | 
|  | virtual ~AssetManager(void); | 
|  |  | 
|  | static int32_t getGlobalCount(); | 
|  |  | 
|  | /* | 
|  | * Add a new source for assets.  This can be called multiple times to | 
|  | * 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. | 
|  | * | 
|  | * 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, void** cookie); | 
|  |  | 
|  | /* | 
|  | * Convenience for adding the standard system assets.  Uses the | 
|  | * ANDROID_ROOT environment variable to find them. | 
|  | */ | 
|  | bool addDefaultAssets(); | 
|  |  | 
|  | /* | 
|  | * Iterate over the asset paths in this manager.  (Previously | 
|  | * added via addAssetPath() and addDefaultAssets().)  On first call, | 
|  | * 'cookie' must be NULL, resulting in the first cookie being returned. | 
|  | * Each next cookie will be returned there-after, until NULL indicating | 
|  | * the end has been reached. | 
|  | */ | 
|  | void* nextAssetPath(void* cookie) const; | 
|  |  | 
|  | /* | 
|  | * Return an asset path in the manager.  'which' must be between 0 and | 
|  | * countAssetPaths(). | 
|  | */ | 
|  | String8 getAssetPath(void* cookie) const; | 
|  |  | 
|  | /* | 
|  | * Set the current locale and vendor.  The locale can change during | 
|  | * the lifetime of an AssetManager if the user updates the device's | 
|  | * language setting.  The vendor is less likely to change. | 
|  | * | 
|  | * Pass in NULL to indicate no preference. | 
|  | */ | 
|  | void setLocale(const char* locale); | 
|  | void setVendor(const char* vendor); | 
|  |  | 
|  | /* | 
|  | * Choose screen orientation for resources values returned. | 
|  | */ | 
|  | void setConfiguration(const ResTable_config& config, const char* locale = NULL); | 
|  |  | 
|  | void getConfiguration(ResTable_config* outConfig) const; | 
|  |  | 
|  | typedef Asset::AccessMode AccessMode;       // typing shortcut | 
|  |  | 
|  | /* | 
|  | * Open an asset. | 
|  | * | 
|  | * This will search through locale-specific and vendor-specific | 
|  | * directories and packages to find the file. | 
|  | * | 
|  | * The object returned does not depend on the AssetManager.  It should | 
|  | * be freed by calling Asset::close(). | 
|  | */ | 
|  | Asset* open(const char* fileName, AccessMode mode); | 
|  |  | 
|  | /* | 
|  | * Open a non-asset file as an asset. | 
|  | * | 
|  | * This is for opening files that are included in an asset package | 
|  | * but aren't assets.  These sit outside the usual "locale/vendor" | 
|  | * path hierarchy, and will not be seen by "AssetDir" or included | 
|  | * in our filename cache. | 
|  | */ | 
|  | Asset* openNonAsset(const char* fileName, AccessMode mode); | 
|  |  | 
|  | /* | 
|  | * Explicit non-asset file.  The file explicitly named by the cookie (the | 
|  | * resource set to look in) and fileName will be opened and returned. | 
|  | */ | 
|  | Asset* openNonAsset(void* cookie, const char* fileName, AccessMode mode); | 
|  |  | 
|  | /* | 
|  | * Open a directory within the asset hierarchy. | 
|  | * | 
|  | * The contents of the directory are an amalgam of vendor-specific, | 
|  | * locale-specific, and generic assets stored loosely or in asset | 
|  | * packages.  Depending on the cache setting and previous accesses, | 
|  | * this call may incur significant disk overhead. | 
|  | * | 
|  | * To open the top-level directory, pass in "". | 
|  | */ | 
|  | AssetDir* openDir(const char* dirName); | 
|  |  | 
|  | /* | 
|  | * Open a directory within a particular path of the asset manager. | 
|  | * | 
|  | * The contents of the directory are an amalgam of vendor-specific, | 
|  | * locale-specific, and generic assets stored loosely or in asset | 
|  | * packages.  Depending on the cache setting and previous accesses, | 
|  | * this call may incur significant disk overhead. | 
|  | * | 
|  | * To open the top-level directory, pass in "". | 
|  | */ | 
|  | AssetDir* openNonAssetDir(void* cookie, const char* dirName); | 
|  |  | 
|  | /* | 
|  | * Get the type of a file in the asset hierarchy.  They will either | 
|  | * be "regular" or "directory".  [Currently only works for "regular".] | 
|  | * | 
|  | * Can also be used as a quick test for existence of a file. | 
|  | */ | 
|  | FileType getFileType(const char* fileName); | 
|  |  | 
|  | /* | 
|  | * Return the complete resource table to find things in the package. | 
|  | */ | 
|  | const ResTable& getResources(bool required = true) const; | 
|  |  | 
|  | /* | 
|  | * Discard cached filename information.  This only needs to be called | 
|  | * if somebody has updated the set of "loose" files, and we want to | 
|  | * discard our cached notion of what's where. | 
|  | */ | 
|  | void purge(void) { purgeFileNameCacheLocked(); } | 
|  |  | 
|  | /* | 
|  | * Return true if the files this AssetManager references are all | 
|  | * up-to-date (have not been changed since it was created).  If false | 
|  | * is returned, you will need to create a new AssetManager to get | 
|  | * the current data. | 
|  | */ | 
|  | bool isUpToDate(); | 
|  |  | 
|  | /** | 
|  | * Get the known locales for this asset manager object. | 
|  | */ | 
|  | void getLocales(Vector<String8>* locales) const; | 
|  |  | 
|  | private: | 
|  | struct asset_path | 
|  | { | 
|  | String8 path; | 
|  | FileType type; | 
|  | String8 idmap; | 
|  | }; | 
|  |  | 
|  | Asset* openInPathLocked(const char* fileName, AccessMode mode, | 
|  | const asset_path& path); | 
|  | Asset* openNonAssetInPathLocked(const char* fileName, AccessMode mode, | 
|  | const asset_path& path); | 
|  | Asset* openInLocaleVendorLocked(const char* fileName, AccessMode mode, | 
|  | const asset_path& path, const char* locale, const char* vendor); | 
|  | String8 createPathNameLocked(const asset_path& path, const char* locale, | 
|  | const char* vendor); | 
|  | String8 createPathNameLocked(const asset_path& path, const char* rootDir); | 
|  | String8 createZipSourceNameLocked(const String8& zipFileName, | 
|  | const String8& dirName, const String8& fileName); | 
|  |  | 
|  | ZipFileRO* getZipFileLocked(const asset_path& path); | 
|  | Asset* openAssetFromFileLocked(const String8& fileName, AccessMode mode); | 
|  | Asset* openAssetFromZipLocked(const ZipFileRO* pZipFile, | 
|  | const ZipEntryRO entry, AccessMode mode, const String8& entryName); | 
|  |  | 
|  | bool scanAndMergeDirLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo, | 
|  | const asset_path& path, const char* rootDir, const char* dirName); | 
|  | SortedVector<AssetDir::FileInfo>* scanDirLocked(const String8& path); | 
|  | bool scanAndMergeZipLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo, | 
|  | const asset_path& path, const char* rootDir, const char* dirName); | 
|  | void mergeInfoLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo, | 
|  | const SortedVector<AssetDir::FileInfo>* pContents); | 
|  |  | 
|  | void loadFileNameCacheLocked(void); | 
|  | void fncScanLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo, | 
|  | const char* dirName); | 
|  | bool fncScanAndMergeDirLocked( | 
|  | SortedVector<AssetDir::FileInfo>* pMergedInfo, | 
|  | const asset_path& path, const char* locale, const char* vendor, | 
|  | const char* dirName); | 
|  | void purgeFileNameCacheLocked(void); | 
|  |  | 
|  | const ResTable* getResTable(bool required = true) const; | 
|  | void setLocaleLocked(const char* locale); | 
|  | void updateResourceParamsLocked() const; | 
|  |  | 
|  | bool createIdmapFileLocked(const String8& originalPath, const String8& overlayPath, | 
|  | const String8& idmapPath); | 
|  |  | 
|  | bool isIdmapStaleLocked(const String8& originalPath, const String8& overlayPath, | 
|  | const String8& idmapPath); | 
|  |  | 
|  | Asset* openIdmapLocked(const struct asset_path& ap) const; | 
|  |  | 
|  | bool getZipEntryCrcLocked(const String8& zipPath, const char* entryFilename, uint32_t* pCrc); | 
|  |  | 
|  | class SharedZip : public RefBase { | 
|  | public: | 
|  | static sp<SharedZip> get(const String8& path); | 
|  |  | 
|  | ZipFileRO* getZip(); | 
|  |  | 
|  | Asset* getResourceTableAsset(); | 
|  | Asset* setResourceTableAsset(Asset* asset); | 
|  |  | 
|  | ResTable* getResourceTable(); | 
|  | ResTable* setResourceTable(ResTable* res); | 
|  |  | 
|  | bool isUpToDate(); | 
|  |  | 
|  | protected: | 
|  | ~SharedZip(); | 
|  |  | 
|  | private: | 
|  | SharedZip(const String8& path, time_t modWhen); | 
|  | SharedZip(); // <-- not implemented | 
|  |  | 
|  | String8 mPath; | 
|  | ZipFileRO* mZipFile; | 
|  | time_t mModWhen; | 
|  |  | 
|  | Asset* mResourceTableAsset; | 
|  | ResTable* mResourceTable; | 
|  |  | 
|  | static Mutex gLock; | 
|  | static DefaultKeyedVector<String8, wp<SharedZip> > gOpen; | 
|  | }; | 
|  |  | 
|  | /* | 
|  | * Manage a set of Zip files.  For each file we need a pointer to the | 
|  | * ZipFile and a time_t with the file's modification date. | 
|  | * | 
|  | * We currently only have two zip files (current app, "common" app). | 
|  | * (This was originally written for 8, based on app/locale/vendor.) | 
|  | */ | 
|  | class ZipSet { | 
|  | public: | 
|  | ZipSet(void); | 
|  | ~ZipSet(void); | 
|  |  | 
|  | /* | 
|  | * Return a ZipFileRO structure for a ZipFileRO with the specified | 
|  | * parameters. | 
|  | */ | 
|  | ZipFileRO* getZip(const String8& path); | 
|  |  | 
|  | Asset* getZipResourceTableAsset(const String8& path); | 
|  | Asset* setZipResourceTableAsset(const String8& path, Asset* asset); | 
|  |  | 
|  | ResTable* getZipResourceTable(const String8& path); | 
|  | ResTable* setZipResourceTable(const String8& path, ResTable* res); | 
|  |  | 
|  | // generate path, e.g. "common/en-US-noogle.zip" | 
|  | static String8 getPathName(const char* path); | 
|  |  | 
|  | bool isUpToDate(); | 
|  |  | 
|  | private: | 
|  | void closeZip(int idx); | 
|  |  | 
|  | int getIndex(const String8& zip) const; | 
|  | mutable Vector<String8> mZipPath; | 
|  | mutable Vector<sp<SharedZip> > mZipFile; | 
|  | }; | 
|  |  | 
|  | // Protect all internal state. | 
|  | mutable Mutex   mLock; | 
|  |  | 
|  | ZipSet          mZipSet; | 
|  |  | 
|  | Vector<asset_path> mAssetPaths; | 
|  | char*           mLocale; | 
|  | char*           mVendor; | 
|  |  | 
|  | mutable ResTable* mResources; | 
|  | ResTable_config* mConfig; | 
|  |  | 
|  | /* | 
|  | * Cached data for "loose" files.  This lets us avoid poking at the | 
|  | * filesystem when searching for loose assets.  Each entry is the | 
|  | * "extended partial" path, e.g. "default/default/foo/bar.txt".  The | 
|  | * full set of files is present, including ".EXCLUDE" entries. | 
|  | * | 
|  | * We do not cache directory names.  We don't retain the ".gz", | 
|  | * because to our clients "foo" and "foo.gz" both look like "foo". | 
|  | */ | 
|  | CacheMode       mCacheMode;         // is the cache enabled? | 
|  | bool            mCacheValid;        // clear when locale or vendor changes | 
|  | SortedVector<AssetDir::FileInfo> mCache; | 
|  | }; | 
|  |  | 
|  | }; // namespace android | 
|  |  | 
|  | #endif // __LIBS_ASSETMANAGER_H |