diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index ea53e59b017dc..c597ed2cc61e7 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -68,14 +68,11 @@ static const int ANIM_ENTRY_NAME_MAX = 256; // --------------------------------------------------------------------------- -BootAnimation::BootAnimation() : Thread(false), mZip(NULL), mClockEnabled(true) { +BootAnimation::BootAnimation() : Thread(false), mClockEnabled(true) { mSession = new SurfaceComposerClient(); } BootAnimation::~BootAnimation() { - if (mZip != NULL) { - delete mZip; - } } void BootAnimation::onFirstRef() { @@ -288,19 +285,15 @@ 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) && - ((zipFile = ZipFileRO::open(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE)) != NULL)) || - - ((access(OEM_BOOTANIMATION_FILE, R_OK) == 0) && - ((zipFile = ZipFileRO::open(OEM_BOOTANIMATION_FILE)) != NULL)) || - - ((access(SYSTEM_BOOTANIMATION_FILE, R_OK) == 0) && - ((zipFile = ZipFileRO::open(SYSTEM_BOOTANIMATION_FILE)) != NULL))) { - mZip = zipFile; + if (encryptedAnimation && (access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0)) { + mZipFileName = SYSTEM_ENCRYPTED_BOOTANIMATION_FILE; + } + else if (access(OEM_BOOTANIMATION_FILE, R_OK) == 0) { + mZipFileName = OEM_BOOTANIMATION_FILE; + } + else if (access(SYSTEM_BOOTANIMATION_FILE, R_OK) == 0) { + mZipFileName = SYSTEM_BOOTANIMATION_FILE; } - return NO_ERROR; } @@ -309,7 +302,7 @@ bool BootAnimation::threadLoop() bool r; // We have no bootanimation file, so we use the stock android logo // animation. - if (mZip == NULL) { + if (mZipFileName.isEmpty()) { r = android(); } else { r = movie(); @@ -429,16 +422,17 @@ static bool parseColor(const char str[7], float color[3]) { return true; } -bool BootAnimation::readFile(const char* name, String8& outString) + +static bool readFile(ZipFileRO* zip, const char* name, String8& outString) { - ZipEntryRO entry = mZip->findEntryByName(name); + ZipEntryRO entry = zip->findEntryByName(name); ALOGE_IF(!entry, "couldn't find %s", name); if (!entry) { return false; } - FileMap* entryMap = mZip->createEntryFileMap(entry); - mZip->releaseEntry(entry); + FileMap* entryMap = zip->createEntryFileMap(entry); + zip->releaseEntry(entry); ALOGE_IF(!entryMap, "entryMap is null"); if (!entryMap) { return false; @@ -512,18 +506,18 @@ void BootAnimation::drawTime(const Texture& clockTex, const int yPos) { glBindTexture(GL_TEXTURE_2D, 0); } -bool BootAnimation::movie() +bool BootAnimation::parseAnimationDesc(Animation& animation) { String8 desString; - if (!readFile("desc.txt", desString)) { + if (!readFile(animation.zip, "desc.txt", desString)) { return false; } char const* s = desString.string(); // Create and initialize an AudioPlayer if we have an audio_conf.txt file String8 audioConf; - if (readFile("audio_conf.txt", audioConf)) { + if (readFile(animation.zip, "audio_conf.txt", audioConf)) { mAudioPlayer = new AudioPlayer; if (!mAudioPlayer->init(audioConf.string())) { ALOGE("mAudioPlayer.init failed"); @@ -531,8 +525,6 @@ bool BootAnimation::movie() } } - Animation animation; - // Parse the description file for (;;) { const char* endl = strstr(s, "\n"); @@ -564,6 +556,7 @@ bool BootAnimation::movie() part.path = path; part.clockPosY = clockPosY; part.audioFile = NULL; + part.animation = NULL; if (!parseColor(color, part.backgroundColor)) { ALOGE("> invalid color '#%s'", color); part.backgroundColor[0] = 0.0f; @@ -572,13 +565,29 @@ bool BootAnimation::movie() } animation.parts.add(part); } - + else if (strcmp(l, "$SYSTEM") == 0) { + // ALOGD("> SYSTEM"); + Animation::Part part; + part.playUntilComplete = false; + part.count = 1; + part.pause = 0; + part.audioFile = NULL; + part.animation = loadAnimation(String8(SYSTEM_BOOTANIMATION_FILE)); + if (part.animation != NULL) + animation.parts.add(part); + } s = ++endl; } + return true; +} + +bool BootAnimation::preloadZip(Animation& animation) +{ // read all the data structures const size_t pcount = animation.parts.size(); void *cookie = NULL; + ZipFileRO* mZip = animation.zip; if (!mZip->startIteration(&cookie)) { return false; } @@ -624,6 +633,16 @@ bool BootAnimation::movie() mZip->endIteration(cookie); + return true; +} + +bool BootAnimation::movie() +{ + + Animation* animation = loadAnimation(mZipFileName); + if (animation == NULL) + return false; + // Blend required to draw time on top of animation frames. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glShadeModel(GL_FLAT); @@ -645,6 +664,19 @@ bool BootAnimation::movie() mClockEnabled = clockTextureInitialized; } + playAnimation(*animation); + releaseAnimation(animation); + + if (clockTextureInitialized) { + glDeleteTextures(1, &mClock.name); + } + + return false; +} + +bool BootAnimation::playAnimation(const Animation& animation) +{ + const size_t pcount = animation.parts.size(); const int xc = (mWidth - animation.width) / 2; const int yc = ((mHeight - animation.height) / 2); nsecs_t frameDuration = s2ns(1) / animation.fps; @@ -657,6 +689,14 @@ bool BootAnimation::movie() const size_t fcount = part.frames.size(); glBindTexture(GL_TEXTURE_2D, 0); + // Handle animation package + if (part.animation != NULL) { + playAnimation(*part.animation); + if (exitPending()) + break; + continue; //to next part + } + for (int r=0 ; !part.count || r::iterator it = animation->parts.begin(), + e = animation->parts.end(); it != e; ++it) { + if (it->animation) + releaseAnimation(it->animation); + } + if (animation->zip) + delete animation->zip; + delete animation; +} + +BootAnimation::Animation* BootAnimation::loadAnimation(const String8& fn) +{ + if (mLoadedFiles.indexOf(fn) >= 0) { + ALOGE("File \"%s\" is already loaded. Cyclic ref is not allowed", + fn.string()); + return NULL; + } + ZipFileRO *zip = ZipFileRO::open(fn); + if (zip == NULL) { + ALOGE("Failed to open animation zip \"%s\": %s", + fn.string(), strerror(errno)); + return NULL; + } + + Animation *animation = new Animation; + animation->fileName = fn; + animation->zip = zip; + mLoadedFiles.add(animation->fileName); + + parseAnimationDesc(*animation); + preloadZip(*animation); + + mLoadedFiles.remove(fn); + return animation; +} // --------------------------------------------------------------------------- } diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h index 83e2b3804fe8a..d49e1ec837b95 100644 --- a/cmds/bootanimation/BootAnimation.h +++ b/cmds/bootanimation/BootAnimation.h @@ -76,19 +76,27 @@ private: bool playUntilComplete; float backgroundColor[3]; FileMap* audioFile; + Animation* animation; }; int fps; int width; int height; Vector parts; + String8 audioConf; + String8 fileName; + ZipFileRO* zip; }; status_t initTexture(Texture* texture, AssetManager& asset, const char* name); status_t initTexture(const Animation::Frame& frame); bool android(); - bool readFile(const char* name, String8& outString); bool movie(); void drawTime(const Texture& clockTex, const int yPos); + Animation* loadAnimation(const String8&); + bool playAnimation(const Animation&); + void releaseAnimation(Animation*) const; + bool parseAnimationDesc(Animation&); + bool preloadZip(Animation &animation); void checkExit(); @@ -104,8 +112,9 @@ private: EGLDisplay mSurface; sp mFlingerSurfaceControl; sp mFlingerSurface; - ZipFileRO *mZip; bool mClockEnabled; + String8 mZipFileName; + SortedVector mLoadedFiles; }; // ---------------------------------------------------------------------------