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