| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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 |  | 
| Christopher Tate | 9373680 | 2010-07-12 18:21:36 -0700 | [diff] [blame] | 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 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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 |  */ | 
| Christopher Tate | 9373680 | 2010-07-12 18:21:36 -0700 | [diff] [blame] | 69 | class AssetManager : public AAssetManager { | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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 |  | 
| Dianne Hackborn | c3ef3ae | 2010-08-04 11:12:40 -0700 | [diff] [blame] | 132 |     void getConfiguration(ResTable_config* outConfig) const; | 
 | 133 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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 |     /* | 
| Dianne Hackborn | 7a57985 | 2009-05-18 15:22:00 -0700 | [diff] [blame] | 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 |     /* | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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; | 
| MÃ¥rten Kongstad | 5f29c87 | 2011-03-17 14:13:41 +0100 | [diff] [blame] | 225 |         String8 idmap; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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 |  | 
| MÃ¥rten Kongstad | 5f29c87 | 2011-03-17 14:13:41 +0100 | [diff] [blame] | 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 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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 |  | 
| Dianne Hackborn | 0f253efb | 2009-07-06 11:07:40 -0700 | [diff] [blame] | 285 |         ResTable* getResourceTable(); | 
 | 286 |         ResTable* setResourceTable(ResTable* res); | 
 | 287 |          | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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; | 
| Dianne Hackborn | 0f253efb | 2009-07-06 11:07:40 -0700 | [diff] [blame] | 302 |         ResTable* mResourceTable; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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 |  | 
| Dianne Hackborn | 0f253efb | 2009-07-06 11:07:40 -0700 | [diff] [blame] | 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); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 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 |