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