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 // Class providing access to a read-only asset. Asset objects are NOT 19 // thread-safe, and should not be shared across threads. 20 // 21 #ifndef __LIBS_ASSET_H 22 #define __LIBS_ASSET_H 23 24 #include <stdio.h> 25 #include <sys/types.h> 26 #include "FileMap.h" 27 #include "String8.h" 28 #include "Errors.h" 29 30 namespace android { 31 32 /* 33 * Instances of this class provide read-only operations on a byte stream. 34 * 35 * Access may be optimized for streaming, random, or whole buffer modes. All 36 * operations are supported regardless of how the file was opened, but some 37 * things will be less efficient. [pass that in??] 38 * 39 * "Asset" is the base class for all types of assets. The classes below 40 * provide most of the implementation. The AssetManager uses one of the 41 * static "create" functions defined here to create a new instance. 42 */ 43 class Asset { 44 public: 45 virtual ~Asset(void); 46 47 static int32_t getGlobalCount(); 48 static String8 getAssetAllocations(); 49 50 /* used when opening an asset */ 51 typedef enum AccessMode { 52 ACCESS_UNKNOWN = 0, 53 54 /* read chunks, and seek forward and backward */ 55 ACCESS_RANDOM, 56 57 /* read sequentially, with an occasional forward seek */ 58 ACCESS_STREAMING, 59 60 /* caller plans to ask for a read-only buffer with all data */ 61 ACCESS_BUFFER, 62 } AccessMode; 63 64 /* 65 * Read data from the current offset. Returns the actual number of 66 * bytes read, 0 on EOF, or -1 on error. 67 */ 68 virtual ssize_t read(void* buf, size_t count) = 0; 69 70 /* 71 * Seek to the specified offset. "whence" uses the same values as 72 * lseek/fseek. Returns the new position on success, or (off_t) -1 73 * on failure. 74 */ 75 virtual off_t seek(off_t offset, int whence) = 0; 76 77 /* 78 * Close the asset, freeing all associated resources. 79 */ 80 virtual void close(void) = 0; 81 82 /* 83 * Get a pointer to a buffer with the entire contents of the file. 84 */ 85 virtual const void* getBuffer(bool wordAligned) = 0; 86 87 /* 88 * Get the total amount of data that can be read. 89 */ 90 virtual off_t getLength(void) const = 0; 91 92 /* 93 * Get the total amount of data that can be read from the current position. 94 */ 95 virtual off_t getRemainingLength(void) const = 0; 96 97 /* 98 * Open a new file descriptor that can be used to read this asset. 99 * Returns -1 if you can not use the file descriptor (for example if the 100 * asset is compressed). 101 */ 102 virtual int openFileDescriptor(off_t* outStart, off_t* outLength) const = 0; 103 104 /* 105 * Return whether this asset's buffer is allocated in RAM (not mmapped). 106 * Note: not virtual so it is safe to call even when being destroyed. 107 */ isAllocated(void)108 virtual bool isAllocated(void) const { return false; } 109 110 /* 111 * Get a string identifying the asset's source. This might be a full 112 * path, it might be a colon-separated list of identifiers. 113 * 114 * This is NOT intended to be used for anything except debug output. 115 * DO NOT try to parse this or use it to open a file. 116 */ getAssetSource(void)117 const char* getAssetSource(void) const { return mAssetSource.string(); } 118 119 protected: 120 Asset(void); // constructor; only invoked indirectly 121 122 /* handle common seek() housekeeping */ 123 off_t handleSeek(off_t offset, int whence, off_t curPosn, off_t maxPosn); 124 125 /* set the asset source string */ setAssetSource(const String8 & path)126 void setAssetSource(const String8& path) { mAssetSource = path; } 127 getAccessMode(void)128 AccessMode getAccessMode(void) const { return mAccessMode; } 129 130 private: 131 /* these operations are not implemented */ 132 Asset(const Asset& src); 133 Asset& operator=(const Asset& src); 134 135 /* AssetManager needs access to our "create" functions */ 136 friend class AssetManager; 137 138 /* 139 * Create the asset from a named file on disk. 140 */ 141 static Asset* createFromFile(const char* fileName, AccessMode mode); 142 143 /* 144 * Create the asset from a named, compressed file on disk (e.g. ".gz"). 145 */ 146 static Asset* createFromCompressedFile(const char* fileName, 147 AccessMode mode); 148 149 #if 0 150 /* 151 * Create the asset from a segment of an open file. This will fail 152 * if "offset" and "length" don't fit within the bounds of the file. 153 * 154 * The asset takes ownership of the file descriptor. 155 */ 156 static Asset* createFromFileSegment(int fd, off_t offset, size_t length, 157 AccessMode mode); 158 159 /* 160 * Create from compressed data. "fd" should be seeked to the start of 161 * the compressed data. This could be inside a gzip file or part of a 162 * Zip archive. 163 * 164 * The asset takes ownership of the file descriptor. 165 * 166 * This may not verify the validity of the compressed data until first 167 * use. 168 */ 169 static Asset* createFromCompressedData(int fd, off_t offset, 170 int compressionMethod, size_t compressedLength, 171 size_t uncompressedLength, AccessMode mode); 172 #endif 173 174 /* 175 * Create the asset from a memory-mapped file segment. 176 * 177 * The asset takes ownership of the FileMap. 178 */ 179 static Asset* createFromUncompressedMap(FileMap* dataMap, AccessMode mode); 180 181 /* 182 * Create the asset from a memory-mapped file segment with compressed 183 * data. "method" is a Zip archive compression method constant. 184 * 185 * The asset takes ownership of the FileMap. 186 */ 187 static Asset* createFromCompressedMap(FileMap* dataMap, int method, 188 size_t uncompressedLen, AccessMode mode); 189 190 191 /* 192 * Create from a reference-counted chunk of shared memory. 193 */ 194 // TODO 195 196 AccessMode mAccessMode; // how the asset was opened 197 String8 mAssetSource; // debug string 198 199 Asset* mNext; // linked list. 200 Asset* mPrev; 201 }; 202 203 204 /* 205 * =========================================================================== 206 * 207 * Innards follow. Do not use these classes directly. 208 */ 209 210 /* 211 * An asset based on an uncompressed file on disk. It may encompass the 212 * entire file or just a piece of it. Access is through fread/fseek. 213 */ 214 class _FileAsset : public Asset { 215 public: 216 _FileAsset(void); 217 virtual ~_FileAsset(void); 218 219 /* 220 * Use a piece of an already-open file. 221 * 222 * On success, the object takes ownership of "fd". 223 */ 224 status_t openChunk(const char* fileName, int fd, off_t offset, size_t length); 225 226 /* 227 * Use a memory-mapped region. 228 * 229 * On success, the object takes ownership of "dataMap". 230 */ 231 status_t openChunk(FileMap* dataMap); 232 233 /* 234 * Standard Asset interfaces. 235 */ 236 virtual ssize_t read(void* buf, size_t count); 237 virtual off_t seek(off_t offset, int whence); 238 virtual void close(void); 239 virtual const void* getBuffer(bool wordAligned); getLength(void)240 virtual off_t getLength(void) const { return mLength; } getRemainingLength(void)241 virtual off_t getRemainingLength(void) const { return mLength-mOffset; } 242 virtual int openFileDescriptor(off_t* outStart, off_t* outLength) const; isAllocated(void)243 virtual bool isAllocated(void) const { return mBuf != NULL; } 244 245 private: 246 off_t mStart; // absolute file offset of start of chunk 247 off_t mLength; // length of the chunk 248 off_t mOffset; // current local offset, 0 == mStart 249 FILE* mFp; // for read/seek 250 char* mFileName; // for opening 251 252 /* 253 * To support getBuffer() we either need to read the entire thing into 254 * a buffer or memory-map it. For small files it's probably best to 255 * just read them in. 256 */ 257 enum { kReadVsMapThreshold = 4096 }; 258 259 FileMap* mMap; // for memory map 260 unsigned char* mBuf; // for read 261 262 const void* ensureAlignment(FileMap* map); 263 }; 264 265 266 /* 267 * An asset based on compressed data in a file. 268 */ 269 class _CompressedAsset : public Asset { 270 public: 271 _CompressedAsset(void); 272 virtual ~_CompressedAsset(void); 273 274 /* 275 * Use a piece of an already-open file. 276 * 277 * On success, the object takes ownership of "fd". 278 */ 279 status_t openChunk(int fd, off_t offset, int compressionMethod, 280 size_t uncompressedLen, size_t compressedLen); 281 282 /* 283 * Use a memory-mapped region. 284 * 285 * On success, the object takes ownership of "fd". 286 */ 287 status_t openChunk(FileMap* dataMap, int compressionMethod, 288 size_t uncompressedLen); 289 290 /* 291 * Standard Asset interfaces. 292 */ 293 virtual ssize_t read(void* buf, size_t count); 294 virtual off_t seek(off_t offset, int whence); 295 virtual void close(void); 296 virtual const void* getBuffer(bool wordAligned); getLength(void)297 virtual off_t getLength(void) const { return mUncompressedLen; } getRemainingLength(void)298 virtual off_t getRemainingLength(void) const { return mUncompressedLen-mOffset; } openFileDescriptor(off_t * outStart,off_t * outLength)299 virtual int openFileDescriptor(off_t* outStart, off_t* outLength) const { return -1; } isAllocated(void)300 virtual bool isAllocated(void) const { return mBuf != NULL; } 301 302 private: 303 off_t mStart; // offset to start of compressed data 304 off_t mCompressedLen; // length of the compressed data 305 off_t mUncompressedLen; // length of the uncompressed data 306 off_t mOffset; // current offset, 0 == start of uncomp data 307 308 FileMap* mMap; // for memory-mapped input 309 int mFd; // for file input 310 311 class StreamingZipInflater* mZipInflater; // for streaming large compressed assets 312 313 unsigned char* mBuf; // for getBuffer() 314 }; 315 316 // need: shared mmap version? 317 318 }; // namespace android 319 320 #endif // __LIBS_ASSET_H 321