BootAnimation.cpp revision 39218ba26d5bb8646f04273f2c3731598721c1da
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood#define LOG_NDEBUG 0
18bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian#define LOG_TAG "BootAnimation"
19bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdint.h>
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/types.h>
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <math.h>
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <fcntl.h>
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/misc.h>
25b4d5a72691846bce5779cc3db056f09a5031d7ccMathias Agopian#include <signal.h>
26bb94f3107ea567ddf67bed4617c3bcbd602538dfElliott Hughes#include <time.h>
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
28bd9a08d318f94a3d0b2f8f9d7b16b10736d80c5cJason parks#include <cutils/properties.h>
29bd9a08d318f94a3d0b2f8f9d7b16b10736d80c5cJason parks
30b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <androidfw/AssetManager.h>
31ac31a3b8b09aba1c5ebc73f0cf65cac2210aa6b7Mathias Agopian#include <binder/IPCThreadState.h>
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Atomic.h>
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Errors.h>
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Log.h>
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <ui/PixelFormat.h>
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <ui/Rect.h>
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <ui/Region.h>
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <ui/DisplayInfo.h>
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
410b722fe9ce98d97dbcb6fefd170b85ab7037e528Jeff Brown#include <gui/ISurfaceComposer.h>
428335f1ccccedb6655d96d9d5b697a7f0938235ddMathias Agopian#include <gui/Surface.h>
438335f1ccccedb6655d96d9d5b697a7f0938235ddMathias Agopian#include <gui/SurfaceComposerClient.h>
44000479f9e325b4e426a67033abd92d47da412725Mathias Agopian
45cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe// TODO: Fix Skia.
46cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe#pragma GCC diagnostic push
47cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe#pragma GCC diagnostic ignored "-Wunused-parameter"
48eece0dda56ae29fff6e9003df97594f6ac50b6e2Derek Sollenberger#include <SkBitmap.h>
49eece0dda56ae29fff6e9003df97594f6ac50b6e2Derek Sollenberger#include <SkStream.h>
50eece0dda56ae29fff6e9003df97594f6ac50b6e2Derek Sollenberger#include <SkImageDecoder.h>
51cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe#pragma GCC diagnostic pop
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <GLES/gl.h>
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <GLES/glext.h>
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <EGL/eglext.h>
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "BootAnimation.h"
58ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood#include "AudioPlayer.h"
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6028f0877073e0ebc59f1eeeb6e0d54b614b9d3fa5Jeff Sharkey#define OEM_BOOTANIMATION_FILE "/oem/media/bootanimation.zip"
61c11f46259a1e8f4e7e58925aefd1ed9eaf57a7fcJim Huang#define SYSTEM_BOOTANIMATION_FILE "/system/media/bootanimation.zip"
62bd9a08d318f94a3d0b2f8f9d7b16b10736d80c5cJason parks#define SYSTEM_ENCRYPTED_BOOTANIMATION_FILE "/system/media/bootanimation-encrypted.zip"
63d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester#define EXIT_PROP_NAME "service.bootanim.exit"
64c11f46259a1e8f4e7e58925aefd1ed9eaf57a7fcJim Huang
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android {
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
67afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamathstatic const int ANIM_ENTRY_NAME_MAX = 256;
68afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7139218ba26d5bb8646f04273f2c3731598721c1daAndriy NaborskyyBootAnimation::BootAnimation() : Thread(false)
72a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian{
73627e7b50be41e4fdee758a1bfad3a55de56b4e27Mathias Agopian    mSession = new SurfaceComposerClient();
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectBootAnimation::~BootAnimation() {
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid BootAnimation::onFirstRef() {
80bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian    status_t err = mSession->linkToComposerDeath(this);
813762c311729fe9f3af085c14c5c1fb471d994c03Steve Block    ALOGE_IF(err, "linkToComposerDeath failed (%s) ", strerror(-err));
828434c5369304e639efe8eab368ca410c589d87c2Mathias Agopian    if (err == NO_ERROR) {
83bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian        run("BootAnimation", PRIORITY_DISPLAY);
84bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian    }
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
87bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopiansp<SurfaceComposerClient> BootAnimation::session() const {
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mSession;
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
91bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian
92afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamathvoid BootAnimation::binderDied(const wp<IBinder>&)
93bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian{
94bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian    // woah, surfaceflinger died!
955baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    ALOGD("SurfaceFlinger died, exiting...");
96bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian
97bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian    // calling requestExit() is not enough here because the Surface code
98bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian    // might be blocked on a condition variable that will never be updated.
99bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian    kill( getpid(), SIGKILL );
100bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian    requestExit();
101ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood    if (mAudioPlayer != NULL) {
102ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood        mAudioPlayer->requestExit();
103ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood    }
104bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian}
105bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t BootAnimation::initTexture(Texture* texture, AssetManager& assets,
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        const char* name) {
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Asset* asset = assets.open(name, Asset::ACCESS_BUFFER);
109cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe    if (asset == NULL)
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NO_INIT;
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkBitmap bitmap;
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkImageDecoder::DecodeMemory(asset->getBuffer(false), asset->getLength(),
11342a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed            &bitmap, kUnknown_SkColorType, SkImageDecoder::kDecodePixels_Mode);
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    asset->close();
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    delete asset;
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // ensure we can call getPixels(). No need to call unlock, since the
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // bitmap will go out of scope when we return from this method.
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    bitmap.lockPixels();
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const int w = bitmap.width();
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const int h = bitmap.height();
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const void* p = bitmap.getPixels();
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    GLint crop[4] = { 0, h, w, -h };
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    texture->w = w;
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    texture->h = h;
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    glGenTextures(1, &texture->name);
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    glBindTexture(GL_TEXTURE_2D, texture->name);
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13242a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed    switch (bitmap.colorType()) {
13342a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed        case kAlpha_8_SkColorType:
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_ALPHA,
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    GL_UNSIGNED_BYTE, p);
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
13742a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed        case kARGB_4444_SkColorType:
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA,
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    GL_UNSIGNED_SHORT_4_4_4_4, p);
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
14142a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed        case kN32_SkColorType:
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA,
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    GL_UNSIGNED_BYTE, p);
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
14542a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed        case kRGB_565_SkColorType:
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB,
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    GL_UNSIGNED_SHORT_5_6_5, p);
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        default:
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NO_ERROR;
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1610c1eeb3c8ab53954218d3b8f4be08ff21be3e985Mykola Kondratenkostatus_t BootAnimation::initTexture(const Animation::Frame& frame)
162a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian{
163a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    //StopWatch watch("blah");
164a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian
165a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    SkBitmap bitmap;
1660c1eeb3c8ab53954218d3b8f4be08ff21be3e985Mykola Kondratenko    SkMemoryStream  stream(frame.map->getDataPtr(), frame.map->getDataLength());
1672b99e55ee3a0956a43a276f8018356ff9d08eafcMathias Agopian    SkImageDecoder* codec = SkImageDecoder::Factory(&stream);
168cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe    if (codec != NULL) {
169c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes        codec->setDitherImage(false);
1702b99e55ee3a0956a43a276f8018356ff9d08eafcMathias Agopian        codec->decode(&stream, &bitmap,
17142a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed                kN32_SkColorType,
1722b99e55ee3a0956a43a276f8018356ff9d08eafcMathias Agopian                SkImageDecoder::kDecodePixels_Mode);
1732b99e55ee3a0956a43a276f8018356ff9d08eafcMathias Agopian        delete codec;
1742b99e55ee3a0956a43a276f8018356ff9d08eafcMathias Agopian    }
175a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian
1760c1eeb3c8ab53954218d3b8f4be08ff21be3e985Mykola Kondratenko    // FileMap memory is never released until application exit.
1770c1eeb3c8ab53954218d3b8f4be08ff21be3e985Mykola Kondratenko    // Release it now as the texture is already loaded and the memory used for
1780c1eeb3c8ab53954218d3b8f4be08ff21be3e985Mykola Kondratenko    // the packed resource can be released.
179688ff4cf0f93d1a886437884f23874e5595d59a3Narayan Kamath    delete frame.map;
1800c1eeb3c8ab53954218d3b8f4be08ff21be3e985Mykola Kondratenko
181a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    // ensure we can call getPixels(). No need to call unlock, since the
182a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    // bitmap will go out of scope when we return from this method.
183a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    bitmap.lockPixels();
184a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian
185a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    const int w = bitmap.width();
186a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    const int h = bitmap.height();
187a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    const void* p = bitmap.getPixels();
188a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian
189a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    GLint crop[4] = { 0, h, w, -h };
190a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    int tw = 1 << (31 - __builtin_clz(w));
191a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    int th = 1 << (31 - __builtin_clz(h));
192a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    if (tw < w) tw <<= 1;
193a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    if (th < h) th <<= 1;
194a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian
19542a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed    switch (bitmap.colorType()) {
19642a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed        case kN32_SkColorType:
197a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian            if (tw != w || th != h) {
198a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tw, th, 0, GL_RGBA,
199a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian                        GL_UNSIGNED_BYTE, 0);
200a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian                glTexSubImage2D(GL_TEXTURE_2D, 0,
201a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian                        0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, p);
202a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian            } else {
203a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tw, th, 0, GL_RGBA,
204a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian                        GL_UNSIGNED_BYTE, p);
205a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian            }
206a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian            break;
207a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian
20842a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed        case kRGB_565_SkColorType:
209a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian            if (tw != w || th != h) {
210a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tw, th, 0, GL_RGB,
211a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian                        GL_UNSIGNED_SHORT_5_6_5, 0);
212a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian                glTexSubImage2D(GL_TEXTURE_2D, 0,
213a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian                        0, 0, w, h, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, p);
214a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian            } else {
215a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tw, th, 0, GL_RGB,
216a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian                        GL_UNSIGNED_SHORT_5_6_5, p);
217a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian            }
218a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian            break;
219a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian        default:
220a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian            break;
221a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    }
222a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian
223a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
224a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian
225a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    return NO_ERROR;
226a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian}
227a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t BootAnimation::readyToRun() {
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mAssets.addDefaultAssets();
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2310b722fe9ce98d97dbcb6fefd170b85ab7037e528Jeff Brown    sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(
2320b722fe9ce98d97dbcb6fefd170b85ab7037e528Jeff Brown            ISurfaceComposer::eDisplayIdMain));
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    DisplayInfo dinfo;
2340b722fe9ce98d97dbcb6fefd170b85ab7037e528Jeff Brown    status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &dinfo);
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (status)
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // create the native surface
2390b722fe9ce98d97dbcb6fefd170b85ab7037e528Jeff Brown    sp<SurfaceControl> control = session()->createSurface(String8("BootAnimation"),
2400b722fe9ce98d97dbcb6fefd170b85ab7037e528Jeff Brown            dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);
241439863f3b3e725b5de1cba4940a21900369961c0Mathias Agopian
242439863f3b3e725b5de1cba4940a21900369961c0Mathias Agopian    SurfaceComposerClient::openGlobalTransaction();
24317f638b39f2e8b610ecfa1290e5bc42ab7700c98Mathias Agopian    control->setLayer(0x40000000);
244439863f3b3e725b5de1cba4940a21900369961c0Mathias Agopian    SurfaceComposerClient::closeGlobalTransaction();
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
24617f638b39f2e8b610ecfa1290e5bc42ab7700c98Mathias Agopian    sp<Surface> s = control->getSurface();
24717f638b39f2e8b610ecfa1290e5bc42ab7700c98Mathias Agopian
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // initialize opengl and egl
249738b9a45399485893fa9541fae19c47e01bc4af4Mathias Agopian    const EGLint attribs[] = {
2501b253b702a356619ae3c5e68ee92062b5305c5d7Mathias Agopian            EGL_RED_SIZE,   8,
2511b253b702a356619ae3c5e68ee92062b5305c5d7Mathias Agopian            EGL_GREEN_SIZE, 8,
2521b253b702a356619ae3c5e68ee92062b5305c5d7Mathias Agopian            EGL_BLUE_SIZE,  8,
253a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian            EGL_DEPTH_SIZE, 0,
254a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian            EGL_NONE
255738b9a45399485893fa9541fae19c47e01bc4af4Mathias Agopian    };
256cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe    EGLint w, h;
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    EGLint numConfigs;
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    EGLConfig config;
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    EGLSurface surface;
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    EGLContext context;
261627e7b50be41e4fdee758a1bfad3a55de56b4e27Mathias Agopian
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
263627e7b50be41e4fdee758a1bfad3a55de56b4e27Mathias Agopian
264627e7b50be41e4fdee758a1bfad3a55de56b4e27Mathias Agopian    eglInitialize(display, 0, 0);
2651b253b702a356619ae3c5e68ee92062b5305c5d7Mathias Agopian    eglChooseConfig(display, attribs, &config, 1, &numConfigs);
2661473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    surface = eglCreateWindowSurface(display, config, s.get(), NULL);
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    context = eglCreateContext(display, config, NULL, NULL);
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    eglQuerySurface(display, surface, EGL_WIDTH, &w);
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    eglQuerySurface(display, surface, EGL_HEIGHT, &h);
270a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian
271abac01052c1c40f8582fe9f010c2efe6013e25c6Mathias Agopian    if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE)
272abac01052c1c40f8582fe9f010c2efe6013e25c6Mathias Agopian        return NO_INIT;
273a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mDisplay = display;
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mContext = context;
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mSurface = surface;
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mWidth = w;
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mHeight = h;
27917f638b39f2e8b610ecfa1290e5bc42ab7700c98Mathias Agopian    mFlingerSurfaceControl = control;
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mFlingerSurface = s;
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
282c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes    // If the device has encryption turned on or is in process
283bd9a08d318f94a3d0b2f8f9d7b16b10736d80c5cJason parks    // of being encrypted we show the encrypted boot animation.
284bd9a08d318f94a3d0b2f8f9d7b16b10736d80c5cJason parks    char decrypt[PROPERTY_VALUE_MAX];
285bd9a08d318f94a3d0b2f8f9d7b16b10736d80c5cJason parks    property_get("vold.decrypt", decrypt, "");
286bd9a08d318f94a3d0b2f8f9d7b16b10736d80c5cJason parks
287bd9a08d318f94a3d0b2f8f9d7b16b10736d80c5cJason parks    bool encryptedAnimation = atoi(decrypt) != 0 || !strcmp("trigger_restart_min_framework", decrypt);
288bd9a08d318f94a3d0b2f8f9d7b16b10736d80c5cJason parks
28939218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    if (encryptedAnimation && (access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0)) {
29039218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy        mZipFileName = SYSTEM_ENCRYPTED_BOOTANIMATION_FILE;
29139218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    }
29239218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    else if (access(OEM_BOOTANIMATION_FILE, R_OK) == 0) {
29339218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy        mZipFileName = OEM_BOOTANIMATION_FILE;
29439218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    }
29539218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    else if (access(SYSTEM_BOOTANIMATION_FILE, R_OK) == 0) {
29639218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy        mZipFileName = SYSTEM_BOOTANIMATION_FILE;
297bd9a08d318f94a3d0b2f8f9d7b16b10736d80c5cJason parks    }
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NO_ERROR;
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
301a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopianbool BootAnimation::threadLoop()
302a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian{
303a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    bool r;
304afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    // We have no bootanimation file, so we use the stock android logo
305afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    // animation.
30639218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    if (mZipFileName.isEmpty()) {
307a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian        r = android();
308a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    } else {
309a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian        r = movie();
310a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    }
311a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    eglDestroyContext(mDisplay, mContext);
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    eglDestroySurface(mDisplay, mSurface);
3156cf0db228ca275dfcda57d79c55e5fa306809632Mathias Agopian    mFlingerSurface.clear();
31617f638b39f2e8b610ecfa1290e5bc42ab7700c98Mathias Agopian    mFlingerSurfaceControl.clear();
317627e7b50be41e4fdee758a1bfad3a55de56b4e27Mathias Agopian    eglTerminate(mDisplay);
318627e7b50be41e4fdee758a1bfad3a55de56b4e27Mathias Agopian    IPCThreadState::self()->stopProcess();
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return r;
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
322a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopianbool BootAnimation::android()
323a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian{
324b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian    initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png");
325b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian    initTexture(&mAndroid[1], mAssets, "images/android-logo-shine.png");
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // clear screen
328a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    glShadeModel(GL_FLAT);
329b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian    glDisable(GL_DITHER);
330b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian    glDisable(GL_SCISSOR_TEST);
33159f19e48c1c043bb9debdc35d166e397e2125d33Mathias Agopian    glClearColor(0,0,0,1);
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    glClear(GL_COLOR_BUFFER_BIT);
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    eglSwapBuffers(mDisplay, mSurface);
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
335a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    glEnable(GL_TEXTURE_2D);
336a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
337a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian
338b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian    const GLint xc = (mWidth  - mAndroid[0].w) / 2;
339b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian    const GLint yc = (mHeight - mAndroid[0].h) / 2;
340b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian    const Rect updateRect(xc, yc, xc + mAndroid[0].w, yc + mAndroid[0].h);
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(),
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            updateRect.height());
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
345b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian    // Blend state
346b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
347b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
348b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const nsecs_t startTime = systemTime();
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    do {
3511379665abdb8330caf813fb77902914d1545bcd9Mathias Agopian        nsecs_t now = systemTime();
3521379665abdb8330caf813fb77902914d1545bcd9Mathias Agopian        double time = now - startTime;
353b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian        float t = 4.0f * float(time / us2ns(16667)) / mAndroid[1].w;
354b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian        GLint offset = (1 - (t - floorf(t))) * mAndroid[1].w;
355b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian        GLint x = xc - offset;
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3578166864e42bc20c1544b2028e8dd65b90f29a0eaMathias Agopian        glDisable(GL_SCISSOR_TEST);
3588166864e42bc20c1544b2028e8dd65b90f29a0eaMathias Agopian        glClear(GL_COLOR_BUFFER_BIT);
3598166864e42bc20c1544b2028e8dd65b90f29a0eaMathias Agopian
3608166864e42bc20c1544b2028e8dd65b90f29a0eaMathias Agopian        glEnable(GL_SCISSOR_TEST);
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        glDisable(GL_BLEND);
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        glBindTexture(GL_TEXTURE_2D, mAndroid[1].name);
363b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian        glDrawTexiOES(x,                 yc, 0, mAndroid[1].w, mAndroid[1].h);
364b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian        glDrawTexiOES(x + mAndroid[1].w, yc, 0, mAndroid[1].w, mAndroid[1].h);
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
366b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian        glEnable(GL_BLEND);
367b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian        glBindTexture(GL_TEXTURE_2D, mAndroid[0].name);
368b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian        glDrawTexiOES(xc, yc, 0, mAndroid[0].w, mAndroid[0].h);
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
370627e7b50be41e4fdee758a1bfad3a55de56b4e27Mathias Agopian        EGLBoolean res = eglSwapBuffers(mDisplay, mSurface);
371627e7b50be41e4fdee758a1bfad3a55de56b4e27Mathias Agopian        if (res == EGL_FALSE)
372627e7b50be41e4fdee758a1bfad3a55de56b4e27Mathias Agopian            break;
373627e7b50be41e4fdee758a1bfad3a55de56b4e27Mathias Agopian
3741379665abdb8330caf813fb77902914d1545bcd9Mathias Agopian        // 12fps: don't animate too fast to preserve CPU
3751379665abdb8330caf813fb77902914d1545bcd9Mathias Agopian        const nsecs_t sleepTime = 83333 - ns2us(systemTime() - now);
3761379665abdb8330caf813fb77902914d1545bcd9Mathias Agopian        if (sleepTime > 0)
377a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian            usleep(sleepTime);
378d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester
379d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester        checkExit();
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } while (!exitPending());
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    glDeleteTextures(1, &mAndroid[0].name);
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    glDeleteTextures(1, &mAndroid[1].name);
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return false;
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
387a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian
388d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hestervoid BootAnimation::checkExit() {
389d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester    // Allow surface flinger to gracefully request shutdown
390d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester    char value[PROPERTY_VALUE_MAX];
391d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester    property_get(EXIT_PROP_NAME, value, "0");
392d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester    int exitnow = atoi(value);
393d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester    if (exitnow) {
394d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester        requestExit();
395ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood        if (mAudioPlayer != NULL) {
396ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood            mAudioPlayer->requestExit();
397ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood        }
398d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester    }
399d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester}
400d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester
401083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall// Parse a color represented as an HTML-style 'RRGGBB' string: each pair of
402083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall// characters in str is a hex number in [0, 255], which are converted to
403083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall// floating point values in the range [0.0, 1.0] and placed in the
404083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall// corresponding elements of color.
405083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall//
406083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall// If the input string isn't valid, parseColor returns false and color is
407083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall// left unchanged.
408083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hallstatic bool parseColor(const char str[7], float color[3]) {
409083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall    float tmpColor[3];
410083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall    for (int i = 0; i < 3; i++) {
411083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall        int val = 0;
412083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall        for (int j = 0; j < 2; j++) {
413083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall            val *= 16;
414083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall            char c = str[2*i + j];
415083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall            if      (c >= '0' && c <= '9') val += c - '0';
416083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall            else if (c >= 'A' && c <= 'F') val += (c - 'A') + 10;
417083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall            else if (c >= 'a' && c <= 'f') val += (c - 'a') + 10;
418083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall            else                           return false;
419083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall        }
420083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall        tmpColor[i] = static_cast<float>(val) / 255.0f;
421083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall    }
422083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall    memcpy(color, tmpColor, sizeof(tmpColor));
423083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall    return true;
424083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall}
425083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall
42639218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy
42739218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyystatic bool readFile(ZipFileRO* zip, const char* name, String8& outString)
428a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian{
42939218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    ZipEntryRO entry = zip->findEntryByName(name);
430ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood    ALOGE_IF(!entry, "couldn't find %s", name);
431ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood    if (!entry) {
432afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath        return false;
433afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    }
434a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian
43539218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    FileMap* entryMap = zip->createEntryFileMap(entry);
43639218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    zip->releaseEntry(entry);
437ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood    ALOGE_IF(!entryMap, "entryMap is null");
438ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood    if (!entryMap) {
439a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian        return false;
440a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    }
441a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian
442ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood    outString.setTo((char const*)entryMap->getDataPtr(), entryMap->getDataLength());
443688ff4cf0f93d1a886437884f23874e5595d59a3Narayan Kamath    delete entryMap;
444ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood    return true;
445ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood}
446ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood
44739218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyybool BootAnimation::parseAnimationDesc(Animation& animation)
448ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood{
449ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood    String8 desString;
450ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood
45139218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    if (!readFile(animation.zip, "desc.txt", desString)) {
452ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood        return false;
453ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood    }
454a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    char const* s = desString.string();
455a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian
456ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood    // Create and initialize an AudioPlayer if we have an audio_conf.txt file
457ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood    String8 audioConf;
45839218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    if (readFile(animation.zip, "audio_conf.txt", audioConf)) {
459ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood        mAudioPlayer = new AudioPlayer;
460ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood        if (!mAudioPlayer->init(audioConf.string())) {
461ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood            ALOGE("mAudioPlayer.init failed");
462ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood            mAudioPlayer = NULL;
463ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood        }
464ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood    }
465ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood
466a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    // Parse the description file
467a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    for (;;) {
468a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian        const char* endl = strstr(s, "\n");
469cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe        if (endl == NULL) break;
470a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian        String8 line(s, endl - s);
471a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian        const char* l = line.string();
472a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian        int fps, width, height, count, pause;
473afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath        char path[ANIM_ENTRY_NAME_MAX];
474083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall        char color[7] = "000000"; // default to black if unspecified
475083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall
476d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester        char pathType;
477a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian        if (sscanf(l, "%d %d %d", &width, &height, &fps) == 3) {
478083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall            // ALOGD("> w=%d, h=%d, fps=%d", width, height, fps);
479a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian            animation.width = width;
480a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian            animation.height = height;
481a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian            animation.fps = fps;
482a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian        }
483083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall        else if (sscanf(l, " %c %d %d %s #%6s", &pathType, &count, &pause, path, color) >= 4) {
484083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall            // ALOGD("> type=%c, count=%d, pause=%d, path=%s, color=%s", pathType, count, pause, path, color);
485a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian            Animation::Part part;
486d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester            part.playUntilComplete = pathType == 'c';
487a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian            part.count = count;
488a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian            part.pause = pause;
489a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian            part.path = path;
490ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood            part.audioFile = NULL;
49139218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy            part.animation = NULL;
492083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall            if (!parseColor(color, part.backgroundColor)) {
493083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall                ALOGE("> invalid color '#%s'", color);
494083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall                part.backgroundColor[0] = 0.0f;
495083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall                part.backgroundColor[1] = 0.0f;
496083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall                part.backgroundColor[2] = 0.0f;
497083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall            }
498a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian            animation.parts.add(part);
499a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian        }
50039218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy        else if (strcmp(l, "$SYSTEM") == 0) {
50139218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy            // ALOGD("> SYSTEM");
50239218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy            Animation::Part part;
50339218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy            part.playUntilComplete = false;
50439218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy            part.count = 1;
50539218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy            part.pause = 0;
50639218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy            part.audioFile = NULL;
50739218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy            part.animation = loadAnimation(String8(SYSTEM_BOOTANIMATION_FILE));
50839218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy            if (part.animation != NULL)
50939218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy                animation.parts.add(part);
51039218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy        }
511a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian        s = ++endl;
512a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    }
513a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian
51439218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    return true;
51539218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy}
51639218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy
51739218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyybool BootAnimation::preloadZip(Animation& animation)
51839218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy{
519a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    // read all the data structures
520a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    const size_t pcount = animation.parts.size();
521afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    void *cookie = NULL;
52239218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    ZipFileRO* mZip = animation.zip;
523afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    if (!mZip->startIteration(&cookie)) {
524afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath        return false;
525afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    }
526afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath
527afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    ZipEntryRO entry;
528afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    char name[ANIM_ENTRY_NAME_MAX];
529afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    while ((entry = mZip->nextEntry(cookie)) != NULL) {
530afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath        const int foundEntryName = mZip->getEntryFileName(entry, name, ANIM_ENTRY_NAME_MAX);
531afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath        if (foundEntryName > ANIM_ENTRY_NAME_MAX || foundEntryName == -1) {
532afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath            ALOGE("Error fetching entry file name");
533afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath            continue;
534afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath        }
535afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath
536afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath        const String8 entryName(name);
537afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath        const String8 path(entryName.getPathDir());
538afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath        const String8 leaf(entryName.getPathLeaf());
539afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath        if (leaf.size() > 0) {
540afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath            for (size_t j=0 ; j<pcount ; j++) {
541afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath                if (path == animation.parts[j].path) {
5424600dd053dbdbd4b95f3b11057a1cc55b99f9c77Narayan Kamath                    uint16_t method;
543afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath                    // supports only stored png files
544afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath                    if (mZip->getEntryInfo(entry, &method, NULL, NULL, NULL, NULL, NULL)) {
545afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath                        if (method == ZipFileRO::kCompressStored) {
546afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath                            FileMap* map = mZip->createEntryFileMap(entry);
547afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath                            if (map) {
548afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath                                Animation::Part& part(animation.parts.editItemAt(j));
549ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood                                if (leaf == "audio.wav") {
550ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood                                    // a part may have at most one audio file
551ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood                                    part.audioFile = map;
552ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood                                } else {
553ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood                                    Animation::Frame frame;
554ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood                                    frame.name = leaf;
555ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood                                    frame.map = map;
556ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood                                    part.frames.add(frame);
557ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood                                }
558a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian                            }
559a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian                        }
560a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian                    }
561a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian                }
562a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian            }
563a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian        }
564a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    }
565a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian
566afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    mZip->endIteration(cookie);
567afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath
56839218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    return true;
56939218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy}
57039218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy
57139218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyybool BootAnimation::movie()
57239218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy{
57339218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy
57439218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    Animation* animation = loadAnimation(mZipFileName);
57539218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    if (animation == NULL)
57639218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy        return false;
57739218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy
57839218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    // clear screen
579a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    glShadeModel(GL_FLAT);
580a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    glDisable(GL_DITHER);
581a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    glDisable(GL_SCISSOR_TEST);
582a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    glDisable(GL_BLEND);
583a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian
584a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    glBindTexture(GL_TEXTURE_2D, 0);
585a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    glEnable(GL_TEXTURE_2D);
586a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
587a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
588a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
589a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
590a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
591a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian
59239218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    playAnimation(*animation);
59339218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    releaseAnimation(animation);
59439218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy
59539218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    return false;
59639218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy}
59739218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy
59839218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyybool BootAnimation::playAnimation(const Animation& animation)
59939218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy{
60039218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    const size_t pcount = animation.parts.size();
60139218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy
602a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    const int xc = (mWidth - animation.width) / 2;
603a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    const int yc = ((mHeight - animation.height) / 2);
604a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    nsecs_t frameDuration = s2ns(1) / animation.fps;
605a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian
6069f3020db15e50d07ee1ace42e47d90b076f2ce54Mathias Agopian    Region clearReg(Rect(mWidth, mHeight));
6079f3020db15e50d07ee1ace42e47d90b076f2ce54Mathias Agopian    clearReg.subtractSelf(Rect(xc, yc, xc+animation.width, yc+animation.height));
6089f3020db15e50d07ee1ace42e47d90b076f2ce54Mathias Agopian
609afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath    for (size_t i=0 ; i<pcount ; i++) {
610a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian        const Animation::Part& part(animation.parts[i]);
611a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian        const size_t fcount = part.frames.size();
612a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian        glBindTexture(GL_TEXTURE_2D, 0);
613a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian
61439218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy        // Handle animation package
61539218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy        if (part.animation != NULL) {
61639218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy            playAnimation(*part.animation);
61739218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy            if (exitPending())
61839218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy                break;
61939218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy            continue; //to next part
62039218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy        }
62139218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy
622a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian        for (int r=0 ; !part.count || r<part.count ; r++) {
623d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester            // Exit any non playuntil complete parts immediately
624d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester            if(exitPending() && !part.playUntilComplete)
625d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester                break;
626d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester
627ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood            // only play audio file the first time we animate the part
628ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood            if (r == 0 && mAudioPlayer != NULL && part.audioFile) {
629ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood                mAudioPlayer->playFile(part.audioFile);
630ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood            }
631ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood
632083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall            glClearColor(
633083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall                    part.backgroundColor[0],
634083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall                    part.backgroundColor[1],
635083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall                    part.backgroundColor[2],
636083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall                    1.0f);
637083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall
638afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath            for (size_t j=0 ; j<fcount && (!exitPending() || part.playUntilComplete) ; j++) {
639a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian                const Animation::Frame& frame(part.frames[j]);
640db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian                nsecs_t lastFrame = systemTime();
641a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian
642a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian                if (r > 0) {
643a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian                    glBindTexture(GL_TEXTURE_2D, frame.tid);
644a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian                } else {
645a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian                    if (part.count != 1) {
646a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian                        glGenTextures(1, &frame.tid);
647a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian                        glBindTexture(GL_TEXTURE_2D, frame.tid);
648a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian                        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
649a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian                        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
650a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian                    }
6510c1eeb3c8ab53954218d3b8f4be08ff21be3e985Mykola Kondratenko                    initTexture(frame);
652a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian                }
653a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian
6549f3020db15e50d07ee1ace42e47d90b076f2ce54Mathias Agopian                if (!clearReg.isEmpty()) {
6559f3020db15e50d07ee1ace42e47d90b076f2ce54Mathias Agopian                    Region::const_iterator head(clearReg.begin());
6569f3020db15e50d07ee1ace42e47d90b076f2ce54Mathias Agopian                    Region::const_iterator tail(clearReg.end());
6579f3020db15e50d07ee1ace42e47d90b076f2ce54Mathias Agopian                    glEnable(GL_SCISSOR_TEST);
6589f3020db15e50d07ee1ace42e47d90b076f2ce54Mathias Agopian                    while (head != tail) {
659cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe                        const Rect& r2(*head++);
660cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe                        glScissor(r2.left, mHeight - r2.bottom,
661cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe                                r2.width(), r2.height());
6629f3020db15e50d07ee1ace42e47d90b076f2ce54Mathias Agopian                        glClear(GL_COLOR_BUFFER_BIT);
6639f3020db15e50d07ee1ace42e47d90b076f2ce54Mathias Agopian                    }
6649f3020db15e50d07ee1ace42e47d90b076f2ce54Mathias Agopian                    glDisable(GL_SCISSOR_TEST);
6659f3020db15e50d07ee1ace42e47d90b076f2ce54Mathias Agopian                }
666d13d504e4b7548f0ce4f9c4f0eee5c1ac2ce6794Chris Elliott                // specify the y center as ceiling((mHeight - animation.height) / 2)
667d13d504e4b7548f0ce4f9c4f0eee5c1ac2ce6794Chris Elliott                // which is equivalent to mHeight - (yc + animation.height)
668d13d504e4b7548f0ce4f9c4f0eee5c1ac2ce6794Chris Elliott                glDrawTexiOES(xc, mHeight - (yc + animation.height),
669d13d504e4b7548f0ce4f9c4f0eee5c1ac2ce6794Chris Elliott                              0, animation.width, animation.height);
670a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian                eglSwapBuffers(mDisplay, mSurface);
671a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian
672a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian                nsecs_t now = systemTime();
673a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian                nsecs_t delay = frameDuration - (now - lastFrame);
674db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian                //ALOGD("%lld, %lld", ns2ms(now - lastFrame), ns2ms(delay));
675a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian                lastFrame = now;
676db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian
677db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian                if (delay > 0) {
678db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian                    struct timespec spec;
679db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian                    spec.tv_sec  = (now + delay) / 1000000000;
680db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian                    spec.tv_nsec = (now + delay) % 1000000000;
681db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian                    int err;
682db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian                    do {
683db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian                        err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL);
684db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian                    } while (err<0 && errno == EINTR);
685db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian                }
686d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester
687d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester                checkExit();
688a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian            }
689d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester
690a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian            usleep(part.pause * ns2us(frameDuration));
691d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester
692d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester            // For infinite parts, we've now played them at least once, so perhaps exit
693d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester            if(exitPending() && !part.count)
694d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester                break;
695a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian        }
696a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian
697a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian        // free the textures for this part
698a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian        if (part.count != 1) {
699afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath            for (size_t j=0 ; j<fcount ; j++) {
700a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian                const Animation::Frame& frame(part.frames[j]);
701a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian                glDeleteTextures(1, &frame.tid);
702a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian            }
703a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian        }
704a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian    }
70539218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    return true;
70639218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy}
707a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian
70839218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyyvoid BootAnimation::releaseAnimation(Animation* animation) const
70939218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy{
71039218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    for (Vector<Animation::Part>::iterator it = animation->parts.begin(),
71139218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy         e = animation->parts.end(); it != e; ++it) {
71239218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy        if (it->animation)
71339218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy            releaseAnimation(it->animation);
71439218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    }
71539218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    if (animation->zip)
71639218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy        delete animation->zip;
71739218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    delete animation;
718a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian}
719a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian
72039218ba26d5bb8646f04273f2c3731598721c1daAndriy NaborskyyBootAnimation::Animation* BootAnimation::loadAnimation(const String8& fn)
72139218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy{
72239218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    if (mLoadedFiles.indexOf(fn) >= 0) {
72339218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy        ALOGE("File \"%s\" is already loaded. Cyclic ref is not allowed",
72439218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy            fn.string());
72539218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy        return NULL;
72639218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    }
72739218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    ZipFileRO *zip = ZipFileRO::open(fn);
72839218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    if (zip == NULL) {
72939218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy        ALOGE("Failed to open animation zip \"%s\": %s",
73039218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy            fn.string(), strerror(errno));
73139218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy        return NULL;
73239218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    }
73339218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy
73439218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    Animation *animation =  new Animation;
73539218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    animation->fileName = fn;
73639218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    animation->zip = zip;
73739218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    mLoadedFiles.add(animation->fileName);
73839218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy
73939218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    parseAnimationDesc(*animation);
74039218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    preloadZip(*animation);
74139218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy
74239218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    mLoadedFiles.remove(fn);
74339218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy    return animation;
74439218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy}
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project; // namespace android
749