• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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      */
purge(void)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