BootAnimation.cpp revision 9748086fe267e21d243a49df1775905094a28dd9
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> 219748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi#include <sys/inotify.h> 229748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi#include <sys/poll.h> 239748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi#include <sys/stat.h> 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/types.h> 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <math.h> 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <fcntl.h> 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/misc.h> 28b4d5a72691846bce5779cc3db056f09a5031d7ccMathias Agopian#include <signal.h> 29bb94f3107ea567ddf67bed4617c3bcbd602538dfElliott Hughes#include <time.h> 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 31bd9a08d318f94a3d0b2f8f9d7b16b10736d80c5cJason parks#include <cutils/properties.h> 32bd9a08d318f94a3d0b2f8f9d7b16b10736d80c5cJason parks 33b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <androidfw/AssetManager.h> 34ac31a3b8b09aba1c5ebc73f0cf65cac2210aa6b7Mathias Agopian#include <binder/IPCThreadState.h> 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Atomic.h> 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Errors.h> 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Log.h> 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <ui/PixelFormat.h> 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <ui/Rect.h> 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <ui/Region.h> 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <ui/DisplayInfo.h> 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 440b722fe9ce98d97dbcb6fefd170b85ab7037e528Jeff Brown#include <gui/ISurfaceComposer.h> 458335f1ccccedb6655d96d9d5b697a7f0938235ddMathias Agopian#include <gui/Surface.h> 468335f1ccccedb6655d96d9d5b697a7f0938235ddMathias Agopian#include <gui/SurfaceComposerClient.h> 47000479f9e325b4e426a67033abd92d47da412725Mathias Agopian 48cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe// TODO: Fix Skia. 49cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe#pragma GCC diagnostic push 50cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe#pragma GCC diagnostic ignored "-Wunused-parameter" 51eece0dda56ae29fff6e9003df97594f6ac50b6e2Derek Sollenberger#include <SkBitmap.h> 52eece0dda56ae29fff6e9003df97594f6ac50b6e2Derek Sollenberger#include <SkStream.h> 53eece0dda56ae29fff6e9003df97594f6ac50b6e2Derek Sollenberger#include <SkImageDecoder.h> 54cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe#pragma GCC diagnostic pop 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <GLES/gl.h> 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <GLES/glext.h> 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <EGL/eglext.h> 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "BootAnimation.h" 61ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood#include "AudioPlayer.h" 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android { 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 659748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchistatic const char OEM_BOOTANIMATION_FILE[] = "/oem/media/bootanimation.zip"; 669748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchistatic const char SYSTEM_BOOTANIMATION_FILE[] = "/system/media/bootanimation.zip"; 679748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchistatic const char SYSTEM_ENCRYPTED_BOOTANIMATION_FILE[] = "/system/media/bootanimation-encrypted.zip"; 689748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchistatic const char SYSTEM_DATA_DIR_PATH[] = "/data/system"; 699748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchistatic const char SYSTEM_TIME_DIR_NAME[] = "time"; 709748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchistatic const char SYSTEM_TIME_DIR_PATH[] = "/data/system/time"; 719748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchistatic const char LAST_TIME_CHANGED_FILE_NAME[] = "last_time_change"; 729748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchistatic const char LAST_TIME_CHANGED_FILE_PATH[] = "/data/system/time/last_time_change"; 739748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchistatic const char ACCURATE_TIME_FLAG_FILE_NAME[] = "time_is_accurate"; 749748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchistatic const char ACCURATE_TIME_FLAG_FILE_PATH[] = "/data/system/time/time_is_accurate"; 759748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchistatic const char EXIT_PROP_NAME[] = "service.bootanim.exit"; 76afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamathstatic const int ANIM_ENTRY_NAME_MAX = 256; 77afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// --------------------------------------------------------------------------- 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 809748086fe267e21d243a49df1775905094a28dd9Damien BargiacchiBootAnimation::BootAnimation() : Thread(false), mClockEnabled(true), mTimeIsAccurate(false), 819748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi mTimeCheckThread(NULL) { 82627e7b50be41e4fdee758a1bfad3a55de56b4e27Mathias Agopian mSession = new SurfaceComposerClient(); 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 859748086fe267e21d243a49df1775905094a28dd9Damien BargiacchiBootAnimation::~BootAnimation() {} 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid BootAnimation::onFirstRef() { 88bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian status_t err = mSession->linkToComposerDeath(this); 893762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE_IF(err, "linkToComposerDeath failed (%s) ", strerror(-err)); 908434c5369304e639efe8eab368ca410c589d87c2Mathias Agopian if (err == NO_ERROR) { 91bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian run("BootAnimation", PRIORITY_DISPLAY); 92bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian } 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 95bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopiansp<SurfaceComposerClient> BootAnimation::session() const { 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mSession; 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 99bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian 100afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamathvoid BootAnimation::binderDied(const wp<IBinder>&) 101bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian{ 102bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian // woah, surfaceflinger died! 1035baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("SurfaceFlinger died, exiting..."); 104bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian 105bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian // calling requestExit() is not enough here because the Surface code 106bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian // might be blocked on a condition variable that will never be updated. 107bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian kill( getpid(), SIGKILL ); 108bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian requestExit(); 109ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood if (mAudioPlayer != NULL) { 110ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood mAudioPlayer->requestExit(); 111ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood } 112bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian} 113bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t BootAnimation::initTexture(Texture* texture, AssetManager& assets, 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char* name) { 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Asset* asset = assets.open(name, Asset::ACCESS_BUFFER); 117cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe if (asset == NULL) 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_INIT; 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SkBitmap bitmap; 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SkImageDecoder::DecodeMemory(asset->getBuffer(false), asset->getLength(), 12142a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed &bitmap, kUnknown_SkColorType, SkImageDecoder::kDecodePixels_Mode); 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project asset->close(); 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delete asset; 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // ensure we can call getPixels(). No need to call unlock, since the 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // bitmap will go out of scope when we return from this method. 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bitmap.lockPixels(); 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const int w = bitmap.width(); 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const int h = bitmap.height(); 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const void* p = bitmap.getPixels(); 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project GLint crop[4] = { 0, h, w, -h }; 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project texture->w = w; 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project texture->h = h; 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project glGenTextures(1, &texture->name); 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project glBindTexture(GL_TEXTURE_2D, texture->name); 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14042a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed switch (bitmap.colorType()) { 14142a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed case kAlpha_8_SkColorType: 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_ALPHA, 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project GL_UNSIGNED_BYTE, p); 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 14542a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed case kARGB_4444_SkColorType: 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project GL_UNSIGNED_SHORT_4_4_4_4, p); 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 14942a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed case kN32_SkColorType: 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project GL_UNSIGNED_BYTE, p); 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 15342a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed case kRGB_565_SkColorType: 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project GL_UNSIGNED_SHORT_5_6_5, p); 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_ERROR; 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1690c1eeb3c8ab53954218d3b8f4be08ff21be3e985Mykola Kondratenkostatus_t BootAnimation::initTexture(const Animation::Frame& frame) 170a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian{ 171a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian //StopWatch watch("blah"); 172a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 173a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian SkBitmap bitmap; 1740c1eeb3c8ab53954218d3b8f4be08ff21be3e985Mykola Kondratenko SkMemoryStream stream(frame.map->getDataPtr(), frame.map->getDataLength()); 1752b99e55ee3a0956a43a276f8018356ff9d08eafcMathias Agopian SkImageDecoder* codec = SkImageDecoder::Factory(&stream); 176cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe if (codec != NULL) { 177c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes codec->setDitherImage(false); 1782b99e55ee3a0956a43a276f8018356ff9d08eafcMathias Agopian codec->decode(&stream, &bitmap, 17942a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed kN32_SkColorType, 1802b99e55ee3a0956a43a276f8018356ff9d08eafcMathias Agopian SkImageDecoder::kDecodePixels_Mode); 1812b99e55ee3a0956a43a276f8018356ff9d08eafcMathias Agopian delete codec; 1822b99e55ee3a0956a43a276f8018356ff9d08eafcMathias Agopian } 183a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 1840c1eeb3c8ab53954218d3b8f4be08ff21be3e985Mykola Kondratenko // FileMap memory is never released until application exit. 1850c1eeb3c8ab53954218d3b8f4be08ff21be3e985Mykola Kondratenko // Release it now as the texture is already loaded and the memory used for 1860c1eeb3c8ab53954218d3b8f4be08ff21be3e985Mykola Kondratenko // the packed resource can be released. 187688ff4cf0f93d1a886437884f23874e5595d59a3Narayan Kamath delete frame.map; 1880c1eeb3c8ab53954218d3b8f4be08ff21be3e985Mykola Kondratenko 189a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian // ensure we can call getPixels(). No need to call unlock, since the 190a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian // bitmap will go out of scope when we return from this method. 191a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian bitmap.lockPixels(); 192a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 193a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian const int w = bitmap.width(); 194a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian const int h = bitmap.height(); 195a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian const void* p = bitmap.getPixels(); 196a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 197a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian GLint crop[4] = { 0, h, w, -h }; 198a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian int tw = 1 << (31 - __builtin_clz(w)); 199a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian int th = 1 << (31 - __builtin_clz(h)); 200a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian if (tw < w) tw <<= 1; 201a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian if (th < h) th <<= 1; 202a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 20342a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed switch (bitmap.colorType()) { 20442a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed case kN32_SkColorType: 205a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian if (tw != w || th != h) { 206a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tw, th, 0, GL_RGBA, 207a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian GL_UNSIGNED_BYTE, 0); 208a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glTexSubImage2D(GL_TEXTURE_2D, 0, 209a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, p); 210a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } else { 211a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tw, th, 0, GL_RGBA, 212a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian GL_UNSIGNED_BYTE, p); 213a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 214a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian break; 215a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 21642a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed case kRGB_565_SkColorType: 217a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian if (tw != w || th != h) { 218a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tw, th, 0, GL_RGB, 219a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian GL_UNSIGNED_SHORT_5_6_5, 0); 220a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glTexSubImage2D(GL_TEXTURE_2D, 0, 221a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 0, 0, w, h, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, p); 222a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } else { 223a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tw, th, 0, GL_RGB, 224a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian GL_UNSIGNED_SHORT_5_6_5, p); 225a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 226a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian break; 227a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian default: 228a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian break; 229a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 230a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 231a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); 232a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 233a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian return NO_ERROR; 234a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian} 235a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t BootAnimation::readyToRun() { 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAssets.addDefaultAssets(); 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2390b722fe9ce98d97dbcb6fefd170b85ab7037e528Jeff Brown sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay( 2400b722fe9ce98d97dbcb6fefd170b85ab7037e528Jeff Brown ISurfaceComposer::eDisplayIdMain)); 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DisplayInfo dinfo; 2420b722fe9ce98d97dbcb6fefd170b85ab7037e528Jeff Brown status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &dinfo); 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (status) 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // create the native surface 2470b722fe9ce98d97dbcb6fefd170b85ab7037e528Jeff Brown sp<SurfaceControl> control = session()->createSurface(String8("BootAnimation"), 2480b722fe9ce98d97dbcb6fefd170b85ab7037e528Jeff Brown dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565); 249439863f3b3e725b5de1cba4940a21900369961c0Mathias Agopian 250439863f3b3e725b5de1cba4940a21900369961c0Mathias Agopian SurfaceComposerClient::openGlobalTransaction(); 25117f638b39f2e8b610ecfa1290e5bc42ab7700c98Mathias Agopian control->setLayer(0x40000000); 252439863f3b3e725b5de1cba4940a21900369961c0Mathias Agopian SurfaceComposerClient::closeGlobalTransaction(); 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 25417f638b39f2e8b610ecfa1290e5bc42ab7700c98Mathias Agopian sp<Surface> s = control->getSurface(); 25517f638b39f2e8b610ecfa1290e5bc42ab7700c98Mathias Agopian 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // initialize opengl and egl 257738b9a45399485893fa9541fae19c47e01bc4af4Mathias Agopian const EGLint attribs[] = { 2581b253b702a356619ae3c5e68ee92062b5305c5d7Mathias Agopian EGL_RED_SIZE, 8, 2591b253b702a356619ae3c5e68ee92062b5305c5d7Mathias Agopian EGL_GREEN_SIZE, 8, 2601b253b702a356619ae3c5e68ee92062b5305c5d7Mathias Agopian EGL_BLUE_SIZE, 8, 261a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian EGL_DEPTH_SIZE, 0, 262a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian EGL_NONE 263738b9a45399485893fa9541fae19c47e01bc4af4Mathias Agopian }; 264cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe EGLint w, h; 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGLint numConfigs; 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGLConfig config; 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGLSurface surface; 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGLContext context; 269627e7b50be41e4fdee758a1bfad3a55de56b4e27Mathias Agopian 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); 271627e7b50be41e4fdee758a1bfad3a55de56b4e27Mathias Agopian 272627e7b50be41e4fdee758a1bfad3a55de56b4e27Mathias Agopian eglInitialize(display, 0, 0); 2731b253b702a356619ae3c5e68ee92062b5305c5d7Mathias Agopian eglChooseConfig(display, attribs, &config, 1, &numConfigs); 2741473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian surface = eglCreateWindowSurface(display, config, s.get(), NULL); 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project context = eglCreateContext(display, config, NULL, NULL); 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project eglQuerySurface(display, surface, EGL_WIDTH, &w); 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project eglQuerySurface(display, surface, EGL_HEIGHT, &h); 278a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 279abac01052c1c40f8582fe9f010c2efe6013e25c6Mathias Agopian if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) 280abac01052c1c40f8582fe9f010c2efe6013e25c6Mathias Agopian return NO_INIT; 281a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDisplay = display; 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSurface = surface; 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWidth = w; 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHeight = h; 28717f638b39f2e8b610ecfa1290e5bc42ab7700c98Mathias Agopian mFlingerSurfaceControl = control; 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFlingerSurface = s; 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 290c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes // If the device has encryption turned on or is in process 291bd9a08d318f94a3d0b2f8f9d7b16b10736d80c5cJason parks // of being encrypted we show the encrypted boot animation. 292bd9a08d318f94a3d0b2f8f9d7b16b10736d80c5cJason parks char decrypt[PROPERTY_VALUE_MAX]; 293bd9a08d318f94a3d0b2f8f9d7b16b10736d80c5cJason parks property_get("vold.decrypt", decrypt, ""); 294bd9a08d318f94a3d0b2f8f9d7b16b10736d80c5cJason parks 295bd9a08d318f94a3d0b2f8f9d7b16b10736d80c5cJason parks bool encryptedAnimation = atoi(decrypt) != 0 || !strcmp("trigger_restart_min_framework", decrypt); 296bd9a08d318f94a3d0b2f8f9d7b16b10736d80c5cJason parks 29739218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy if (encryptedAnimation && (access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0)) { 29839218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy mZipFileName = SYSTEM_ENCRYPTED_BOOTANIMATION_FILE; 29939218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy } 30039218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy else if (access(OEM_BOOTANIMATION_FILE, R_OK) == 0) { 30139218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy mZipFileName = OEM_BOOTANIMATION_FILE; 30239218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy } 30339218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy else if (access(SYSTEM_BOOTANIMATION_FILE, R_OK) == 0) { 30439218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy mZipFileName = SYSTEM_BOOTANIMATION_FILE; 305bd9a08d318f94a3d0b2f8f9d7b16b10736d80c5cJason parks } 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_ERROR; 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 309a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopianbool BootAnimation::threadLoop() 310a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian{ 311a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian bool r; 312afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath // We have no bootanimation file, so we use the stock android logo 313afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath // animation. 31439218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy if (mZipFileName.isEmpty()) { 315a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian r = android(); 316a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } else { 317a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian r = movie(); 318a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 319a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project eglDestroyContext(mDisplay, mContext); 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project eglDestroySurface(mDisplay, mSurface); 3236cf0db228ca275dfcda57d79c55e5fa306809632Mathias Agopian mFlingerSurface.clear(); 32417f638b39f2e8b610ecfa1290e5bc42ab7700c98Mathias Agopian mFlingerSurfaceControl.clear(); 325627e7b50be41e4fdee758a1bfad3a55de56b4e27Mathias Agopian eglTerminate(mDisplay); 326627e7b50be41e4fdee758a1bfad3a55de56b4e27Mathias Agopian IPCThreadState::self()->stopProcess(); 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return r; 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 330a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopianbool BootAnimation::android() 331a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian{ 332b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png"); 333b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian initTexture(&mAndroid[1], mAssets, "images/android-logo-shine.png"); 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // clear screen 336a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glShadeModel(GL_FLAT); 337b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian glDisable(GL_DITHER); 338b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian glDisable(GL_SCISSOR_TEST); 33959f19e48c1c043bb9debdc35d166e397e2125d33Mathias Agopian glClearColor(0,0,0,1); 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project glClear(GL_COLOR_BUFFER_BIT); 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project eglSwapBuffers(mDisplay, mSurface); 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 343a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glEnable(GL_TEXTURE_2D); 344a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 345a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 346b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian const GLint xc = (mWidth - mAndroid[0].w) / 2; 347b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian const GLint yc = (mHeight - mAndroid[0].h) / 2; 348b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian const Rect updateRect(xc, yc, xc + mAndroid[0].w, yc + mAndroid[0].h); 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(), 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project updateRect.height()); 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 353b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian // Blend state 354b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 355b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 356b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const nsecs_t startTime = systemTime(); 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 3591379665abdb8330caf813fb77902914d1545bcd9Mathias Agopian nsecs_t now = systemTime(); 3601379665abdb8330caf813fb77902914d1545bcd9Mathias Agopian double time = now - startTime; 361b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian float t = 4.0f * float(time / us2ns(16667)) / mAndroid[1].w; 362b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian GLint offset = (1 - (t - floorf(t))) * mAndroid[1].w; 363b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian GLint x = xc - offset; 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3658166864e42bc20c1544b2028e8dd65b90f29a0eaMathias Agopian glDisable(GL_SCISSOR_TEST); 3668166864e42bc20c1544b2028e8dd65b90f29a0eaMathias Agopian glClear(GL_COLOR_BUFFER_BIT); 3678166864e42bc20c1544b2028e8dd65b90f29a0eaMathias Agopian 3688166864e42bc20c1544b2028e8dd65b90f29a0eaMathias Agopian glEnable(GL_SCISSOR_TEST); 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project glDisable(GL_BLEND); 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project glBindTexture(GL_TEXTURE_2D, mAndroid[1].name); 371b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian glDrawTexiOES(x, yc, 0, mAndroid[1].w, mAndroid[1].h); 372b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian glDrawTexiOES(x + mAndroid[1].w, yc, 0, mAndroid[1].w, mAndroid[1].h); 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 374b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian glEnable(GL_BLEND); 375b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian glBindTexture(GL_TEXTURE_2D, mAndroid[0].name); 376b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian glDrawTexiOES(xc, yc, 0, mAndroid[0].w, mAndroid[0].h); 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 378627e7b50be41e4fdee758a1bfad3a55de56b4e27Mathias Agopian EGLBoolean res = eglSwapBuffers(mDisplay, mSurface); 379627e7b50be41e4fdee758a1bfad3a55de56b4e27Mathias Agopian if (res == EGL_FALSE) 380627e7b50be41e4fdee758a1bfad3a55de56b4e27Mathias Agopian break; 381627e7b50be41e4fdee758a1bfad3a55de56b4e27Mathias Agopian 3821379665abdb8330caf813fb77902914d1545bcd9Mathias Agopian // 12fps: don't animate too fast to preserve CPU 3831379665abdb8330caf813fb77902914d1545bcd9Mathias Agopian const nsecs_t sleepTime = 83333 - ns2us(systemTime() - now); 3841379665abdb8330caf813fb77902914d1545bcd9Mathias Agopian if (sleepTime > 0) 385a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian usleep(sleepTime); 386d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester 387d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester checkExit(); 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (!exitPending()); 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project glDeleteTextures(1, &mAndroid[0].name); 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project glDeleteTextures(1, &mAndroid[1].name); 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 395a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 396d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hestervoid BootAnimation::checkExit() { 397d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester // Allow surface flinger to gracefully request shutdown 398d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester char value[PROPERTY_VALUE_MAX]; 399d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester property_get(EXIT_PROP_NAME, value, "0"); 400d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester int exitnow = atoi(value); 401d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester if (exitnow) { 402d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester requestExit(); 403ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood if (mAudioPlayer != NULL) { 404ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood mAudioPlayer->requestExit(); 405ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood } 406d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester } 407d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester} 408d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester 409083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall// Parse a color represented as an HTML-style 'RRGGBB' string: each pair of 410083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall// characters in str is a hex number in [0, 255], which are converted to 411083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall// floating point values in the range [0.0, 1.0] and placed in the 412083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall// corresponding elements of color. 413083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall// 414083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall// If the input string isn't valid, parseColor returns false and color is 415083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall// left unchanged. 416083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hallstatic bool parseColor(const char str[7], float color[3]) { 417083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall float tmpColor[3]; 418083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall for (int i = 0; i < 3; i++) { 419083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall int val = 0; 420083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall for (int j = 0; j < 2; j++) { 421083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall val *= 16; 422083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall char c = str[2*i + j]; 423083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall if (c >= '0' && c <= '9') val += c - '0'; 424083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall else if (c >= 'A' && c <= 'F') val += (c - 'A') + 10; 425083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall else if (c >= 'a' && c <= 'f') val += (c - 'a') + 10; 426083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall else return false; 427083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall } 428083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall tmpColor[i] = static_cast<float>(val) / 255.0f; 429083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall } 430083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall memcpy(color, tmpColor, sizeof(tmpColor)); 431083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall return true; 432083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall} 433083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall 43439218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy 43539218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyystatic bool readFile(ZipFileRO* zip, const char* name, String8& outString) 436a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian{ 43739218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy ZipEntryRO entry = zip->findEntryByName(name); 438ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood ALOGE_IF(!entry, "couldn't find %s", name); 439ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood if (!entry) { 440afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath return false; 441afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath } 442a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 44339218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy FileMap* entryMap = zip->createEntryFileMap(entry); 44439218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy zip->releaseEntry(entry); 445ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood ALOGE_IF(!entryMap, "entryMap is null"); 446ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood if (!entryMap) { 447a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian return false; 448a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 449a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 450ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood outString.setTo((char const*)entryMap->getDataPtr(), entryMap->getDataLength()); 451688ff4cf0f93d1a886437884f23874e5595d59a3Narayan Kamath delete entryMap; 452ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood return true; 453ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood} 454ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood 455a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi// The time glyphs are stored in a single image of height 64 pixels. Each digit is 40 pixels wide, 456a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi// and the colon character is half that at 20 pixels. The glyph order is '0123456789:'. 457a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi// We render 24 hour time. 458a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchivoid BootAnimation::drawTime(const Texture& clockTex, const int yPos) { 459a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi static constexpr char TIME_FORMAT[] = "%H:%M"; 460a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi static constexpr int TIME_LENGTH = sizeof(TIME_FORMAT); 461a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi 462a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi static constexpr int DIGIT_HEIGHT = 64; 463a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi static constexpr int DIGIT_WIDTH = 40; 464a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi static constexpr int COLON_WIDTH = DIGIT_WIDTH / 2; 465a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi static constexpr int TIME_WIDTH = (DIGIT_WIDTH * 4) + COLON_WIDTH; 466a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi 467a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi if (clockTex.h < DIGIT_HEIGHT || clockTex.w < (10 * DIGIT_WIDTH + COLON_WIDTH)) { 468a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi ALOGE("Clock texture is too small; abandoning boot animation clock"); 469a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi mClockEnabled = false; 470a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi return; 471a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi } 472a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi 473a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi time_t rawtime; 474a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi time(&rawtime); 475a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi struct tm* timeInfo = localtime(&rawtime); 476a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi 477a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi char timeBuff[TIME_LENGTH]; 478a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi size_t length = strftime(timeBuff, TIME_LENGTH, TIME_FORMAT, timeInfo); 479a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi 480a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi if (length != TIME_LENGTH - 1) { 481a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi ALOGE("Couldn't format time; abandoning boot animation clock"); 482a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi mClockEnabled = false; 483a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi return; 484a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi } 485a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi 486a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi glEnable(GL_BLEND); // Allow us to draw on top of the animation 487a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi glBindTexture(GL_TEXTURE_2D, clockTex.name); 488a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi 489a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi int xPos = (mWidth - TIME_WIDTH) / 2; 490a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi int cropRect[4] = { 0, DIGIT_HEIGHT, DIGIT_WIDTH, -DIGIT_HEIGHT }; 491a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi 492a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi for (int i = 0; i < TIME_LENGTH - 1; i++) { 493a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi char c = timeBuff[i]; 494a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi int width = DIGIT_WIDTH; 495a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi int pos = c - '0'; // Position in the character list 496a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi if (pos < 0 || pos > 10) { 497a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi continue; 498a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi } 499a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi if (c == ':') { 500a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi width = COLON_WIDTH; 501a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi } 502a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi 503a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi // Crop the texture to only the pixels in the current glyph 504a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi int left = pos * DIGIT_WIDTH; 505a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi cropRect[0] = left; 506a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi cropRect[2] = width; 507a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect); 508a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi 509a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi glDrawTexiOES(xPos, yPos, 0, width, DIGIT_HEIGHT); 510a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi 511a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi xPos += width; 512a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi } 513a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi 514a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi glDisable(GL_BLEND); // Return to the animation's default behaviour 515a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi glBindTexture(GL_TEXTURE_2D, 0); 516a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi} 517a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi 51839218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyybool BootAnimation::parseAnimationDesc(Animation& animation) 519ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood{ 520ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood String8 desString; 521ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood 52239218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy if (!readFile(animation.zip, "desc.txt", desString)) { 523ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood return false; 524ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood } 525a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian char const* s = desString.string(); 526a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 527ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood // Create and initialize an AudioPlayer if we have an audio_conf.txt file 528ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood String8 audioConf; 52939218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy if (readFile(animation.zip, "audio_conf.txt", audioConf)) { 530ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood mAudioPlayer = new AudioPlayer; 531ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood if (!mAudioPlayer->init(audioConf.string())) { 532ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood ALOGE("mAudioPlayer.init failed"); 533ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood mAudioPlayer = NULL; 534ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood } 535ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood } 536ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood 537a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian // Parse the description file 538a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian for (;;) { 539a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian const char* endl = strstr(s, "\n"); 540cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe if (endl == NULL) break; 541a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian String8 line(s, endl - s); 542a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian const char* l = line.string(); 543a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi int fps = 0; 544a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi int width = 0; 545a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi int height = 0; 546a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi int count = 0; 547a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi int pause = 0; 548a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi int clockPosY = -1; 549afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath char path[ANIM_ENTRY_NAME_MAX]; 550083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall char color[7] = "000000"; // default to black if unspecified 551083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall 552d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester char pathType; 553a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian if (sscanf(l, "%d %d %d", &width, &height, &fps) == 3) { 554083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall // ALOGD("> w=%d, h=%d, fps=%d", width, height, fps); 555a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian animation.width = width; 556a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian animation.height = height; 557a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian animation.fps = fps; 558a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi } else if (sscanf(l, " %c %d %d %s #%6s %d", 559a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi &pathType, &count, &pause, path, color, &clockPosY) >= 4) { 560a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi // ALOGD("> type=%c, count=%d, pause=%d, path=%s, color=%s, clockPosY=%d", pathType, count, pause, path, color, clockPosY); 561a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian Animation::Part part; 562d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester part.playUntilComplete = pathType == 'c'; 563a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian part.count = count; 564a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian part.pause = pause; 565a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian part.path = path; 566a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi part.clockPosY = clockPosY; 567ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood part.audioFile = NULL; 56839218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy part.animation = NULL; 569083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall if (!parseColor(color, part.backgroundColor)) { 570083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall ALOGE("> invalid color '#%s'", color); 571083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall part.backgroundColor[0] = 0.0f; 572083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall part.backgroundColor[1] = 0.0f; 573083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall part.backgroundColor[2] = 0.0f; 574083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall } 575a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian animation.parts.add(part); 576a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 57739218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy else if (strcmp(l, "$SYSTEM") == 0) { 57839218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy // ALOGD("> SYSTEM"); 57939218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy Animation::Part part; 58039218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy part.playUntilComplete = false; 58139218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy part.count = 1; 58239218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy part.pause = 0; 58339218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy part.audioFile = NULL; 58439218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy part.animation = loadAnimation(String8(SYSTEM_BOOTANIMATION_FILE)); 58539218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy if (part.animation != NULL) 58639218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy animation.parts.add(part); 58739218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy } 588a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian s = ++endl; 589a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 590a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 59139218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy return true; 59239218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy} 59339218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy 59439218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyybool BootAnimation::preloadZip(Animation& animation) 59539218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy{ 596a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian // read all the data structures 597a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian const size_t pcount = animation.parts.size(); 598afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath void *cookie = NULL; 59939218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy ZipFileRO* mZip = animation.zip; 600afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath if (!mZip->startIteration(&cookie)) { 601afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath return false; 602afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath } 603afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath 604afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath ZipEntryRO entry; 605afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath char name[ANIM_ENTRY_NAME_MAX]; 606afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath while ((entry = mZip->nextEntry(cookie)) != NULL) { 607afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath const int foundEntryName = mZip->getEntryFileName(entry, name, ANIM_ENTRY_NAME_MAX); 608afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath if (foundEntryName > ANIM_ENTRY_NAME_MAX || foundEntryName == -1) { 609afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath ALOGE("Error fetching entry file name"); 610afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath continue; 611afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath } 612afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath 613afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath const String8 entryName(name); 614afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath const String8 path(entryName.getPathDir()); 615afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath const String8 leaf(entryName.getPathLeaf()); 616afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath if (leaf.size() > 0) { 617afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath for (size_t j=0 ; j<pcount ; j++) { 618afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath if (path == animation.parts[j].path) { 6194600dd053dbdbd4b95f3b11057a1cc55b99f9c77Narayan Kamath uint16_t method; 620afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath // supports only stored png files 621afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath if (mZip->getEntryInfo(entry, &method, NULL, NULL, NULL, NULL, NULL)) { 622afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath if (method == ZipFileRO::kCompressStored) { 623afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath FileMap* map = mZip->createEntryFileMap(entry); 624afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath if (map) { 625afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath Animation::Part& part(animation.parts.editItemAt(j)); 626ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood if (leaf == "audio.wav") { 627ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood // a part may have at most one audio file 628ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood part.audioFile = map; 629ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood } else { 630ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood Animation::Frame frame; 631ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood frame.name = leaf; 632ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood frame.map = map; 633ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood part.frames.add(frame); 634ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood } 635a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 636a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 637a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 638a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 639a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 640a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 641a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 642a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 643afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath mZip->endIteration(cookie); 644afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath 64539218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy return true; 64639218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy} 64739218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy 64839218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyybool BootAnimation::movie() 64939218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy{ 65039218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy Animation* animation = loadAnimation(mZipFileName); 65139218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy if (animation == NULL) 65239218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy return false; 65339218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy 6549748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi bool anyPartHasClock = false; 6559748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi for (size_t i=0; i < animation->parts.size(); i++) { 6569748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi if(animation->parts[i].clockPosY >= 0) { 6579748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi anyPartHasClock = true; 6589748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi break; 6599748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 6609748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 6619748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi if (!anyPartHasClock) { 6629748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi mClockEnabled = false; 6639748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 6649748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 665a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi // Blend required to draw time on top of animation frames. 666a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 667a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glShadeModel(GL_FLAT); 668a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glDisable(GL_DITHER); 669a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glDisable(GL_SCISSOR_TEST); 670a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glDisable(GL_BLEND); 671a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 672a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glBindTexture(GL_TEXTURE_2D, 0); 673a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glEnable(GL_TEXTURE_2D); 674a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 675a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 676a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 677a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 678a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 679a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 680a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi bool clockTextureInitialized = false; 681a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi if (mClockEnabled) { 682a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi clockTextureInitialized = (initTexture(&mClock, mAssets, "images/clock64.png") == NO_ERROR); 683a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi mClockEnabled = clockTextureInitialized; 684a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi } 685a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi 6869748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi if (mClockEnabled && !updateIsTimeAccurate()) { 6879748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi mTimeCheckThread = new TimeCheckThread(this); 6889748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi mTimeCheckThread->run("BootAnimation::TimeCheckThread", PRIORITY_NORMAL); 6899748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 6909748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 69139218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy playAnimation(*animation); 6929748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 6939748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi if (mTimeCheckThread != NULL) { 6949748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi mTimeCheckThread->requestExit(); 6959748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi mTimeCheckThread = NULL; 6969748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 6979748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 69839218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy releaseAnimation(animation); 69939218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy 700815e51d76cc284f3ca59534d9f9372d3dd50f574Andriy Naborskyy if (clockTextureInitialized) { 701815e51d76cc284f3ca59534d9f9372d3dd50f574Andriy Naborskyy glDeleteTextures(1, &mClock.name); 702815e51d76cc284f3ca59534d9f9372d3dd50f574Andriy Naborskyy } 703815e51d76cc284f3ca59534d9f9372d3dd50f574Andriy Naborskyy 70439218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy return false; 70539218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy} 70639218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy 70739218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyybool BootAnimation::playAnimation(const Animation& animation) 70839218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy{ 70939218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy const size_t pcount = animation.parts.size(); 710a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian const int xc = (mWidth - animation.width) / 2; 711a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian const int yc = ((mHeight - animation.height) / 2); 712a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian nsecs_t frameDuration = s2ns(1) / animation.fps; 713a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 7149f3020db15e50d07ee1ace42e47d90b076f2ce54Mathias Agopian Region clearReg(Rect(mWidth, mHeight)); 7159f3020db15e50d07ee1ace42e47d90b076f2ce54Mathias Agopian clearReg.subtractSelf(Rect(xc, yc, xc+animation.width, yc+animation.height)); 7169f3020db15e50d07ee1ace42e47d90b076f2ce54Mathias Agopian 717afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath for (size_t i=0 ; i<pcount ; i++) { 718a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian const Animation::Part& part(animation.parts[i]); 719a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian const size_t fcount = part.frames.size(); 720a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glBindTexture(GL_TEXTURE_2D, 0); 721a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 72239218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy // Handle animation package 72339218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy if (part.animation != NULL) { 72439218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy playAnimation(*part.animation); 72539218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy if (exitPending()) 72639218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy break; 72739218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy continue; //to next part 72839218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy } 72939218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy 730a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian for (int r=0 ; !part.count || r<part.count ; r++) { 731d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester // Exit any non playuntil complete parts immediately 732d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester if(exitPending() && !part.playUntilComplete) 733d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester break; 734d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester 735ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood // only play audio file the first time we animate the part 736ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood if (r == 0 && mAudioPlayer != NULL && part.audioFile) { 737ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood mAudioPlayer->playFile(part.audioFile); 738ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood } 739ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood 740083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall glClearColor( 741083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall part.backgroundColor[0], 742083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall part.backgroundColor[1], 743083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall part.backgroundColor[2], 744083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall 1.0f); 745083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall 746afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath for (size_t j=0 ; j<fcount && (!exitPending() || part.playUntilComplete) ; j++) { 747a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian const Animation::Frame& frame(part.frames[j]); 748db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian nsecs_t lastFrame = systemTime(); 749a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 750a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian if (r > 0) { 751a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glBindTexture(GL_TEXTURE_2D, frame.tid); 752a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } else { 753a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian if (part.count != 1) { 754a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glGenTextures(1, &frame.tid); 755a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glBindTexture(GL_TEXTURE_2D, frame.tid); 756a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 757a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 758a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 7590c1eeb3c8ab53954218d3b8f4be08ff21be3e985Mykola Kondratenko initTexture(frame); 760a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 761a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 7629f3020db15e50d07ee1ace42e47d90b076f2ce54Mathias Agopian if (!clearReg.isEmpty()) { 7639f3020db15e50d07ee1ace42e47d90b076f2ce54Mathias Agopian Region::const_iterator head(clearReg.begin()); 7649f3020db15e50d07ee1ace42e47d90b076f2ce54Mathias Agopian Region::const_iterator tail(clearReg.end()); 7659f3020db15e50d07ee1ace42e47d90b076f2ce54Mathias Agopian glEnable(GL_SCISSOR_TEST); 7669f3020db15e50d07ee1ace42e47d90b076f2ce54Mathias Agopian while (head != tail) { 767cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe const Rect& r2(*head++); 768cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe glScissor(r2.left, mHeight - r2.bottom, 769cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe r2.width(), r2.height()); 7709f3020db15e50d07ee1ace42e47d90b076f2ce54Mathias Agopian glClear(GL_COLOR_BUFFER_BIT); 7719f3020db15e50d07ee1ace42e47d90b076f2ce54Mathias Agopian } 7729f3020db15e50d07ee1ace42e47d90b076f2ce54Mathias Agopian glDisable(GL_SCISSOR_TEST); 7739f3020db15e50d07ee1ace42e47d90b076f2ce54Mathias Agopian } 774d13d504e4b7548f0ce4f9c4f0eee5c1ac2ce6794Chris Elliott // specify the y center as ceiling((mHeight - animation.height) / 2) 775d13d504e4b7548f0ce4f9c4f0eee5c1ac2ce6794Chris Elliott // which is equivalent to mHeight - (yc + animation.height) 776d13d504e4b7548f0ce4f9c4f0eee5c1ac2ce6794Chris Elliott glDrawTexiOES(xc, mHeight - (yc + animation.height), 777d13d504e4b7548f0ce4f9c4f0eee5c1ac2ce6794Chris Elliott 0, animation.width, animation.height); 7789748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi if (mClockEnabled && mTimeIsAccurate && part.clockPosY >= 0) { 779a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi drawTime(mClock, part.clockPosY); 780a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi } 781a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi 782a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian eglSwapBuffers(mDisplay, mSurface); 783a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 784a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian nsecs_t now = systemTime(); 785a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian nsecs_t delay = frameDuration - (now - lastFrame); 786db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian //ALOGD("%lld, %lld", ns2ms(now - lastFrame), ns2ms(delay)); 787a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian lastFrame = now; 788db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian 789db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian if (delay > 0) { 790db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian struct timespec spec; 791db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian spec.tv_sec = (now + delay) / 1000000000; 792db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian spec.tv_nsec = (now + delay) % 1000000000; 793db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian int err; 794db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian do { 795db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL); 796db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian } while (err<0 && errno == EINTR); 797db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian } 798d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester 799d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester checkExit(); 800a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 801d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester 802a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian usleep(part.pause * ns2us(frameDuration)); 803d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester 804d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester // For infinite parts, we've now played them at least once, so perhaps exit 805d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester if(exitPending() && !part.count) 806d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester break; 807a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 808a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 809a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian // free the textures for this part 810a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian if (part.count != 1) { 811afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath for (size_t j=0 ; j<fcount ; j++) { 812a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian const Animation::Frame& frame(part.frames[j]); 813a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glDeleteTextures(1, &frame.tid); 814a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 815a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 816a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 81739218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy return true; 81839218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy} 819a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 82039218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyyvoid BootAnimation::releaseAnimation(Animation* animation) const 82139218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy{ 82239218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy for (Vector<Animation::Part>::iterator it = animation->parts.begin(), 82339218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy e = animation->parts.end(); it != e; ++it) { 82439218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy if (it->animation) 82539218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy releaseAnimation(it->animation); 82639218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy } 82739218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy if (animation->zip) 82839218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy delete animation->zip; 82939218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy delete animation; 830a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian} 831a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 83239218ba26d5bb8646f04273f2c3731598721c1daAndriy NaborskyyBootAnimation::Animation* BootAnimation::loadAnimation(const String8& fn) 83339218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy{ 83439218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy if (mLoadedFiles.indexOf(fn) >= 0) { 83539218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy ALOGE("File \"%s\" is already loaded. Cyclic ref is not allowed", 83639218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy fn.string()); 83739218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy return NULL; 83839218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy } 83939218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy ZipFileRO *zip = ZipFileRO::open(fn); 84039218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy if (zip == NULL) { 84139218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy ALOGE("Failed to open animation zip \"%s\": %s", 84239218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy fn.string(), strerror(errno)); 84339218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy return NULL; 844a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi } 845a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi 84639218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy Animation *animation = new Animation; 84739218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy animation->fileName = fn; 84839218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy animation->zip = zip; 84939218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy mLoadedFiles.add(animation->fileName); 85039218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy 85139218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy parseAnimationDesc(*animation); 85239218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy preloadZip(*animation); 853a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 85439218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy mLoadedFiles.remove(fn); 85539218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy return animation; 85639218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy} 8579748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 8589748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchibool BootAnimation::updateIsTimeAccurate() { 8599748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi static constexpr long long MAX_TIME_IN_PAST = 60000LL * 60LL * 24LL * 30LL; // 30 days 8609748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi static constexpr long long MAX_TIME_IN_FUTURE = 60000LL * 90LL; // 90 minutes 8619748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 8629748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi if (mTimeIsAccurate) { 8639748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi return true; 8649748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 8659748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 8669748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi struct stat statResult; 8679748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi if(stat(ACCURATE_TIME_FLAG_FILE_PATH, &statResult) == 0) { 8689748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi mTimeIsAccurate = true; 8699748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi return true; 8709748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 8719748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 8729748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi FILE* file = fopen(LAST_TIME_CHANGED_FILE_PATH, "r"); 8739748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi if (file != NULL) { 8749748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi long long lastChangedTime = 0; 8759748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi fscanf(file, "%lld", &lastChangedTime); 8769748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi fclose(file); 8779748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi if (lastChangedTime > 0) { 8789748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi struct timespec now; 8799748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi clock_gettime(CLOCK_REALTIME, &now); 8809748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi // Match the Java timestamp format 8819748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi long long rtcNow = (now.tv_sec * 1000LL) + (now.tv_nsec / 1000000LL); 8829748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi if (lastChangedTime > rtcNow - MAX_TIME_IN_PAST 8839748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi && lastChangedTime < rtcNow + MAX_TIME_IN_FUTURE) { 8849748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi mTimeIsAccurate = true; 8859748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 8869748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 8879748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 8889748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 8899748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi return mTimeIsAccurate; 8909748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi} 8919748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 8929748086fe267e21d243a49df1775905094a28dd9Damien BargiacchiBootAnimation::TimeCheckThread::TimeCheckThread(BootAnimation* bootAnimation) : Thread(false), 8939748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi mInotifyFd(-1), mSystemWd(-1), mTimeWd(-1), mBootAnimation(bootAnimation) {} 8949748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 8959748086fe267e21d243a49df1775905094a28dd9Damien BargiacchiBootAnimation::TimeCheckThread::~TimeCheckThread() { 8969748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi // mInotifyFd may be -1 but that's ok since we're not at risk of attempting to close a valid FD. 8979748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi close(mInotifyFd); 8989748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi} 8999748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 9009748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchibool BootAnimation::TimeCheckThread::threadLoop() { 9019748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi bool shouldLoop = doThreadLoop() && !mBootAnimation->mTimeIsAccurate 9029748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi && mBootAnimation->mClockEnabled; 9039748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi if (!shouldLoop) { 9049748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi close(mInotifyFd); 9059748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi mInotifyFd = -1; 9069748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 9079748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi return shouldLoop; 9089748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi} 9099748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 9109748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchibool BootAnimation::TimeCheckThread::doThreadLoop() { 9119748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi static constexpr int BUFF_LEN (10 * (sizeof(struct inotify_event) + NAME_MAX + 1)); 9129748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 9139748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi // Poll instead of doing a blocking read so the Thread can exit if requested. 9149748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi struct pollfd pfd = { mInotifyFd, POLLIN, 0 }; 9159748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi ssize_t pollResult = poll(&pfd, 1, 1000); 9169748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 9179748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi if (pollResult == 0) { 9189748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi return true; 9199748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } else if (pollResult < 0) { 9209748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi ALOGE("Could not poll inotify events"); 9219748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi return false; 9229748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 9239748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 9249748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi char buff[BUFF_LEN] __attribute__ ((aligned(__alignof__(struct inotify_event))));; 9259748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi ssize_t length = read(mInotifyFd, buff, BUFF_LEN); 9269748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi if (length == 0) { 9279748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi return true; 9289748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } else if (length < 0) { 9299748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi ALOGE("Could not read inotify events"); 9309748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi return false; 9319748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 9329748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 9339748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi const struct inotify_event *event; 9349748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi for (char* ptr = buff; ptr < buff + length; ptr += sizeof(struct inotify_event) + event->len) { 9359748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi event = (const struct inotify_event *) ptr; 9369748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi if (event->wd == mSystemWd && strcmp(SYSTEM_TIME_DIR_NAME, event->name) == 0) { 9379748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi addTimeDirWatch(); 9389748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } else if (event->wd == mTimeWd && (strcmp(LAST_TIME_CHANGED_FILE_NAME, event->name) == 0 9399748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi || strcmp(ACCURATE_TIME_FLAG_FILE_NAME, event->name) == 0)) { 9409748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi return !mBootAnimation->updateIsTimeAccurate(); 9419748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 9429748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 9439748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 9449748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi return true; 9459748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi} 9469748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 9479748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchivoid BootAnimation::TimeCheckThread::addTimeDirWatch() { 9489748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi mTimeWd = inotify_add_watch(mInotifyFd, SYSTEM_TIME_DIR_PATH, 9499748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi IN_CLOSE_WRITE | IN_MOVED_TO | IN_ATTRIB); 9509748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi if (mTimeWd > 0) { 9519748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi // No need to watch for the time directory to be created if it already exists 9529748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi inotify_rm_watch(mInotifyFd, mSystemWd); 9539748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi mSystemWd = -1; 9549748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 9559748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi} 9569748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 9579748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchistatus_t BootAnimation::TimeCheckThread::readyToRun() { 9589748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi mInotifyFd = inotify_init(); 9599748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi if (mInotifyFd < 0) { 9609748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi ALOGE("Could not initialize inotify fd"); 9619748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi return NO_INIT; 9629748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 9639748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 9649748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi mSystemWd = inotify_add_watch(mInotifyFd, SYSTEM_DATA_DIR_PATH, IN_CREATE | IN_ATTRIB); 9659748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi if (mSystemWd < 0) { 9669748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi close(mInotifyFd); 9679748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi mInotifyFd = -1; 9689748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi ALOGE("Could not add watch for %s", SYSTEM_DATA_DIR_PATH); 9699748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi return NO_INIT; 9709748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 9719748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 9729748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi addTimeDirWatch(); 9739748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 9749748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi if (mBootAnimation->updateIsTimeAccurate()) { 9759748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi close(mInotifyFd); 9769748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi mInotifyFd = -1; 9779748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi return ALREADY_EXISTS; 9789748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 9799748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 9809748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi return NO_ERROR; 9819748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi} 9829748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// --------------------------------------------------------------------------- 9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project; // namespace android 987