Loading cmds/bootanimation/BootAnimation.cpp +59 −39 Original line number Diff line number Diff line Loading @@ -63,14 +63,19 @@ extern "C" int clock_nanosleep(clockid_t clock_id, int flags, namespace android { static const int ANIM_ENTRY_NAME_MAX = 256; // --------------------------------------------------------------------------- BootAnimation::BootAnimation() : Thread(false) BootAnimation::BootAnimation() : Thread(false), mZip(NULL) { mSession = new SurfaceComposerClient(); } BootAnimation::~BootAnimation() { if (mZip != NULL) { delete mZip; } } void BootAnimation::onFirstRef() { Loading @@ -86,7 +91,7 @@ sp<SurfaceComposerClient> BootAnimation::session() const { } void BootAnimation::binderDied(const wp<IBinder>& who) void BootAnimation::binderDied(const wp<IBinder>&) { // woah, surfaceflinger died! ALOGD("SurfaceFlinger died, exiting..."); Loading Loading @@ -268,8 +273,6 @@ status_t BootAnimation::readyToRun() { mFlingerSurfaceControl = control; mFlingerSurface = s; mAndroidAnimation = true; // If the device has encryption turned on or is in process // of being encrypted we show the encrypted boot animation. char decrypt[PROPERTY_VALUE_MAX]; Loading @@ -277,16 +280,17 @@ status_t BootAnimation::readyToRun() { bool encryptedAnimation = atoi(decrypt) != 0 || !strcmp("trigger_restart_min_framework", decrypt); ZipFileRO* zipFile = NULL; if ((encryptedAnimation && (access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0) && (mZip.open(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE) == NO_ERROR)) || ((zipFile = ZipFileRO::open(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE)) != NULL)) || ((access(USER_BOOTANIMATION_FILE, R_OK) == 0) && (mZip.open(USER_BOOTANIMATION_FILE) == NO_ERROR)) || ((zipFile = ZipFileRO::open(USER_BOOTANIMATION_FILE)) != NULL)) || ((access(SYSTEM_BOOTANIMATION_FILE, R_OK) == 0) && (mZip.open(SYSTEM_BOOTANIMATION_FILE) == NO_ERROR))) { mAndroidAnimation = false; ((zipFile = ZipFileRO::open(SYSTEM_BOOTANIMATION_FILE)) != NULL))) { mZip = zipFile; } return NO_ERROR; Loading @@ -295,7 +299,9 @@ status_t BootAnimation::readyToRun() { bool BootAnimation::threadLoop() { bool r; if (mAndroidAnimation) { // We have no bootanimation file, so we use the stock android logo // animation. if (mZip == NULL) { r = android(); } else { r = movie(); Loading Loading @@ -392,11 +398,14 @@ void BootAnimation::checkExit() { bool BootAnimation::movie() { ZipFileRO& zip(mZip); ZipEntryRO desc = mZip->findEntryByName("desc.txt"); ALOGE_IF(!desc, "couldn't find desc.txt"); if (!desc) { return false; } size_t numEntries = zip.getNumEntries(); ZipEntryRO desc = zip.findEntryByName("desc.txt"); FileMap* descMap = zip.createEntryFileMap(desc); FileMap* descMap = mZip->createEntryFileMap(desc); mZip->releaseEntry(desc); ALOGE_IF(!descMap, "descMap is null"); if (!descMap) { return false; Loading @@ -415,7 +424,7 @@ bool BootAnimation::movie() String8 line(s, endl - s); const char* l = line.string(); int fps, width, height, count, pause; char path[256]; char path[ANIM_ENTRY_NAME_MAX]; char pathType; if (sscanf(l, "%d %d %d", &width, &height, &fps) == 3) { //LOGD("> w=%d, h=%d, fps=%d", width, height, fps); Loading @@ -438,21 +447,31 @@ bool BootAnimation::movie() // read all the data structures const size_t pcount = animation.parts.size(); for (size_t i=0 ; i<numEntries ; i++) { char name[256]; ZipEntryRO entry = zip.findEntryByIndex(i); if (zip.getEntryFileName(entry, name, 256) == 0) { void *cookie = NULL; if (!mZip->startIteration(&cookie)) { return false; } ZipEntryRO entry; char name[ANIM_ENTRY_NAME_MAX]; while ((entry = mZip->nextEntry(cookie)) != NULL) { const int foundEntryName = mZip->getEntryFileName(entry, name, ANIM_ENTRY_NAME_MAX); if (foundEntryName > ANIM_ENTRY_NAME_MAX || foundEntryName == -1) { ALOGE("Error fetching entry file name"); continue; } const String8 entryName(name); const String8 path(entryName.getPathDir()); const String8 leaf(entryName.getPathLeaf()); if (leaf.size() > 0) { for (int j=0 ; j<pcount ; j++) { for (size_t j=0 ; j<pcount ; j++) { if (path == animation.parts[j].path) { int method; // supports only stored png files if (zip.getEntryInfo(entry, &method, 0, 0, 0, 0, 0)) { if (mZip->getEntryInfo(entry, &method, NULL, NULL, NULL, NULL, NULL)) { if (method == ZipFileRO::kCompressStored) { FileMap* map = zip.createEntryFileMap(entry); FileMap* map = mZip->createEntryFileMap(entry); if (map) { Animation::Frame frame; frame.name = leaf; Loading @@ -466,7 +485,8 @@ bool BootAnimation::movie() } } } } mZip->endIteration(cookie); // clear screen glShadeModel(GL_FLAT); Loading Loading @@ -494,7 +514,7 @@ bool BootAnimation::movie() Region clearReg(Rect(mWidth, mHeight)); clearReg.subtractSelf(Rect(xc, yc, xc+animation.width, yc+animation.height)); for (int i=0 ; i<pcount ; i++) { for (size_t i=0 ; i<pcount ; i++) { const Animation::Part& part(animation.parts[i]); const size_t fcount = part.frames.size(); glBindTexture(GL_TEXTURE_2D, 0); Loading @@ -504,7 +524,7 @@ bool BootAnimation::movie() if(exitPending() && !part.playUntilComplete) break; for (int j=0 ; j<fcount && (!exitPending() || part.playUntilComplete) ; j++) { for (size_t j=0 ; j<fcount && (!exitPending() || part.playUntilComplete) ; j++) { const Animation::Frame& frame(part.frames[j]); nsecs_t lastFrame = systemTime(); Loading Loading @@ -564,7 +584,7 @@ bool BootAnimation::movie() // free the textures for this part if (part.count != 1) { for (int j=0 ; j<fcount ; j++) { for (size_t j=0 ; j<fcount ; j++) { const Animation::Frame& frame(part.frames[j]); glDeleteTextures(1, &frame.tid); } Loading cmds/bootanimation/BootAnimation.h +1 −2 Original line number Diff line number Diff line Loading @@ -95,8 +95,7 @@ private: EGLDisplay mSurface; sp<SurfaceControl> mFlingerSurfaceControl; sp<Surface> mFlingerSurface; bool mAndroidAnimation; ZipFileRO mZip; ZipFileRO *mZip; }; // --------------------------------------------------------------------------- Loading core/jni/com_android_internal_content_NativeLibraryHelper.cpp +18 −14 Original line number Diff line number Diff line Loading @@ -21,7 +21,9 @@ #include <utils/Log.h> #include <androidfw/ZipFileRO.h> #include <androidfw/ZipUtils.h> #include <ScopedUtfChars.h> #include <UniquePtr.h> #include <zlib.h> Loading Loading @@ -143,7 +145,7 @@ isFileDifferent(const char* filePath, size_t fileSize, time_t modifiedTime, } static install_status_t sumFiles(JNIEnv* env, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntry, const char* fileName) sumFiles(JNIEnv*, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntry, const char*) { size_t* total = (size_t*) arg; size_t uncompLen; Loading Loading @@ -178,7 +180,7 @@ copyFileIfChanged(JNIEnv *env, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntr return INSTALL_FAILED_INVALID_APK; } else { struct tm t; ZipFileRO::zipTimeToTimespec(when, &t); ZipUtils::zipTimeToTimespec(when, &t); modTime = mktime(&t); } Loading Loading @@ -273,26 +275,25 @@ iterateOverNativeFiles(JNIEnv *env, jstring javaFilePath, jstring javaCpuAbi, js ScopedUtfChars cpuAbi(env, javaCpuAbi); ScopedUtfChars cpuAbi2(env, javaCpuAbi2); ZipFileRO zipFile; if (zipFile.open(filePath.c_str()) != NO_ERROR) { UniquePtr<ZipFileRO> zipFile(ZipFileRO::open(filePath.c_str())); if (zipFile.get() == NULL) { ALOGI("Couldn't open APK %s\n", filePath.c_str()); return INSTALL_FAILED_INVALID_APK; } const int N = zipFile.getNumEntries(); char fileName[PATH_MAX]; bool hasPrimaryAbi = false; for (int i = 0; i < N; i++) { const ZipEntryRO entry = zipFile.findEntryByIndex(i); if (entry == NULL) { continue; void* cookie = NULL; if (!zipFile->startIteration(&cookie)) { ALOGI("Couldn't iterate over APK%s\n", filePath.c_str()); return INSTALL_FAILED_INVALID_APK; } ZipEntryRO entry = NULL; while ((entry = zipFile->nextEntry(cookie)) != NULL) { // Make sure this entry has a filename. if (zipFile.getEntryFileName(entry, fileName, sizeof(fileName))) { if (zipFile->getEntryFileName(entry, fileName, sizeof(fileName))) { continue; } Loading Loading @@ -346,15 +347,18 @@ iterateOverNativeFiles(JNIEnv *env, jstring javaFilePath, jstring javaCpuAbi, js && isFilenameSafe(lastSlash + 1)) || !strncmp(lastSlash + 1, GDBSERVER, GDBSERVER_LEN)) { install_status_t ret = callFunc(env, callArg, &zipFile, entry, lastSlash + 1); install_status_t ret = callFunc(env, callArg, zipFile.get(), entry, lastSlash + 1); if (ret != INSTALL_SUCCEEDED) { ALOGV("Failure for entry %s", lastSlash + 1); zipFile->endIteration(cookie); return ret; } } } zipFile->endIteration(cookie); return INSTALL_SUCCEEDED; } Loading include/androidfw/ZipFileRO.h +40 −132 Original line number Diff line number Diff line Loading @@ -40,6 +40,8 @@ #include <unistd.h> #include <time.h> typedef void* ZipArchiveHandle; namespace android { /* Loading @@ -51,18 +53,13 @@ typedef void* ZipEntryRO; /* * Open a Zip archive for reading. * * We want "open" and "find entry by name" to be fast operations, and we * want to use as little memory as possible. We memory-map the file, * and load a hash table with pointers to the filenames (which aren't * null-terminated). The other fields are at a fixed offset from the * filename, so we don't need to extract those (but we do need to byte-read * and endian-swap them every time we want them). * Implemented as a thin wrapper over system/core/libziparchive. * * "open" and "find entry by name" are fast operations and use as little * memory as possible. * * To speed comparisons when doing a lookup by name, we could make the mapping * "private" (copy-on-write) and null-terminate the filenames after verifying * the record structure. However, this requires a private mapping of * every page that the Central Directory touches. Easier to tuck a copy * of the string length into the hash table entry. * We also support fast iteration over all entries in the file (with a * stable, but unspecified iteration order). * * NOTE: If this is used on file descriptors inherited from a fork() operation, * you must be on a platform that implements pread() to guarantee correctness Loading @@ -70,48 +67,44 @@ typedef void* ZipEntryRO; */ class ZipFileRO { public: ZipFileRO() : mFd(-1), mFileName(NULL), mFileLength(-1), mDirectoryMap(NULL), mNumEntries(-1), mDirectoryOffset(-1), mHashTableSize(-1), mHashTable(NULL) {} ~ZipFileRO(); /* Zip compression methods we support */ enum { kCompressStored = 0, // no compression kCompressDeflated = 8, // standard deflate }; /* * Open an archive. */ status_t open(const char* zipFileName); static ZipFileRO* open(const char* zipFileName); /* * Find an entry, by name. Returns the entry identifier, or NULL if * not found. * * If two entries have the same name, one will be chosen at semi-random. */ ZipEntryRO findEntryByName(const char* fileName) const; ZipEntryRO findEntryByName(const char* entryName) const; /* * Return the #of entries in the Zip archive. * Start iterating over the list of entries in the zip file. Requires * a matching call to endIteration with the same cookie. */ int getNumEntries(void) const { return mNumEntries; } bool startIteration(void** cookie); /** * Return the next entry in iteration order, or NULL if there are no more * entries in this archive. */ ZipEntryRO nextEntry(void* cookie); void endIteration(void* cookie); void releaseEntry(ZipEntryRO entry) const; /* * Return the Nth entry. Zip file entries are not stored in sorted * order, and updated entries may appear at the end, so anyone walking * the archive needs to avoid making ordering assumptions. We take * that further by returning the Nth non-empty entry in the hash table * rather than the Nth entry in the archive. * * Valid values are [0..numEntries). * * [This is currently O(n). If it needs to be fast we can allocate an * additional data structure or provide an iterator interface.] * Return the #of entries in the Zip archive. */ ZipEntryRO findEntryByIndex(int idx) const; int getNumEntries(); /* * Copy the filename into the supplied buffer. Returns 0 on success, Loading Loading @@ -149,112 +142,27 @@ public: * * Returns "true" on success. */ bool uncompressEntry(ZipEntryRO entry, void* buffer) const; bool uncompressEntry(ZipEntryRO entry, void* buffer, size_t size) const; /* * Uncompress the data to an open file descriptor. */ bool uncompressEntry(ZipEntryRO entry, int fd) const; /* Zip compression methods we support */ enum { kCompressStored = 0, // no compression kCompressDeflated = 8, // standard deflate }; /* * Utility function: uncompress deflated data, buffer to buffer. */ static bool inflateBuffer(void* outBuf, const void* inBuf, size_t uncompLen, size_t compLen); /* * Utility function: uncompress deflated data, buffer to fd. */ static bool inflateBuffer(int fd, const void* inBuf, size_t uncompLen, size_t compLen); /* * Utility function to convert ZIP's time format to a timespec struct. */ static inline void zipTimeToTimespec(long when, struct tm* timespec) { const long date = when >> 16; timespec->tm_year = ((date >> 9) & 0x7F) + 80; // Zip is years since 1980 timespec->tm_mon = (date >> 5) & 0x0F; timespec->tm_mday = date & 0x1F; timespec->tm_hour = (when >> 11) & 0x1F; timespec->tm_min = (when >> 5) & 0x3F; timespec->tm_sec = (when & 0x1F) << 1; } /* * Some basic functions for raw data manipulation. "LE" means * Little Endian. */ static inline unsigned short get2LE(const unsigned char* buf) { return buf[0] | (buf[1] << 8); } static inline unsigned long get4LE(const unsigned char* buf) { return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); } ~ZipFileRO(); private: /* these are private and not defined */ ZipFileRO(const ZipFileRO& src); ZipFileRO& operator=(const ZipFileRO& src); /* locate and parse the central directory */ bool mapCentralDirectory(void); /* parse the archive, prepping internal structures */ bool parseZipArchive(void); /* add a new entry to the hash table */ void addToHash(const char* str, int strLen, unsigned int hash); /* compute string hash code */ static unsigned int computeHash(const char* str, int len); /* convert a ZipEntryRO back to a hash table index */ int entryToIndex(const ZipEntryRO entry) const; /* * One entry in the hash table. */ typedef struct HashEntry { const char* name; unsigned short nameLen; //unsigned int hash; } HashEntry; /* open Zip archive */ int mFd; /* Lock for handling the file descriptor (seeks, etc) */ mutable Mutex mFdLock; ZipFileRO(ZipArchiveHandle handle, char* fileName) : mHandle(handle), mFileName(fileName) { } /* zip file name */ const ZipArchiveHandle mHandle; char* mFileName; /* length of file */ size_t mFileLength; /* mapped file */ FileMap* mDirectoryMap; /* number of entries in the Zip archive */ int mNumEntries; /* CD directory offset in the Zip archive */ off64_t mDirectoryOffset; /* * We know how many entries are in the Zip archive, so we have a * fixed-size hash table. We probe for an empty slot. */ int mHashTableSize; HashEntry* mHashTable; }; }; // namespace android Loading include/androidfw/ZipUtils.h +17 −1 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #define __LIBS_ZIPUTILS_H #include <stdio.h> #include <time.h> namespace android { Loading @@ -33,9 +34,11 @@ public: * General utility function for uncompressing "deflate" data from a file * to a buffer. */ static bool inflateToBuffer(FILE* fp, void* buf, long uncompressedLen, long compressedLen); static bool inflateToBuffer(int fd, void* buf, long uncompressedLen, long compressedLen); static bool inflateToBuffer(FILE* fp, void* buf, long uncompressedLen, static bool inflateToBuffer(void *in, void* buf, long uncompressedLen, long compressedLen); /* Loading @@ -57,6 +60,19 @@ public: static bool examineGzip(FILE* fp, int* pCompressionMethod, long* pUncompressedLen, long* pCompressedLen, unsigned long* pCRC32); /* * Utility function to convert ZIP's time format to a timespec struct. */ static inline void zipTimeToTimespec(long when, struct tm* timespec) { const long date = when >> 16; timespec->tm_year = ((date >> 9) & 0x7F) + 80; // Zip is years since 1980 timespec->tm_mon = (date >> 5) & 0x0F; timespec->tm_mday = date & 0x1F; timespec->tm_hour = (when >> 11) & 0x1F; timespec->tm_min = (when >> 5) & 0x3F; timespec->tm_sec = (when & 0x1F) << 1; } private: ZipUtils() {} ~ZipUtils() {} Loading Loading
cmds/bootanimation/BootAnimation.cpp +59 −39 Original line number Diff line number Diff line Loading @@ -63,14 +63,19 @@ extern "C" int clock_nanosleep(clockid_t clock_id, int flags, namespace android { static const int ANIM_ENTRY_NAME_MAX = 256; // --------------------------------------------------------------------------- BootAnimation::BootAnimation() : Thread(false) BootAnimation::BootAnimation() : Thread(false), mZip(NULL) { mSession = new SurfaceComposerClient(); } BootAnimation::~BootAnimation() { if (mZip != NULL) { delete mZip; } } void BootAnimation::onFirstRef() { Loading @@ -86,7 +91,7 @@ sp<SurfaceComposerClient> BootAnimation::session() const { } void BootAnimation::binderDied(const wp<IBinder>& who) void BootAnimation::binderDied(const wp<IBinder>&) { // woah, surfaceflinger died! ALOGD("SurfaceFlinger died, exiting..."); Loading Loading @@ -268,8 +273,6 @@ status_t BootAnimation::readyToRun() { mFlingerSurfaceControl = control; mFlingerSurface = s; mAndroidAnimation = true; // If the device has encryption turned on or is in process // of being encrypted we show the encrypted boot animation. char decrypt[PROPERTY_VALUE_MAX]; Loading @@ -277,16 +280,17 @@ status_t BootAnimation::readyToRun() { bool encryptedAnimation = atoi(decrypt) != 0 || !strcmp("trigger_restart_min_framework", decrypt); ZipFileRO* zipFile = NULL; if ((encryptedAnimation && (access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0) && (mZip.open(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE) == NO_ERROR)) || ((zipFile = ZipFileRO::open(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE)) != NULL)) || ((access(USER_BOOTANIMATION_FILE, R_OK) == 0) && (mZip.open(USER_BOOTANIMATION_FILE) == NO_ERROR)) || ((zipFile = ZipFileRO::open(USER_BOOTANIMATION_FILE)) != NULL)) || ((access(SYSTEM_BOOTANIMATION_FILE, R_OK) == 0) && (mZip.open(SYSTEM_BOOTANIMATION_FILE) == NO_ERROR))) { mAndroidAnimation = false; ((zipFile = ZipFileRO::open(SYSTEM_BOOTANIMATION_FILE)) != NULL))) { mZip = zipFile; } return NO_ERROR; Loading @@ -295,7 +299,9 @@ status_t BootAnimation::readyToRun() { bool BootAnimation::threadLoop() { bool r; if (mAndroidAnimation) { // We have no bootanimation file, so we use the stock android logo // animation. if (mZip == NULL) { r = android(); } else { r = movie(); Loading Loading @@ -392,11 +398,14 @@ void BootAnimation::checkExit() { bool BootAnimation::movie() { ZipFileRO& zip(mZip); ZipEntryRO desc = mZip->findEntryByName("desc.txt"); ALOGE_IF(!desc, "couldn't find desc.txt"); if (!desc) { return false; } size_t numEntries = zip.getNumEntries(); ZipEntryRO desc = zip.findEntryByName("desc.txt"); FileMap* descMap = zip.createEntryFileMap(desc); FileMap* descMap = mZip->createEntryFileMap(desc); mZip->releaseEntry(desc); ALOGE_IF(!descMap, "descMap is null"); if (!descMap) { return false; Loading @@ -415,7 +424,7 @@ bool BootAnimation::movie() String8 line(s, endl - s); const char* l = line.string(); int fps, width, height, count, pause; char path[256]; char path[ANIM_ENTRY_NAME_MAX]; char pathType; if (sscanf(l, "%d %d %d", &width, &height, &fps) == 3) { //LOGD("> w=%d, h=%d, fps=%d", width, height, fps); Loading @@ -438,21 +447,31 @@ bool BootAnimation::movie() // read all the data structures const size_t pcount = animation.parts.size(); for (size_t i=0 ; i<numEntries ; i++) { char name[256]; ZipEntryRO entry = zip.findEntryByIndex(i); if (zip.getEntryFileName(entry, name, 256) == 0) { void *cookie = NULL; if (!mZip->startIteration(&cookie)) { return false; } ZipEntryRO entry; char name[ANIM_ENTRY_NAME_MAX]; while ((entry = mZip->nextEntry(cookie)) != NULL) { const int foundEntryName = mZip->getEntryFileName(entry, name, ANIM_ENTRY_NAME_MAX); if (foundEntryName > ANIM_ENTRY_NAME_MAX || foundEntryName == -1) { ALOGE("Error fetching entry file name"); continue; } const String8 entryName(name); const String8 path(entryName.getPathDir()); const String8 leaf(entryName.getPathLeaf()); if (leaf.size() > 0) { for (int j=0 ; j<pcount ; j++) { for (size_t j=0 ; j<pcount ; j++) { if (path == animation.parts[j].path) { int method; // supports only stored png files if (zip.getEntryInfo(entry, &method, 0, 0, 0, 0, 0)) { if (mZip->getEntryInfo(entry, &method, NULL, NULL, NULL, NULL, NULL)) { if (method == ZipFileRO::kCompressStored) { FileMap* map = zip.createEntryFileMap(entry); FileMap* map = mZip->createEntryFileMap(entry); if (map) { Animation::Frame frame; frame.name = leaf; Loading @@ -466,7 +485,8 @@ bool BootAnimation::movie() } } } } mZip->endIteration(cookie); // clear screen glShadeModel(GL_FLAT); Loading Loading @@ -494,7 +514,7 @@ bool BootAnimation::movie() Region clearReg(Rect(mWidth, mHeight)); clearReg.subtractSelf(Rect(xc, yc, xc+animation.width, yc+animation.height)); for (int i=0 ; i<pcount ; i++) { for (size_t i=0 ; i<pcount ; i++) { const Animation::Part& part(animation.parts[i]); const size_t fcount = part.frames.size(); glBindTexture(GL_TEXTURE_2D, 0); Loading @@ -504,7 +524,7 @@ bool BootAnimation::movie() if(exitPending() && !part.playUntilComplete) break; for (int j=0 ; j<fcount && (!exitPending() || part.playUntilComplete) ; j++) { for (size_t j=0 ; j<fcount && (!exitPending() || part.playUntilComplete) ; j++) { const Animation::Frame& frame(part.frames[j]); nsecs_t lastFrame = systemTime(); Loading Loading @@ -564,7 +584,7 @@ bool BootAnimation::movie() // free the textures for this part if (part.count != 1) { for (int j=0 ; j<fcount ; j++) { for (size_t j=0 ; j<fcount ; j++) { const Animation::Frame& frame(part.frames[j]); glDeleteTextures(1, &frame.tid); } Loading
cmds/bootanimation/BootAnimation.h +1 −2 Original line number Diff line number Diff line Loading @@ -95,8 +95,7 @@ private: EGLDisplay mSurface; sp<SurfaceControl> mFlingerSurfaceControl; sp<Surface> mFlingerSurface; bool mAndroidAnimation; ZipFileRO mZip; ZipFileRO *mZip; }; // --------------------------------------------------------------------------- Loading
core/jni/com_android_internal_content_NativeLibraryHelper.cpp +18 −14 Original line number Diff line number Diff line Loading @@ -21,7 +21,9 @@ #include <utils/Log.h> #include <androidfw/ZipFileRO.h> #include <androidfw/ZipUtils.h> #include <ScopedUtfChars.h> #include <UniquePtr.h> #include <zlib.h> Loading Loading @@ -143,7 +145,7 @@ isFileDifferent(const char* filePath, size_t fileSize, time_t modifiedTime, } static install_status_t sumFiles(JNIEnv* env, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntry, const char* fileName) sumFiles(JNIEnv*, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntry, const char*) { size_t* total = (size_t*) arg; size_t uncompLen; Loading Loading @@ -178,7 +180,7 @@ copyFileIfChanged(JNIEnv *env, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntr return INSTALL_FAILED_INVALID_APK; } else { struct tm t; ZipFileRO::zipTimeToTimespec(when, &t); ZipUtils::zipTimeToTimespec(when, &t); modTime = mktime(&t); } Loading Loading @@ -273,26 +275,25 @@ iterateOverNativeFiles(JNIEnv *env, jstring javaFilePath, jstring javaCpuAbi, js ScopedUtfChars cpuAbi(env, javaCpuAbi); ScopedUtfChars cpuAbi2(env, javaCpuAbi2); ZipFileRO zipFile; if (zipFile.open(filePath.c_str()) != NO_ERROR) { UniquePtr<ZipFileRO> zipFile(ZipFileRO::open(filePath.c_str())); if (zipFile.get() == NULL) { ALOGI("Couldn't open APK %s\n", filePath.c_str()); return INSTALL_FAILED_INVALID_APK; } const int N = zipFile.getNumEntries(); char fileName[PATH_MAX]; bool hasPrimaryAbi = false; for (int i = 0; i < N; i++) { const ZipEntryRO entry = zipFile.findEntryByIndex(i); if (entry == NULL) { continue; void* cookie = NULL; if (!zipFile->startIteration(&cookie)) { ALOGI("Couldn't iterate over APK%s\n", filePath.c_str()); return INSTALL_FAILED_INVALID_APK; } ZipEntryRO entry = NULL; while ((entry = zipFile->nextEntry(cookie)) != NULL) { // Make sure this entry has a filename. if (zipFile.getEntryFileName(entry, fileName, sizeof(fileName))) { if (zipFile->getEntryFileName(entry, fileName, sizeof(fileName))) { continue; } Loading Loading @@ -346,15 +347,18 @@ iterateOverNativeFiles(JNIEnv *env, jstring javaFilePath, jstring javaCpuAbi, js && isFilenameSafe(lastSlash + 1)) || !strncmp(lastSlash + 1, GDBSERVER, GDBSERVER_LEN)) { install_status_t ret = callFunc(env, callArg, &zipFile, entry, lastSlash + 1); install_status_t ret = callFunc(env, callArg, zipFile.get(), entry, lastSlash + 1); if (ret != INSTALL_SUCCEEDED) { ALOGV("Failure for entry %s", lastSlash + 1); zipFile->endIteration(cookie); return ret; } } } zipFile->endIteration(cookie); return INSTALL_SUCCEEDED; } Loading
include/androidfw/ZipFileRO.h +40 −132 Original line number Diff line number Diff line Loading @@ -40,6 +40,8 @@ #include <unistd.h> #include <time.h> typedef void* ZipArchiveHandle; namespace android { /* Loading @@ -51,18 +53,13 @@ typedef void* ZipEntryRO; /* * Open a Zip archive for reading. * * We want "open" and "find entry by name" to be fast operations, and we * want to use as little memory as possible. We memory-map the file, * and load a hash table with pointers to the filenames (which aren't * null-terminated). The other fields are at a fixed offset from the * filename, so we don't need to extract those (but we do need to byte-read * and endian-swap them every time we want them). * Implemented as a thin wrapper over system/core/libziparchive. * * "open" and "find entry by name" are fast operations and use as little * memory as possible. * * To speed comparisons when doing a lookup by name, we could make the mapping * "private" (copy-on-write) and null-terminate the filenames after verifying * the record structure. However, this requires a private mapping of * every page that the Central Directory touches. Easier to tuck a copy * of the string length into the hash table entry. * We also support fast iteration over all entries in the file (with a * stable, but unspecified iteration order). * * NOTE: If this is used on file descriptors inherited from a fork() operation, * you must be on a platform that implements pread() to guarantee correctness Loading @@ -70,48 +67,44 @@ typedef void* ZipEntryRO; */ class ZipFileRO { public: ZipFileRO() : mFd(-1), mFileName(NULL), mFileLength(-1), mDirectoryMap(NULL), mNumEntries(-1), mDirectoryOffset(-1), mHashTableSize(-1), mHashTable(NULL) {} ~ZipFileRO(); /* Zip compression methods we support */ enum { kCompressStored = 0, // no compression kCompressDeflated = 8, // standard deflate }; /* * Open an archive. */ status_t open(const char* zipFileName); static ZipFileRO* open(const char* zipFileName); /* * Find an entry, by name. Returns the entry identifier, or NULL if * not found. * * If two entries have the same name, one will be chosen at semi-random. */ ZipEntryRO findEntryByName(const char* fileName) const; ZipEntryRO findEntryByName(const char* entryName) const; /* * Return the #of entries in the Zip archive. * Start iterating over the list of entries in the zip file. Requires * a matching call to endIteration with the same cookie. */ int getNumEntries(void) const { return mNumEntries; } bool startIteration(void** cookie); /** * Return the next entry in iteration order, or NULL if there are no more * entries in this archive. */ ZipEntryRO nextEntry(void* cookie); void endIteration(void* cookie); void releaseEntry(ZipEntryRO entry) const; /* * Return the Nth entry. Zip file entries are not stored in sorted * order, and updated entries may appear at the end, so anyone walking * the archive needs to avoid making ordering assumptions. We take * that further by returning the Nth non-empty entry in the hash table * rather than the Nth entry in the archive. * * Valid values are [0..numEntries). * * [This is currently O(n). If it needs to be fast we can allocate an * additional data structure or provide an iterator interface.] * Return the #of entries in the Zip archive. */ ZipEntryRO findEntryByIndex(int idx) const; int getNumEntries(); /* * Copy the filename into the supplied buffer. Returns 0 on success, Loading Loading @@ -149,112 +142,27 @@ public: * * Returns "true" on success. */ bool uncompressEntry(ZipEntryRO entry, void* buffer) const; bool uncompressEntry(ZipEntryRO entry, void* buffer, size_t size) const; /* * Uncompress the data to an open file descriptor. */ bool uncompressEntry(ZipEntryRO entry, int fd) const; /* Zip compression methods we support */ enum { kCompressStored = 0, // no compression kCompressDeflated = 8, // standard deflate }; /* * Utility function: uncompress deflated data, buffer to buffer. */ static bool inflateBuffer(void* outBuf, const void* inBuf, size_t uncompLen, size_t compLen); /* * Utility function: uncompress deflated data, buffer to fd. */ static bool inflateBuffer(int fd, const void* inBuf, size_t uncompLen, size_t compLen); /* * Utility function to convert ZIP's time format to a timespec struct. */ static inline void zipTimeToTimespec(long when, struct tm* timespec) { const long date = when >> 16; timespec->tm_year = ((date >> 9) & 0x7F) + 80; // Zip is years since 1980 timespec->tm_mon = (date >> 5) & 0x0F; timespec->tm_mday = date & 0x1F; timespec->tm_hour = (when >> 11) & 0x1F; timespec->tm_min = (when >> 5) & 0x3F; timespec->tm_sec = (when & 0x1F) << 1; } /* * Some basic functions for raw data manipulation. "LE" means * Little Endian. */ static inline unsigned short get2LE(const unsigned char* buf) { return buf[0] | (buf[1] << 8); } static inline unsigned long get4LE(const unsigned char* buf) { return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); } ~ZipFileRO(); private: /* these are private and not defined */ ZipFileRO(const ZipFileRO& src); ZipFileRO& operator=(const ZipFileRO& src); /* locate and parse the central directory */ bool mapCentralDirectory(void); /* parse the archive, prepping internal structures */ bool parseZipArchive(void); /* add a new entry to the hash table */ void addToHash(const char* str, int strLen, unsigned int hash); /* compute string hash code */ static unsigned int computeHash(const char* str, int len); /* convert a ZipEntryRO back to a hash table index */ int entryToIndex(const ZipEntryRO entry) const; /* * One entry in the hash table. */ typedef struct HashEntry { const char* name; unsigned short nameLen; //unsigned int hash; } HashEntry; /* open Zip archive */ int mFd; /* Lock for handling the file descriptor (seeks, etc) */ mutable Mutex mFdLock; ZipFileRO(ZipArchiveHandle handle, char* fileName) : mHandle(handle), mFileName(fileName) { } /* zip file name */ const ZipArchiveHandle mHandle; char* mFileName; /* length of file */ size_t mFileLength; /* mapped file */ FileMap* mDirectoryMap; /* number of entries in the Zip archive */ int mNumEntries; /* CD directory offset in the Zip archive */ off64_t mDirectoryOffset; /* * We know how many entries are in the Zip archive, so we have a * fixed-size hash table. We probe for an empty slot. */ int mHashTableSize; HashEntry* mHashTable; }; }; // namespace android Loading
include/androidfw/ZipUtils.h +17 −1 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #define __LIBS_ZIPUTILS_H #include <stdio.h> #include <time.h> namespace android { Loading @@ -33,9 +34,11 @@ public: * General utility function for uncompressing "deflate" data from a file * to a buffer. */ static bool inflateToBuffer(FILE* fp, void* buf, long uncompressedLen, long compressedLen); static bool inflateToBuffer(int fd, void* buf, long uncompressedLen, long compressedLen); static bool inflateToBuffer(FILE* fp, void* buf, long uncompressedLen, static bool inflateToBuffer(void *in, void* buf, long uncompressedLen, long compressedLen); /* Loading @@ -57,6 +60,19 @@ public: static bool examineGzip(FILE* fp, int* pCompressionMethod, long* pUncompressedLen, long* pCompressedLen, unsigned long* pCRC32); /* * Utility function to convert ZIP's time format to a timespec struct. */ static inline void zipTimeToTimespec(long when, struct tm* timespec) { const long date = when >> 16; timespec->tm_year = ((date >> 9) & 0x7F) + 80; // Zip is years since 1980 timespec->tm_mon = (date >> 5) & 0x0F; timespec->tm_mday = date & 0x1F; timespec->tm_hour = (when >> 11) & 0x1F; timespec->tm_min = (when >> 5) & 0x3F; timespec->tm_sec = (when & 0x1F) << 1; } private: ZipUtils() {} ~ZipUtils() {} Loading