• 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 <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      */
purge(void)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