Home | History | Annotate | Download | only in utils
      1 /*
      2  * Copyright (C) 2006 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 //
     18 // Asset management class.  AssetManager objects are thread-safe.
     19 //
     20 #ifndef __LIBS_ASSETMANAGER_H
     21 #define __LIBS_ASSETMANAGER_H
     22 
     23 #include <utils/Asset.h>
     24 #include <utils/AssetDir.h>
     25 #include <utils/KeyedVector.h>
     26 #include <utils/String8.h>
     27 #include <utils/Vector.h>
     28 #include <utils/String16.h>
     29 #include <utils/ZipFileRO.h>
     30 #include <utils/threads.h>
     31 
     32 /*
     33  * Native-app access is via the opaque typedef struct AAssetManager in the C namespace.
     34  */
     35 #ifdef __cplusplus
     36 extern "C" {
     37 #endif
     38 
     39 struct AAssetManager { };
     40 
     41 #ifdef __cplusplus
     42 };
     43 #endif
     44 
     45 
     46 /*
     47  * Now the proper C++ android-namespace definitions
     48  */
     49 
     50 namespace android {
     51 
     52 class Asset;        // fwd decl for things that include Asset.h first
     53 class ResTable;
     54 struct ResTable_config;
     55 
     56 /*
     57  * Every application that uses assets needs one instance of this.  A
     58  * single instance may be shared across multiple threads, and a single
     59  * thread may have more than one instance (the latter is discouraged).
     60  *
     61  * The purpose of the AssetManager is to create Asset objects.  To do
     62  * this efficiently it may cache information about the locations of
     63  * files it has seen.  This can be controlled with the "cacheMode"
     64  * argument.
     65  *
     66  * The asset hierarchy may be examined like a filesystem, using
     67  * AssetDir objects to peruse a single directory.
     68  */
     69 class AssetManager : public AAssetManager {
     70 public:
     71     typedef enum CacheMode {
     72         CACHE_UNKNOWN = 0,
     73         CACHE_OFF,          // don't try to cache file locations
     74         CACHE_DEFER,        // construct cache as pieces are needed
     75         //CACHE_SCAN,         // scan full(!) asset hierarchy at init() time
     76     } CacheMode;
     77 
     78     AssetManager(CacheMode cacheMode = CACHE_OFF);
     79     virtual ~AssetManager(void);
     80 
     81     static int32_t getGlobalCount();
     82 
     83     /*
     84      * Add a new source for assets.  This can be called multiple times to
     85      * look in multiple places for assets.  It can be either a directory (for
     86      * finding assets as raw files on the disk) or a ZIP file.  This newly
     87      * added asset path will be examined first when searching for assets,
     88      * before any that were previously added.
     89      *
     90      * Returns "true" on success, "false" on failure.  If 'cookie' is non-NULL,
     91      * then on success, *cookie is set to the value corresponding to the
     92      * newly-added asset source.
     93      */
     94     bool addAssetPath(const String8& path, void** cookie);
     95 
     96     /*
     97      * Convenience for adding the standard system assets.  Uses the
     98      * ANDROID_ROOT environment variable to find them.
     99      */
    100     bool addDefaultAssets();
    101 
    102     /*
    103      * Iterate over the asset paths in this manager.  (Previously
    104      * added via addAssetPath() and addDefaultAssets().)  On first call,
    105      * 'cookie' must be NULL, resulting in the first cookie being returned.
    106      * Each next cookie will be returned there-after, until NULL indicating
    107      * the end has been reached.
    108      */
    109     void* nextAssetPath(void* cookie) const;
    110 
    111     /*
    112      * Return an asset path in the manager.  'which' must be between 0 and
    113      * countAssetPaths().
    114      */
    115     String8 getAssetPath(void* cookie) const;
    116 
    117     /*
    118      * Set the current locale and vendor.  The locale can change during
    119      * the lifetime of an AssetManager if the user updates the device's
    120      * language setting.  The vendor is less likely to change.
    121      *
    122      * Pass in NULL to indicate no preference.
    123      */
    124     void setLocale(const char* locale);
    125     void setVendor(const char* vendor);
    126 
    127     /*
    128      * Choose screen orientation for resources values returned.
    129      */
    130     void setConfiguration(const ResTable_config& config, const char* locale = NULL);
    131 
    132     void getConfiguration(ResTable_config* outConfig) const;
    133 
    134     typedef Asset::AccessMode AccessMode;       // typing shortcut
    135 
    136     /*
    137      * Open an asset.
    138      *
    139      * This will search through locale-specific and vendor-specific
    140      * directories and packages to find the file.
    141      *
    142      * The object returned does not depend on the AssetManager.  It should
    143      * be freed by calling Asset::close().
    144      */
    145     Asset* open(const char* fileName, AccessMode mode);
    146 
    147     /*
    148      * Open a non-asset file as an asset.
    149      *
    150      * This is for opening files that are included in an asset package
    151      * but aren't assets.  These sit outside the usual "locale/vendor"
    152      * path hierarchy, and will not be seen by "AssetDir" or included
    153      * in our filename cache.
    154      */
    155     Asset* openNonAsset(const char* fileName, AccessMode mode);
    156 
    157     /*
    158      * Explicit non-asset file.  The file explicitly named by the cookie (the
    159      * resource set to look in) and fileName will be opened and returned.
    160      */
    161     Asset* openNonAsset(void* cookie, const char* fileName, AccessMode mode);
    162 
    163     /*
    164      * Open a directory within the asset hierarchy.
    165      *
    166      * The contents of the directory are an amalgam of vendor-specific,
    167      * locale-specific, and generic assets stored loosely or in asset
    168      * packages.  Depending on the cache setting and previous accesses,
    169      * this call may incur significant disk overhead.
    170      *
    171      * To open the top-level directory, pass in "".
    172      */
    173     AssetDir* openDir(const char* dirName);
    174 
    175     /*
    176      * Open a directory within a particular path of the asset manager.
    177      *
    178      * The contents of the directory are an amalgam of vendor-specific,
    179      * locale-specific, and generic assets stored loosely or in asset
    180      * packages.  Depending on the cache setting and previous accesses,
    181      * this call may incur significant disk overhead.
    182      *
    183      * To open the top-level directory, pass in "".
    184      */
    185     AssetDir* openNonAssetDir(void* cookie, const char* dirName);
    186 
    187     /*
    188      * Get the type of a file in the asset hierarchy.  They will either
    189      * be "regular" or "directory".  [Currently only works for "regular".]
    190      *
    191      * Can also be used as a quick test for existence of a file.
    192      */
    193     FileType getFileType(const char* fileName);
    194 
    195     /*
    196      * Return the complete resource table to find things in the package.
    197      */
    198     const ResTable& getResources(bool required = true) const;
    199 
    200     /*
    201      * Discard cached filename information.  This only needs to be called
    202      * if somebody has updated the set of "loose" files, and we want to
    203      * discard our cached notion of what's where.
    204      */
    205     void purge(void) { purgeFileNameCacheLocked(); }
    206 
    207     /*
    208      * Return true if the files this AssetManager references are all
    209      * up-to-date (have not been changed since it was created).  If false
    210      * is returned, you will need to create a new AssetManager to get
    211      * the current data.
    212      */
    213     bool isUpToDate();
    214 
    215     /**
    216      * Get the known locales for this asset manager object.
    217      */
    218     void getLocales(Vector<String8>* locales) const;
    219 
    220 private:
    221     struct asset_path
    222     {
    223         String8 path;
    224         FileType type;
    225         String8 idmap;
    226     };
    227 
    228     Asset* openInPathLocked(const char* fileName, AccessMode mode,
    229         const asset_path& path);
    230     Asset* openNonAssetInPathLocked(const char* fileName, AccessMode mode,
    231         const asset_path& path);
    232     Asset* openInLocaleVendorLocked(const char* fileName, AccessMode mode,
    233         const asset_path& path, const char* locale, const char* vendor);
    234     String8 createPathNameLocked(const asset_path& path, const char* locale,
    235         const char* vendor);
    236     String8 createPathNameLocked(const asset_path& path, const char* rootDir);
    237     String8 createZipSourceNameLocked(const String8& zipFileName,
    238         const String8& dirName, const String8& fileName);
    239 
    240     ZipFileRO* getZipFileLocked(const asset_path& path);
    241     Asset* openAssetFromFileLocked(const String8& fileName, AccessMode mode);
    242     Asset* openAssetFromZipLocked(const ZipFileRO* pZipFile,
    243         const ZipEntryRO entry, AccessMode mode, const String8& entryName);
    244 
    245     bool scanAndMergeDirLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo,
    246         const asset_path& path, const char* rootDir, const char* dirName);
    247     SortedVector<AssetDir::FileInfo>* scanDirLocked(const String8& path);
    248     bool scanAndMergeZipLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo,
    249         const asset_path& path, const char* rootDir, const char* dirName);
    250     void mergeInfoLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo,
    251         const SortedVector<AssetDir::FileInfo>* pContents);
    252 
    253     void loadFileNameCacheLocked(void);
    254     void fncScanLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo,
    255         const char* dirName);
    256     bool fncScanAndMergeDirLocked(
    257         SortedVector<AssetDir::FileInfo>* pMergedInfo,
    258         const asset_path& path, const char* locale, const char* vendor,
    259         const char* dirName);
    260     void purgeFileNameCacheLocked(void);
    261 
    262     const ResTable* getResTable(bool required = true) const;
    263     void setLocaleLocked(const char* locale);
    264     void updateResourceParamsLocked() const;
    265 
    266     bool createIdmapFileLocked(const String8& originalPath, const String8& overlayPath,
    267                                const String8& idmapPath);
    268 
    269     bool isIdmapStaleLocked(const String8& originalPath, const String8& overlayPath,
    270                             const String8& idmapPath);
    271 
    272     Asset* openIdmapLocked(const struct asset_path& ap) const;
    273 
    274     bool getZipEntryCrcLocked(const String8& zipPath, const char* entryFilename, uint32_t* pCrc);
    275 
    276     class SharedZip : public RefBase {
    277     public:
    278         static sp<SharedZip> get(const String8& path);
    279 
    280         ZipFileRO* getZip();
    281 
    282         Asset* getResourceTableAsset();
    283         Asset* setResourceTableAsset(Asset* asset);
    284 
    285         ResTable* getResourceTable();
    286         ResTable* setResourceTable(ResTable* res);
    287 
    288         bool isUpToDate();
    289 
    290     protected:
    291         ~SharedZip();
    292 
    293     private:
    294         SharedZip(const String8& path, time_t modWhen);
    295         SharedZip(); // <-- not implemented
    296 
    297         String8 mPath;
    298         ZipFileRO* mZipFile;
    299         time_t mModWhen;
    300 
    301         Asset* mResourceTableAsset;
    302         ResTable* mResourceTable;
    303 
    304         static Mutex gLock;
    305         static DefaultKeyedVector<String8, wp<SharedZip> > gOpen;
    306     };
    307 
    308     /*
    309      * Manage a set of Zip files.  For each file we need a pointer to the
    310      * ZipFile and a time_t with the file's modification date.
    311      *
    312      * We currently only have two zip files (current app, "common" app).
    313      * (This was originally written for 8, based on app/locale/vendor.)
    314      */
    315     class ZipSet {
    316     public:
    317         ZipSet(void);
    318         ~ZipSet(void);
    319 
    320         /*
    321          * Return a ZipFileRO structure for a ZipFileRO with the specified
    322          * parameters.
    323          */
    324         ZipFileRO* getZip(const String8& path);
    325 
    326         Asset* getZipResourceTableAsset(const String8& path);
    327         Asset* setZipResourceTableAsset(const String8& path, Asset* asset);
    328 
    329         ResTable* getZipResourceTable(const String8& path);
    330         ResTable* setZipResourceTable(const String8& path, ResTable* res);
    331 
    332         // generate path, e.g. "common/en-US-noogle.zip"
    333         static String8 getPathName(const char* path);
    334 
    335         bool isUpToDate();
    336 
    337     private:
    338         void closeZip(int idx);
    339 
    340         int getIndex(const String8& zip) const;
    341         mutable Vector<String8> mZipPath;
    342         mutable Vector<sp<SharedZip> > mZipFile;
    343     };
    344 
    345     // Protect all internal state.
    346     mutable Mutex   mLock;
    347 
    348     ZipSet          mZipSet;
    349 
    350     Vector<asset_path> mAssetPaths;
    351     char*           mLocale;
    352     char*           mVendor;
    353 
    354     mutable ResTable* mResources;
    355     ResTable_config* mConfig;
    356 
    357     /*
    358      * Cached data for "loose" files.  This lets us avoid poking at the
    359      * filesystem when searching for loose assets.  Each entry is the
    360      * "extended partial" path, e.g. "default/default/foo/bar.txt".  The
    361      * full set of files is present, including ".EXCLUDE" entries.
    362      *
    363      * We do not cache directory names.  We don't retain the ".gz",
    364      * because to our clients "foo" and "foo.gz" both look like "foo".
    365      */
    366     CacheMode       mCacheMode;         // is the cache enabled?
    367     bool            mCacheValid;        // clear when locale or vendor changes
    368     SortedVector<AssetDir::FileInfo> mCache;
    369 };
    370 
    371 }; // namespace android
    372 
    373 #endif // __LIBS_ASSETMANAGER_H
    374