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 struct AAssetManager { };
     37 
     38 /*
     39  * Now the proper C++ android-namespace definitions
     40  */
     41 
     42 namespace android {
     43 
     44 class Asset;        // fwd decl for things that include Asset.h first
     45 class ResTable;
     46 struct ResTable_config;
     47 
     48 /*
     49  * Every application that uses assets needs one instance of this.  A
     50  * single instance may be shared across multiple threads, and a single
     51  * thread may have more than one instance (the latter is discouraged).
     52  *
     53  * The purpose of the AssetManager is to create Asset objects.
     54  *
     55  * The asset hierarchy may be examined like a filesystem, using
     56  * AssetDir objects to peruse a single directory.
     57  */
     58 class AssetManager : public AAssetManager {
     59 public:
     60     static const char* RESOURCES_FILENAME;
     61     static const char* IDMAP_BIN;
     62     static const char* OVERLAY_DIR;
     63     static const char* PRODUCT_OVERLAY_DIR;
     64     /*
     65      * If OVERLAY_THEME_DIR_PROPERTY is set, search for runtime resource overlay
     66      * APKs in OVERLAY_DIR/<value of OVERLAY_THEME_DIR_PROPERTY> in addition to
     67      * OVERLAY_DIR.
     68      */
     69     static const char* OVERLAY_THEME_DIR_PROPERTY;
     70     static const char* TARGET_PACKAGE_NAME;
     71     static const char* TARGET_APK_PATH;
     72     static const char* IDMAP_DIR;
     73 
     74     AssetManager();
     75     virtual ~AssetManager(void);
     76 
     77     static int32_t getGlobalCount();
     78 
     79     /*
     80      * Add a new source for assets.  This can be called multiple times to
     81      * look in multiple places for assets.  It can be either a directory (for
     82      * finding assets as raw files on the disk) or a ZIP file.  This newly
     83      * added asset path will be examined first when searching for assets,
     84      * before any that were previously added, the assets are added as shared
     85      * library if appAsLib is true.
     86      *
     87      * Returns "true" on success, "false" on failure.  If 'cookie' is non-NULL,
     88      * then on success, *cookie is set to the value corresponding to the
     89      * newly-added asset source.
     90      */
     91     bool addAssetPath(const String8& path, int32_t* cookie,
     92         bool appAsLib=false, bool isSystemAsset=false);
     93     bool addOverlayPath(const String8& path, int32_t* cookie);
     94 
     95     /*
     96      * Add a new source for assets from an already open file descriptor.
     97      * This does not give full AssetManager functionality for these assets,
     98      * since the origin of the file is not known for purposes of sharing,
     99      * overlay resolution, and other features.  However it does allow you
    100      * to do simple access to the contents of the given fd as an apk file.
    101      *
    102      * Returns "true" on success, "false" on failure.  If 'cookie' is non-NULL,
    103      * then on success, *cookie is set to the value corresponding to the
    104      * newly-added asset source.
    105      */
    106     bool addAssetFd(int fd, const String8& debugPathName, int32_t* cookie,
    107         bool appAsLib=false, bool assume_ownership=true);
    108 
    109     /*
    110      * Convenience for adding the standard system assets.  Uses the
    111      * ANDROID_ROOT environment variable to find them.
    112      */
    113     bool addDefaultAssets();
    114 
    115     /*
    116      * Iterate over the asset paths in this manager.  (Previously
    117      * added via addAssetPath() and addDefaultAssets().)  On first call,
    118      * 'cookie' must be 0, resulting in the first cookie being returned.
    119      * Each next cookie will be returned there-after, until -1 indicating
    120      * the end has been reached.
    121      */
    122     int32_t nextAssetPath(const int32_t cookie) const;
    123 
    124     /*
    125      * Return an asset path in the manager.  'cookie' must be a non-negative value
    126      * previously returned from addAssetPath() or nextAssetPath().
    127      */
    128     String8 getAssetPath(const int32_t cookie) const;
    129 
    130     /*
    131      * Sets various device configuration parameters, like screen orientation, layout,
    132      * size, locale, etc.
    133      * The optional 'locale' string takes precedence over the locale within 'config'
    134      * and must be in bcp47 format.
    135      */
    136     void setConfiguration(const ResTable_config& config, const char* locale = NULL);
    137 
    138     void getConfiguration(ResTable_config* outConfig) const;
    139 
    140     typedef Asset::AccessMode AccessMode;       // typing shortcut
    141 
    142     /*
    143      * Open an asset.
    144      *
    145      * The object returned does not depend on the AssetManager.  It should
    146      * be freed by calling Asset::close().
    147      */
    148     Asset* open(const char* fileName, AccessMode mode);
    149 
    150     /*
    151      * Open a non-asset file as an asset.
    152      *
    153      * This is for opening files that are included in an asset package
    154      * but aren't assets.  These sit outside the usual "assets/"
    155      * path hierarchy, and will not be seen by "AssetDir".
    156      */
    157     Asset* openNonAsset(const char* fileName, AccessMode mode, int32_t* outCookie = NULL);
    158 
    159     /*
    160      * Explicit non-asset file.  The file explicitly named by the cookie (the
    161      * resource set to look in) and fileName will be opened and returned.
    162      */
    163     Asset* openNonAsset(const int32_t cookie, const char* fileName, AccessMode mode);
    164 
    165     /*
    166      * Open a directory within the asset hierarchy.
    167      *
    168      * To open the top-level directory, pass in "".
    169      */
    170     AssetDir* openDir(const char* dirName);
    171 
    172     /*
    173      * Open a directory within a particular path of the asset manager.
    174      *
    175      * To open the top-level directory, pass in "".
    176      */
    177     AssetDir* openNonAssetDir(const int32_t cookie, const char* dirName);
    178 
    179     /*
    180      * Get the type of a file in the asset hierarchy.  They will either
    181      * be "regular" or "directory".  [Currently only works for "regular".]
    182      *
    183      * Can also be used as a quick test for existence of a file.
    184      */
    185     FileType getFileType(const char* fileName);
    186 
    187     /*
    188      * Return the complete resource table to find things in the package.
    189      */
    190     const ResTable& getResources(bool required = true) const;
    191 
    192     /*
    193      * Return true if the files this AssetManager references are all
    194      * up-to-date (have not been changed since it was created).  If false
    195      * is returned, you will need to create a new AssetManager to get
    196      * the current data.
    197      */
    198     bool isUpToDate();
    199 
    200     /**
    201      * Get the known locales for this asset manager object.
    202      */
    203     void getLocales(Vector<String8>* locales, bool includeSystemLocales=true) const;
    204 
    205     /**
    206      * Generate idmap data to translate resources IDs between a package and a
    207      * corresponding overlay package.
    208      */
    209     bool createIdmap(const char* targetApkPath, const char* overlayApkPath,
    210         uint32_t targetCrc, uint32_t overlayCrc, uint32_t** outData, size_t* outSize);
    211 
    212 private:
    213     class SharedZip;
    214 
    215     struct asset_path
    216     {
    217         asset_path() : path(""), rawFd(-1), type(kFileTypeRegular), idmap(""),
    218                        isSystemOverlay(false), isSystemAsset(false), assumeOwnership(false) {}
    219         String8 path;
    220         int rawFd;
    221         FileType type;
    222         String8 idmap;
    223         bool isSystemOverlay;
    224         bool isSystemAsset;
    225         bool assumeOwnership;
    226         sp<SharedZip> zip;
    227     };
    228 
    229     Asset* openNonAssetInPathLocked(const char* fileName, AccessMode mode,
    230         asset_path& path);
    231     String8 createPathNameLocked(const asset_path& path, const char* rootDir);
    232     String8 createZipSourceNameLocked(const String8& zipFileName,
    233         const String8& dirName, const String8& fileName);
    234 
    235     ZipFileRO* getZipFileLocked(asset_path& path);
    236     Asset* openAssetFromFileLocked(const String8& fileName, AccessMode mode);
    237     Asset* openAssetFromZipLocked(const ZipFileRO* pZipFile,
    238         const ZipEntryRO entry, AccessMode mode, const String8& entryName);
    239 
    240     bool scanAndMergeDirLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo,
    241         const asset_path& path, const char* rootDir, const char* dirName);
    242     SortedVector<AssetDir::FileInfo>* scanDirLocked(const String8& path);
    243     bool scanAndMergeZipLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo,
    244         const asset_path& path, const char* rootDir, const char* dirName);
    245     void mergeInfoLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo,
    246         const SortedVector<AssetDir::FileInfo>* pContents);
    247 
    248     const ResTable* getResTable(bool required = true) const;
    249     void setLocaleLocked(const char* locale);
    250     void updateResourceParamsLocked() const;
    251     bool appendPathToResTable(asset_path& ap, bool appAsLib=false) const;
    252 
    253     Asset* openIdmapLocked(const struct asset_path& ap) const;
    254 
    255     void addSystemOverlays(const char* pathOverlaysList, const String8& targetPackagePath,
    256             ResTable* sharedRes, size_t offset) const;
    257 
    258     class SharedZip : public RefBase {
    259     public:
    260         static sp<SharedZip> get(const String8& path, bool createIfNotPresent = true);
    261         static sp<SharedZip> create(int fd, const String8& path);
    262 
    263         ZipFileRO* getZip();
    264 
    265         Asset* getResourceTableAsset();
    266         Asset* setResourceTableAsset(Asset* asset);
    267 
    268         ResTable* getResourceTable();
    269         ResTable* setResourceTable(ResTable* res);
    270 
    271         bool isUpToDate();
    272 
    273         void addOverlay(const asset_path& ap);
    274         bool getOverlay(size_t idx, asset_path* out) const;
    275 
    276     protected:
    277         ~SharedZip();
    278 
    279     private:
    280         SharedZip(const String8& path, time_t modWhen);
    281         SharedZip(int fd, const String8& path);
    282         SharedZip(); // <-- not implemented
    283 
    284         String8 mPath;
    285         ZipFileRO* mZipFile;
    286         time_t mModWhen;
    287 
    288         Asset* mResourceTableAsset;
    289         ResTable* mResourceTable;
    290 
    291         Vector<asset_path> mOverlays;
    292 
    293         static Mutex gLock;
    294         static DefaultKeyedVector<String8, wp<SharedZip> > gOpen;
    295     };
    296 
    297     /*
    298      * Manage a set of Zip files.  For each file we need a pointer to the
    299      * ZipFile and a time_t with the file's modification date.
    300      *
    301      * We currently only have two zip files (current app, "common" app).
    302      * (This was originally written for 8, based on app/locale/vendor.)
    303      */
    304     class ZipSet {
    305     public:
    306         ZipSet() = default;
    307         ~ZipSet();
    308 
    309         /*
    310          * Return a ZipFileRO structure for a ZipFileRO with the specified
    311          * parameters.
    312          */
    313         ZipFileRO* getZip(const String8& path);
    314 
    315         const sp<SharedZip> getSharedZip(const String8& path);
    316 
    317         Asset* getZipResourceTableAsset(const String8& path);
    318         Asset* setZipResourceTableAsset(const String8& path, Asset* asset);
    319 
    320         ResTable* getZipResourceTable(const String8& path);
    321         ResTable* setZipResourceTable(const String8& path, ResTable* res);
    322 
    323         // generate path, e.g. "common/en-US-noogle.zip"
    324         static String8 getPathName(const char* path);
    325 
    326         bool isUpToDate();
    327 
    328         void addOverlay(const String8& path, const asset_path& overlay);
    329         bool getOverlay(const String8& path, size_t idx, asset_path* out) const;
    330 
    331     private:
    332         void closeZip(int idx);
    333 
    334         int getIndex(const String8& zip) const;
    335         mutable Vector<String8> mZipPath;
    336         mutable Vector<sp<SharedZip> > mZipFile;
    337     };
    338 
    339     // Protect all internal state.
    340     mutable Mutex   mLock;
    341 
    342     ZipSet          mZipSet;
    343 
    344     Vector<asset_path> mAssetPaths;
    345     char*           mLocale;
    346 
    347     mutable ResTable* mResources;
    348     ResTable_config* mConfig;
    349 };
    350 
    351 }; // namespace android
    352 
    353 #endif // __LIBS_ASSETMANAGER_H
    354