| /* | 
 |  * 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; | 
 |     }; | 
 |  | 
 |     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; | 
 |  | 
 |     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 |