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) = default; 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 /* 123 * Adds this Asset to the global Asset list for debugging and 124 * accounting. 125 * Concrete subclasses must call this in their constructor. 126 */ 127 static void registerAsset(Asset* asset); 128 129 /* 130 * Removes this Asset from the global Asset list. 131 * Concrete subclasses must call this in their destructor. 132 */ 133 static void unregisterAsset(Asset* asset); 134 135 Asset(void); // constructor; only invoked indirectly 136 137 /* handle common seek() housekeeping */ 138 off64_t handleSeek(off64_t offset, int whence, off64_t curPosn, off64_t maxPosn); 139 140 /* set the asset source string */ 141 void setAssetSource(const String8& path) { mAssetSource = path; } 142 143 AccessMode getAccessMode(void) const { return mAccessMode; } 144 145 private: 146 /* these operations are not implemented */ 147 Asset(const Asset& src); 148 Asset& operator=(const Asset& src); 149 150 /* AssetManager needs access to our "create" functions */ 151 friend class AssetManager; 152 153 /* 154 * Create the asset from a named file on disk. 155 */ 156 static Asset* createFromFile(const char* fileName, AccessMode mode); 157 158 /* 159 * Create the asset from a named, compressed file on disk (e.g. ".gz"). 160 */ 161 static Asset* createFromCompressedFile(const char* fileName, 162 AccessMode mode); 163 164 #if 0 165 /* 166 * Create the asset from a segment of an open file. This will fail 167 * if "offset" and "length" don't fit within the bounds of the file. 168 * 169 * The asset takes ownership of the file descriptor. 170 */ 171 static Asset* createFromFileSegment(int fd, off64_t offset, size_t length, 172 AccessMode mode); 173 174 /* 175 * Create from compressed data. "fd" should be seeked to the start of 176 * the compressed data. This could be inside a gzip file or part of a 177 * Zip archive. 178 * 179 * The asset takes ownership of the file descriptor. 180 * 181 * This may not verify the validity of the compressed data until first 182 * use. 183 */ 184 static Asset* createFromCompressedData(int fd, off64_t offset, 185 int compressionMethod, size_t compressedLength, 186 size_t uncompressedLength, AccessMode mode); 187 #endif 188 189 /* 190 * Create the asset from a memory-mapped file segment. 191 * 192 * The asset takes ownership of the FileMap. 193 */ 194 static Asset* createFromUncompressedMap(FileMap* dataMap, AccessMode mode); 195 196 /* 197 * Create the asset from a memory-mapped file segment with compressed 198 * data. 199 * 200 * The asset takes ownership of the FileMap. 201 */ 202 static Asset* createFromCompressedMap(FileMap* dataMap, 203 size_t uncompressedLen, AccessMode mode); 204 205 206 /* 207 * Create from a reference-counted chunk of shared memory. 208 */ 209 // TODO 210 211 AccessMode mAccessMode; // how the asset was opened 212 String8 mAssetSource; // debug string 213 214 Asset* mNext; // linked list. 215 Asset* mPrev; 216 }; 217 218 219 /* 220 * =========================================================================== 221 * 222 * Innards follow. Do not use these classes directly. 223 */ 224 225 /* 226 * An asset based on an uncompressed file on disk. It may encompass the 227 * entire file or just a piece of it. Access is through fread/fseek. 228 */ 229 class _FileAsset : public Asset { 230 public: 231 _FileAsset(void); 232 virtual ~_FileAsset(void); 233 234 /* 235 * Use a piece of an already-open file. 236 * 237 * On success, the object takes ownership of "fd". 238 */ 239 status_t openChunk(const char* fileName, int fd, off64_t offset, size_t length); 240 241 /* 242 * Use a memory-mapped region. 243 * 244 * On success, the object takes ownership of "dataMap". 245 */ 246 status_t openChunk(FileMap* dataMap); 247 248 /* 249 * Standard Asset interfaces. 250 */ 251 virtual ssize_t read(void* buf, size_t count); 252 virtual off64_t seek(off64_t offset, int whence); 253 virtual void close(void); 254 virtual const void* getBuffer(bool wordAligned); 255 virtual off64_t getLength(void) const { return mLength; } 256 virtual off64_t getRemainingLength(void) const { return mLength-mOffset; } 257 virtual int openFileDescriptor(off64_t* outStart, off64_t* outLength) const; 258 virtual bool isAllocated(void) const { return mBuf != NULL; } 259 260 private: 261 off64_t mStart; // absolute file offset of start of chunk 262 off64_t mLength; // length of the chunk 263 off64_t mOffset; // current local offset, 0 == mStart 264 FILE* mFp; // for read/seek 265 char* mFileName; // for opening 266 267 /* 268 * To support getBuffer() we either need to read the entire thing into 269 * a buffer or memory-map it. For small files it's probably best to 270 * just read them in. 271 */ 272 enum { kReadVsMapThreshold = 4096 }; 273 274 FileMap* mMap; // for memory map 275 unsigned char* mBuf; // for read 276 277 const void* ensureAlignment(FileMap* map); 278 }; 279 280 281 /* 282 * An asset based on compressed data in a file. 283 */ 284 class _CompressedAsset : public Asset { 285 public: 286 _CompressedAsset(void); 287 virtual ~_CompressedAsset(void); 288 289 /* 290 * Use a piece of an already-open file. 291 * 292 * On success, the object takes ownership of "fd". 293 */ 294 status_t openChunk(int fd, off64_t offset, int compressionMethod, 295 size_t uncompressedLen, size_t compressedLen); 296 297 /* 298 * Use a memory-mapped region. 299 * 300 * On success, the object takes ownership of "fd". 301 */ 302 status_t openChunk(FileMap* dataMap, size_t uncompressedLen); 303 304 /* 305 * Standard Asset interfaces. 306 */ 307 virtual ssize_t read(void* buf, size_t count); 308 virtual off64_t seek(off64_t offset, int whence); 309 virtual void close(void); 310 virtual const void* getBuffer(bool wordAligned); 311 virtual off64_t getLength(void) const { return mUncompressedLen; } 312 virtual off64_t getRemainingLength(void) const { return mUncompressedLen-mOffset; } 313 virtual int openFileDescriptor(off64_t* outStart, off64_t* outLength) const { return -1; } 314 virtual bool isAllocated(void) const { return mBuf != NULL; } 315 316 private: 317 off64_t mStart; // offset to start of compressed data 318 off64_t mCompressedLen; // length of the compressed data 319 off64_t mUncompressedLen; // length of the uncompressed data 320 off64_t mOffset; // current offset, 0 == start of uncomp data 321 322 FileMap* mMap; // for memory-mapped input 323 int mFd; // for file input 324 325 class StreamingZipInflater* mZipInflater; // for streaming large compressed assets 326 327 unsigned char* mBuf; // for getBuffer() 328 }; 329 330 // need: shared mmap version? 331 332 }; // namespace android 333 334 #endif // __LIBS_ASSET_H 335