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