375 lines
13 KiB
C
375 lines
13 KiB
C
|
/*
|
||
|
* Copyright (C) 2006 The Android Open Source Project
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
|
||
|
//
|
||
|
// Asset management class. AssetManager objects are thread-safe.
|
||
|
//
|
||
|
#ifndef __LIBS_ASSETMANAGER_H
|
||
|
#define __LIBS_ASSETMANAGER_H
|
||
|
|
||
|
#include <androidfw/Asset.h>
|
||
|
#include <androidfw/AssetDir.h>
|
||
|
#include <androidfw/ZipFileRO.h>
|
||
|
#include <utils/KeyedVector.h>
|
||
|
#include <utils/SortedVector.h>
|
||
|
#include <utils/String16.h>
|
||
|
#include <utils/String8.h>
|
||
|
#include <utils/threads.h>
|
||
|
#include <utils/Vector.h>
|
||
|
|
||
|
/*
|
||
|
* Native-app access is via the opaque typedef struct AAssetManager in the C namespace.
|
||
|
*/
|
||
|
#ifdef __cplusplus
|
||
|
extern "C" {
|
||
|
#endif
|
||
|
|
||
|
struct AAssetManager { };
|
||
|
|
||
|
#ifdef __cplusplus
|
||
|
};
|
||
|
#endif
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Now the proper C++ android-namespace definitions
|
||
|
*/
|
||
|
|
||
|
namespace android {
|
||
|
|
||
|
class Asset; // fwd decl for things that include Asset.h first
|
||
|
class ResTable;
|
||
|
struct ResTable_config;
|
||
|
|
||
|
/*
|
||
|
* Every application that uses assets needs one instance of this. A
|
||
|
* single instance may be shared across multiple threads, and a single
|
||
|
* thread may have more than one instance (the latter is discouraged).
|
||
|
*
|
||
|
* The purpose of the AssetManager is to create Asset objects. To do
|
||
|
* this efficiently it may cache information about the locations of
|
||
|
* files it has seen. This can be controlled with the "cacheMode"
|
||
|
* argument.
|
||
|
*
|
||
|
* The asset hierarchy may be examined like a filesystem, using
|
||
|
* AssetDir objects to peruse a single directory.
|
||
|
*/
|
||
|
class AssetManager : public AAssetManager {
|
||
|
public:
|
||
|
typedef enum CacheMode {
|
||
|
CACHE_UNKNOWN = 0,
|
||
|
CACHE_OFF, // don't try to cache file locations
|
||
|
CACHE_DEFER, // construct cache as pieces are needed
|
||
|
//CACHE_SCAN, // scan full(!) asset hierarchy at init() time
|
||
|
} CacheMode;
|
||
|
|
||
|
AssetManager(CacheMode cacheMode = CACHE_OFF);
|
||
|
virtual ~AssetManager(void);
|
||
|
|
||
|
static int32_t getGlobalCount();
|
||
|
|
||
|
/*
|
||
|
* Add a new source for assets. This can be called multiple times to
|
||
|
* look in multiple places for assets. It can be either a directory (for
|
||
|
* finding assets as raw files on the disk) or a ZIP file. This newly
|
||
|
* added asset path will be examined first when searching for assets,
|
||
|
* before any that were previously added.
|
||
|
*
|
||
|
* Returns "true" on success, "false" on failure. If 'cookie' is non-NULL,
|
||
|
* then on success, *cookie is set to the value corresponding to the
|
||
|
* newly-added asset source.
|
||
|
*/
|
||
|
bool addAssetPath(const String8& path, void** cookie);
|
||
|
|
||
|
/*
|
||
|
* Convenience for adding the standard system assets. Uses the
|
||
|
* ANDROID_ROOT environment variable to find them.
|
||
|
*/
|
||
|
bool addDefaultAssets();
|
||
|
|
||
|
/*
|
||
|
* Iterate over the asset paths in this manager. (Previously
|
||
|
* added via addAssetPath() and addDefaultAssets().) On first call,
|
||
|
* 'cookie' must be NULL, resulting in the first cookie being returned.
|
||
|
* Each next cookie will be returned there-after, until NULL indicating
|
||
|
* the end has been reached.
|
||
|
*/
|
||
|
void* nextAssetPath(void* cookie) const;
|
||
|
|
||
|
/*
|
||
|
* Return an asset path in the manager. 'which' must be between 0 and
|
||
|
* countAssetPaths().
|
||
|
*/
|
||
|
String8 getAssetPath(void* cookie) const;
|
||
|
|
||
|
/*
|
||
|
* Set the current locale and vendor. The locale can change during
|
||
|
* the lifetime of an AssetManager if the user updates the device's
|
||
|
* language setting. The vendor is less likely to change.
|
||
|
*
|
||
|
* Pass in NULL to indicate no preference.
|
||
|
*/
|
||
|
void setLocale(const char* locale);
|
||
|
void setVendor(const char* vendor);
|
||
|
|
||
|
/*
|
||
|
* Choose screen orientation for resources values returned.
|
||
|
*/
|
||
|
void setConfiguration(const ResTable_config& config, const char* locale = NULL);
|
||
|
|
||
|
void getConfiguration(ResTable_config* outConfig) const;
|
||
|
|
||
|
typedef Asset::AccessMode AccessMode; // typing shortcut
|
||
|
|
||
|
/*
|
||
|
* Open an asset.
|
||
|
*
|
||
|
* This will search through locale-specific and vendor-specific
|
||
|
* directories and packages to find the file.
|
||
|
*
|
||
|
* The object returned does not depend on the AssetManager. It should
|
||
|
* be freed by calling Asset::close().
|
||
|
*/
|
||
|
Asset* open(const char* fileName, AccessMode mode);
|
||
|
|
||
|
/*
|
||
|
* Open a non-asset file as an asset.
|
||
|
*
|
||
|
* This is for opening files that are included in an asset package
|
||
|
* but aren't assets. These sit outside the usual "locale/vendor"
|
||
|
* path hierarchy, and will not be seen by "AssetDir" or included
|
||
|
* in our filename cache.
|
||
|
*/
|
||
|
Asset* openNonAsset(const char* fileName, AccessMode mode);
|
||
|
|
||
|
/*
|
||
|
* Explicit non-asset file. The file explicitly named by the cookie (the
|
||
|
* resource set to look in) and fileName will be opened and returned.
|
||
|
*/
|
||
|
Asset* openNonAsset(void* cookie, const char* fileName, AccessMode mode);
|
||
|
|
||
|
/*
|
||
|
* Open a directory within the asset hierarchy.
|
||
|
*
|
||
|
* The contents of the directory are an amalgam of vendor-specific,
|
||
|
* locale-specific, and generic assets stored loosely or in asset
|
||
|
* packages. Depending on the cache setting and previous accesses,
|
||
|
* this call may incur significant disk overhead.
|
||
|
*
|
||
|
* To open the top-level directory, pass in "".
|
||
|
*/
|
||
|
AssetDir* openDir(const char* dirName);
|
||
|
|
||
|
/*
|
||
|
* Open a directory within a particular path of the asset manager.
|
||
|
*
|
||
|
* The contents of the directory are an amalgam of vendor-specific,
|
||
|
* locale-specific, and generic assets stored loosely or in asset
|
||
|
* packages. Depending on the cache setting and previous accesses,
|
||
|
* this call may incur significant disk overhead.
|
||
|
*
|
||
|
* To open the top-level directory, pass in "".
|
||
|
*/
|
||
|
AssetDir* openNonAssetDir(void* cookie, const char* dirName);
|
||
|
|
||
|
/*
|
||
|
* Get the type of a file in the asset hierarchy. They will either
|
||
|
* be "regular" or "directory". [Currently only works for "regular".]
|
||
|
*
|
||
|
* Can also be used as a quick test for existence of a file.
|
||
|
*/
|
||
|
FileType getFileType(const char* fileName);
|
||
|
|
||
|
/*
|
||
|
* Return the complete resource table to find things in the package.
|
||
|
*/
|
||
|
const ResTable& getResources(bool required = true) const;
|
||
|
|
||
|
/*
|
||
|
* Discard cached filename information. This only needs to be called
|
||
|
* if somebody has updated the set of "loose" files, and we want to
|
||
|
* discard our cached notion of what's where.
|
||
|
*/
|
||
|
void purge(void) { purgeFileNameCacheLocked(); }
|
||
|
|
||
|
/*
|
||
|
* Return true if the files this AssetManager references are all
|
||
|
* up-to-date (have not been changed since it was created). If false
|
||
|
* is returned, you will need to create a new AssetManager to get
|
||
|
* the current data.
|
||
|
*/
|
||
|
bool isUpToDate();
|
||
|
|
||
|
/**
|
||
|
* Get the known locales for this asset manager object.
|
||
|
*/
|
||
|
void getLocales(Vector<String8>* locales) const;
|
||
|
|
||
|
private:
|
||
|
struct asset_path
|
||
|
{
|
||
|
String8 path;
|
||
|
FileType type;
|
||
|
String8 idmap;
|
||
|
};
|
||
|
|
||
|
Asset* openInPathLocked(const char* fileName, AccessMode mode,
|
||
|
const asset_path& path);
|
||
|
Asset* openNonAssetInPathLocked(const char* fileName, AccessMode mode,
|
||
|
const asset_path& path);
|
||
|
Asset* openInLocaleVendorLocked(const char* fileName, AccessMode mode,
|
||
|
const asset_path& path, const char* locale, const char* vendor);
|
||
|
String8 createPathNameLocked(const asset_path& path, const char* locale,
|
||
|
const char* vendor);
|
||
|
String8 createPathNameLocked(const asset_path& path, const char* rootDir);
|
||
|
String8 createZipSourceNameLocked(const String8& zipFileName,
|
||
|
const String8& dirName, const String8& fileName);
|
||
|
|
||
|
ZipFileRO* getZipFileLocked(const asset_path& path);
|
||
|
Asset* openAssetFromFileLocked(const String8& fileName, AccessMode mode);
|
||
|
Asset* openAssetFromZipLocked(const ZipFileRO* pZipFile,
|
||
|
const ZipEntryRO entry, AccessMode mode, const String8& entryName);
|
||
|
|
||
|
bool scanAndMergeDirLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo,
|
||
|
const asset_path& path, const char* rootDir, const char* dirName);
|
||
|
SortedVector<AssetDir::FileInfo>* scanDirLocked(const String8& path);
|
||
|
bool scanAndMergeZipLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo,
|
||
|
const asset_path& path, const char* rootDir, const char* dirName);
|
||
|
void mergeInfoLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo,
|
||
|
const SortedVector<AssetDir::FileInfo>* pContents);
|
||
|
|
||
|
void loadFileNameCacheLocked(void);
|
||
|
void fncScanLocked(SortedVector<AssetDir::FileInfo>* pMergedInfo,
|
||
|
const char* dirName);
|
||
|
bool fncScanAndMergeDirLocked(
|
||
|
SortedVector<AssetDir::FileInfo>* pMergedInfo,
|
||
|
const asset_path& path, const char* locale, const char* vendor,
|
||
|
const char* dirName);
|
||
|
void purgeFileNameCacheLocked(void);
|
||
|
|
||
|
const ResTable* getResTable(bool required = true) const;
|
||
|
void setLocaleLocked(const char* locale);
|
||
|
void updateResourceParamsLocked() const;
|
||
|
|
||
|
bool createIdmapFileLocked(const String8& originalPath, const String8& overlayPath,
|
||
|
const String8& idmapPath);
|
||
|
|
||
|
bool isIdmapStaleLocked(const String8& originalPath, const String8& overlayPath,
|
||
|
const String8& idmapPath);
|
||
|
|
||
|
Asset* openIdmapLocked(const struct asset_path& ap) const;
|
||
|
|
||
|
bool getZipEntryCrcLocked(const String8& zipPath, const char* entryFilename, uint32_t* pCrc);
|
||
|
|
||
|
class SharedZip : public RefBase {
|
||
|
public:
|
||
|
static sp<SharedZip> get(const String8& path);
|
||
|
|
||
|
ZipFileRO* getZip();
|
||
|
|
||
|
Asset* getResourceTableAsset();
|
||
|
Asset* setResourceTableAsset(Asset* asset);
|
||
|
|
||
|
ResTable* getResourceTable();
|
||
|
ResTable* setResourceTable(ResTable* res);
|
||
|
|
||
|
bool isUpToDate();
|
||
|
|
||
|
protected:
|
||
|
~SharedZip();
|
||
|
|
||
|
private:
|
||
|
SharedZip(const String8& path, time_t modWhen);
|
||
|
SharedZip(); // <-- not implemented
|
||
|
|
||
|
String8 mPath;
|
||
|
ZipFileRO* mZipFile;
|
||
|
time_t mModWhen;
|
||
|
|
||
|
Asset* mResourceTableAsset;
|
||
|
ResTable* mResourceTable;
|
||
|
|
||
|
static Mutex gLock;
|
||
|
static DefaultKeyedVector<String8, wp<SharedZip> > gOpen;
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
* Manage a set of Zip files. For each file we need a pointer to the
|
||
|
* ZipFile and a time_t with the file's modification date.
|
||
|
*
|
||
|
* We currently only have two zip files (current app, "common" app).
|
||
|
* (This was originally written for 8, based on app/locale/vendor.)
|
||
|
*/
|
||
|
class ZipSet {
|
||
|
public:
|
||
|
ZipSet(void);
|
||
|
~ZipSet(void);
|
||
|
|
||
|
/*
|
||
|
* Return a ZipFileRO structure for a ZipFileRO with the specified
|
||
|
* parameters.
|
||
|
*/
|
||
|
ZipFileRO* getZip(const String8& path);
|
||
|
|
||
|
Asset* getZipResourceTableAsset(const String8& path);
|
||
|
Asset* setZipResourceTableAsset(const String8& path, Asset* asset);
|
||
|
|
||
|
ResTable* getZipResourceTable(const String8& path);
|
||
|
ResTable* setZipResourceTable(const String8& path, ResTable* res);
|
||
|
|
||
|
// generate path, e.g. "common/en-US-noogle.zip"
|
||
|
static String8 getPathName(const char* path);
|
||
|
|
||
|
bool isUpToDate();
|
||
|
|
||
|
private:
|
||
|
void closeZip(int idx);
|
||
|
|
||
|
int getIndex(const String8& zip) const;
|
||
|
mutable Vector<String8> mZipPath;
|
||
|
mutable Vector<sp<SharedZip> > mZipFile;
|
||
|
};
|
||
|
|
||
|
// Protect all internal state.
|
||
|
mutable Mutex mLock;
|
||
|
|
||
|
ZipSet mZipSet;
|
||
|
|
||
|
Vector<asset_path> mAssetPaths;
|
||
|
char* mLocale;
|
||
|
char* mVendor;
|
||
|
|
||
|
mutable ResTable* mResources;
|
||
|
ResTable_config* mConfig;
|
||
|
|
||
|
/*
|
||
|
* Cached data for "loose" files. This lets us avoid poking at the
|
||
|
* filesystem when searching for loose assets. Each entry is the
|
||
|
* "extended partial" path, e.g. "default/default/foo/bar.txt". The
|
||
|
* full set of files is present, including ".EXCLUDE" entries.
|
||
|
*
|
||
|
* We do not cache directory names. We don't retain the ".gz",
|
||
|
* because to our clients "foo" and "foo.gz" both look like "foo".
|
||
|
*/
|
||
|
CacheMode mCacheMode; // is the cache enabled?
|
||
|
bool mCacheValid; // clear when locale or vendor changes
|
||
|
SortedVector<AssetDir::FileInfo> mCache;
|
||
|
};
|
||
|
|
||
|
}; // namespace android
|
||
|
|
||
|
#endif // __LIBS_ASSETMANAGER_H
|