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> 21a90c54c90e1cb668cd74f218370f868763bbd009Wei Wang#include <inttypes.h> 229748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi#include <sys/inotify.h> 239748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi#include <sys/poll.h> 249748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi#include <sys/stat.h> 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/types.h> 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <math.h> 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <fcntl.h> 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/misc.h> 29b4d5a72691846bce5779cc3db056f09a5031d7ccMathias Agopian#include <signal.h> 30bb94f3107ea567ddf67bed4617c3bcbd602538dfElliott Hughes#include <time.h> 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 32bd9a08d318f94a3d0b2f8f9d7b16b10736d80c5cJason parks#include <cutils/properties.h> 33bd9a08d318f94a3d0b2f8f9d7b16b10736d80c5cJason parks 34b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <androidfw/AssetManager.h> 35ac31a3b8b09aba1c5ebc73f0cf65cac2210aa6b7Mathias Agopian#include <binder/IPCThreadState.h> 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Atomic.h> 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Errors.h> 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Log.h> 39a90c54c90e1cb668cd74f218370f868763bbd009Wei Wang#include <utils/SystemClock.h> 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 41b593842063770f9e75c623a4bc7bb41b4c1830c6Keun-young Park#include <android-base/properties.h> 42b593842063770f9e75c623a4bc7bb41b4c1830c6Keun-young Park 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <ui/PixelFormat.h> 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <ui/Rect.h> 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <ui/Region.h> 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <ui/DisplayInfo.h> 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 480b722fe9ce98d97dbcb6fefd170b85ab7037e528Jeff Brown#include <gui/ISurfaceComposer.h> 498335f1ccccedb6655d96d9d5b697a7f0938235ddMathias Agopian#include <gui/Surface.h> 508335f1ccccedb6655d96d9d5b697a7f0938235ddMathias Agopian#include <gui/SurfaceComposerClient.h> 51000479f9e325b4e426a67033abd92d47da412725Mathias Agopian 52cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe// TODO: Fix Skia. 53cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe#pragma GCC diagnostic push 54cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe#pragma GCC diagnostic ignored "-Wunused-parameter" 55eece0dda56ae29fff6e9003df97594f6ac50b6e2Derek Sollenberger#include <SkBitmap.h> 568898c16987831db47542a92151ed7209e22268aaMatt Sarett#include <SkImage.h> 57eece0dda56ae29fff6e9003df97594f6ac50b6e2Derek Sollenberger#include <SkStream.h> 58cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe#pragma GCC diagnostic pop 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <GLES/gl.h> 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <GLES/glext.h> 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <EGL/eglext.h> 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "BootAnimation.h" 65d6d9a1d0b9cf6fa740d9fe410015b094475c5a4cGeoffrey Pitsch#include "audioplay.h" 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android { 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 699748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchistatic const char OEM_BOOTANIMATION_FILE[] = "/oem/media/bootanimation.zip"; 709748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchistatic const char SYSTEM_BOOTANIMATION_FILE[] = "/system/media/bootanimation.zip"; 719748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchistatic const char SYSTEM_ENCRYPTED_BOOTANIMATION_FILE[] = "/system/media/bootanimation-encrypted.zip"; 72b593842063770f9e75c623a4bc7bb41b4c1830c6Keun-young Parkstatic const char OEM_SHUTDOWNANIMATION_FILE[] = "/oem/media/shutdownanimation.zip"; 73b593842063770f9e75c623a4bc7bb41b4c1830c6Keun-young Parkstatic const char SYSTEM_SHUTDOWNANIMATION_FILE[] = "/system/media/shutdownanimation.zip"; 74b593842063770f9e75c623a4bc7bb41b4c1830c6Keun-young Park 759748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchistatic const char SYSTEM_DATA_DIR_PATH[] = "/data/system"; 769748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchistatic const char SYSTEM_TIME_DIR_NAME[] = "time"; 779748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchistatic const char SYSTEM_TIME_DIR_PATH[] = "/data/system/time"; 780e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchistatic const char CLOCK_FONT_ASSET[] = "images/clock_font.png"; 790e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchistatic const char CLOCK_FONT_ZIP_NAME[] = "clock_font.png"; 809748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchistatic const char LAST_TIME_CHANGED_FILE_NAME[] = "last_time_change"; 819748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchistatic const char LAST_TIME_CHANGED_FILE_PATH[] = "/data/system/time/last_time_change"; 829748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchistatic const char ACCURATE_TIME_FLAG_FILE_NAME[] = "time_is_accurate"; 839748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchistatic const char ACCURATE_TIME_FLAG_FILE_PATH[] = "/data/system/time/time_is_accurate"; 849071db1d370573bad80f127898e34066f56c4e64Damien Bargiacchistatic const char TIME_FORMAT_12_HOUR_FLAG_FILE_PATH[] = "/data/system/time/time_format_12_hour"; 859676281c4f0b34707e34cf9d2f5a866f1979c405Damien Bargiacchi// Java timestamp format. Don't show the clock if the date is before 2000-01-01 00:00:00. 869676281c4f0b34707e34cf9d2f5a866f1979c405Damien Bargiacchistatic const long long ACCURATE_TIME_EPOCH = 946684800000; 870e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchistatic constexpr char FONT_BEGIN_CHAR = ' '; 880e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchistatic constexpr char FONT_END_CHAR = '~' + 1; 890e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchistatic constexpr size_t FONT_NUM_CHARS = FONT_END_CHAR - FONT_BEGIN_CHAR + 1; 900e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchistatic constexpr size_t FONT_NUM_COLS = 16; 910e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchistatic constexpr size_t FONT_NUM_ROWS = FONT_NUM_CHARS / FONT_NUM_COLS; 920e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchistatic const int TEXT_CENTER_VALUE = INT_MAX; 930e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchistatic const int TEXT_MISSING_VALUE = INT_MIN; 949748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchistatic const char EXIT_PROP_NAME[] = "service.bootanim.exit"; 95305087991d1b88d98c5e5e03fcf5a6a6e93ad356Geoffrey Pitschstatic const char PLAY_SOUND_PROP_NAME[] = "persist.sys.bootanim.play_sound"; 96afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamathstatic const int ANIM_ENTRY_NAME_MAX = 256; 970e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchistatic constexpr size_t TEXT_POS_LEN_MAX = 16; 98290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitschstatic const char BOOT_COMPLETED_PROP_NAME[] = "sys.boot_completed"; 99290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitschstatic const char BOOTREASON_PROP_NAME[] = "ro.boot.bootreason"; 100290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitsch// bootreasons list in "system/core/bootstat/bootstat.cpp". 101290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitschstatic const std::vector<std::string> PLAY_SOUND_BOOTREASON_BLACKLIST { 102290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitsch "kernel_panic", 103290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitsch "Panic", 104290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitsch "Watchdog", 105290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitsch}; 106afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// --------------------------------------------------------------------------- 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1099748086fe267e21d243a49df1775905094a28dd9Damien BargiacchiBootAnimation::BootAnimation() : Thread(false), mClockEnabled(true), mTimeIsAccurate(false), 1109071db1d370573bad80f127898e34066f56c4e64Damien Bargiacchi mTimeFormat12Hour(false), mTimeCheckThread(NULL) { 111627e7b50be41e4fdee758a1bfad3a55de56b4e27Mathias Agopian mSession = new SurfaceComposerClient(); 112290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitsch 113290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitsch // If the system has already booted, the animation is not being used for a boot. 114b593842063770f9e75c623a4bc7bb41b4c1830c6Keun-young Park mSystemBoot = !android::base::GetBoolProperty(BOOT_COMPLETED_PROP_NAME, false); 115b593842063770f9e75c623a4bc7bb41b4c1830c6Keun-young Park std::string powerCtl = android::base::GetProperty("sys.powerctl", ""); 116b593842063770f9e75c623a4bc7bb41b4c1830c6Keun-young Park if (powerCtl.empty()) { 117b593842063770f9e75c623a4bc7bb41b4c1830c6Keun-young Park mShuttingDown = false; 118b593842063770f9e75c623a4bc7bb41b4c1830c6Keun-young Park } else { 119b593842063770f9e75c623a4bc7bb41b4c1830c6Keun-young Park mShuttingDown = true; 120b593842063770f9e75c623a4bc7bb41b4c1830c6Keun-young Park } 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid BootAnimation::onFirstRef() { 124bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian status_t err = mSession->linkToComposerDeath(this); 1253762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE_IF(err, "linkToComposerDeath failed (%s) ", strerror(-err)); 1268434c5369304e639efe8eab368ca410c589d87c2Mathias Agopian if (err == NO_ERROR) { 127bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian run("BootAnimation", PRIORITY_DISPLAY); 128bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian } 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 131bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopiansp<SurfaceComposerClient> BootAnimation::session() const { 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mSession; 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 135bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian 136afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamathvoid BootAnimation::binderDied(const wp<IBinder>&) 137bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian{ 138bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian // woah, surfaceflinger died! 1395baa3a62a97544669fba6d65a11c07f252e654ddSteve Block ALOGD("SurfaceFlinger died, exiting..."); 140bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian 141bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian // calling requestExit() is not enough here because the Surface code 142bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian // might be blocked on a condition variable that will never be updated. 143bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian kill( getpid(), SIGKILL ); 144bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian requestExit(); 145d6d9a1d0b9cf6fa740d9fe410015b094475c5a4cGeoffrey Pitsch audioplay::destroy(); 146bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian} 147bc7261130a51dc9f3461d3970eee1b923bcbf193Mathias Agopian 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t BootAnimation::initTexture(Texture* texture, AssetManager& assets, 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char* name) { 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Asset* asset = assets.open(name, Asset::ACCESS_BUFFER); 151cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe if (asset == NULL) 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_INIT; 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SkBitmap bitmap; 1548898c16987831db47542a92151ed7209e22268aaMatt Sarett sk_sp<SkData> data = SkData::MakeWithoutCopy(asset->getBuffer(false), 1558898c16987831db47542a92151ed7209e22268aaMatt Sarett asset->getLength()); 1568898c16987831db47542a92151ed7209e22268aaMatt Sarett sk_sp<SkImage> image = SkImage::MakeFromEncoded(data); 1578898c16987831db47542a92151ed7209e22268aaMatt Sarett image->asLegacyBitmap(&bitmap, SkImage::kRO_LegacyBitmapMode); 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project asset->close(); 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delete asset; 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // ensure we can call getPixels(). No need to call unlock, since the 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // bitmap will go out of scope when we return from this method. 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bitmap.lockPixels(); 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const int w = bitmap.width(); 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const int h = bitmap.height(); 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const void* p = bitmap.getPixels(); 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project GLint crop[4] = { 0, h, w, -h }; 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project texture->w = w; 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project texture->h = h; 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project glGenTextures(1, &texture->name); 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project glBindTexture(GL_TEXTURE_2D, texture->name); 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17642a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed switch (bitmap.colorType()) { 17742a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed case kAlpha_8_SkColorType: 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_ALPHA, 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project GL_UNSIGNED_BYTE, p); 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 18142a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed case kARGB_4444_SkColorType: 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project GL_UNSIGNED_SHORT_4_4_4_4, p); 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 18542a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed case kN32_SkColorType: 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project GL_UNSIGNED_BYTE, p); 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 18942a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed case kRGB_565_SkColorType: 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project GL_UNSIGNED_SHORT_5_6_5, p); 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 2020e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_ERROR; 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2060e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchistatus_t BootAnimation::initTexture(FileMap* map, int* width, int* height) 207a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian{ 208a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian SkBitmap bitmap; 209f67b317c102db72182046ec2a2cffe2331017709Damien Bargiacchi sk_sp<SkData> data = SkData::MakeWithoutCopy(map->getDataPtr(), 210f67b317c102db72182046ec2a2cffe2331017709Damien Bargiacchi map->getDataLength()); 2118898c16987831db47542a92151ed7209e22268aaMatt Sarett sk_sp<SkImage> image = SkImage::MakeFromEncoded(data); 2128898c16987831db47542a92151ed7209e22268aaMatt Sarett image->asLegacyBitmap(&bitmap, SkImage::kRO_LegacyBitmapMode); 213a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 2140c1eeb3c8ab53954218d3b8f4be08ff21be3e985Mykola Kondratenko // FileMap memory is never released until application exit. 2150c1eeb3c8ab53954218d3b8f4be08ff21be3e985Mykola Kondratenko // Release it now as the texture is already loaded and the memory used for 2160c1eeb3c8ab53954218d3b8f4be08ff21be3e985Mykola Kondratenko // the packed resource can be released. 2170e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi delete map; 2180c1eeb3c8ab53954218d3b8f4be08ff21be3e985Mykola Kondratenko 219a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian // ensure we can call getPixels(). No need to call unlock, since the 220a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian // bitmap will go out of scope when we return from this method. 221a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian bitmap.lockPixels(); 222a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 223a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian const int w = bitmap.width(); 224a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian const int h = bitmap.height(); 225a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian const void* p = bitmap.getPixels(); 226a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 227a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian GLint crop[4] = { 0, h, w, -h }; 228a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian int tw = 1 << (31 - __builtin_clz(w)); 229a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian int th = 1 << (31 - __builtin_clz(h)); 230a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian if (tw < w) tw <<= 1; 231a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian if (th < h) th <<= 1; 232a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 23342a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed switch (bitmap.colorType()) { 23442a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed case kN32_SkColorType: 235271674930a1f9020a291827a8ecb6ab68782c4faSai Kiran Korwar if (!mUseNpotTextures && (tw != w || th != h)) { 236a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tw, th, 0, GL_RGBA, 237a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian GL_UNSIGNED_BYTE, 0); 238a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glTexSubImage2D(GL_TEXTURE_2D, 0, 239a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, p); 240a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } else { 241271674930a1f9020a291827a8ecb6ab68782c4faSai Kiran Korwar glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, 242a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian GL_UNSIGNED_BYTE, p); 243a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 244a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian break; 245a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 24642a1d08df7d417fd4e67eabc91ff05ee77fd9995Mike Reed case kRGB_565_SkColorType: 247271674930a1f9020a291827a8ecb6ab68782c4faSai Kiran Korwar if (!mUseNpotTextures && (tw != w || th != h)) { 248a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tw, th, 0, GL_RGB, 249a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian GL_UNSIGNED_SHORT_5_6_5, 0); 250a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glTexSubImage2D(GL_TEXTURE_2D, 0, 251a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 0, 0, w, h, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, p); 252a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } else { 253271674930a1f9020a291827a8ecb6ab68782c4faSai Kiran Korwar glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, 254a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian GL_UNSIGNED_SHORT_5_6_5, p); 255a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 256a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian break; 257a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian default: 258a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian break; 259a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 260a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 261a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); 262a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 2630e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi *width = w; 2640e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi *height = h; 2650e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi 266a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian return NO_ERROR; 267a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian} 268a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t BootAnimation::readyToRun() { 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAssets.addDefaultAssets(); 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2720b722fe9ce98d97dbcb6fefd170b85ab7037e528Jeff Brown sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay( 2730b722fe9ce98d97dbcb6fefd170b85ab7037e528Jeff Brown ISurfaceComposer::eDisplayIdMain)); 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DisplayInfo dinfo; 2750b722fe9ce98d97dbcb6fefd170b85ab7037e528Jeff Brown status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &dinfo); 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (status) 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // create the native surface 2800b722fe9ce98d97dbcb6fefd170b85ab7037e528Jeff Brown sp<SurfaceControl> control = session()->createSurface(String8("BootAnimation"), 2810b722fe9ce98d97dbcb6fefd170b85ab7037e528Jeff Brown dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565); 282439863f3b3e725b5de1cba4940a21900369961c0Mathias Agopian 283439863f3b3e725b5de1cba4940a21900369961c0Mathias Agopian SurfaceComposerClient::openGlobalTransaction(); 28417f638b39f2e8b610ecfa1290e5bc42ab7700c98Mathias Agopian control->setLayer(0x40000000); 285439863f3b3e725b5de1cba4940a21900369961c0Mathias Agopian SurfaceComposerClient::closeGlobalTransaction(); 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 28717f638b39f2e8b610ecfa1290e5bc42ab7700c98Mathias Agopian sp<Surface> s = control->getSurface(); 28817f638b39f2e8b610ecfa1290e5bc42ab7700c98Mathias Agopian 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // initialize opengl and egl 290738b9a45399485893fa9541fae19c47e01bc4af4Mathias Agopian const EGLint attribs[] = { 2911b253b702a356619ae3c5e68ee92062b5305c5d7Mathias Agopian EGL_RED_SIZE, 8, 2921b253b702a356619ae3c5e68ee92062b5305c5d7Mathias Agopian EGL_GREEN_SIZE, 8, 2931b253b702a356619ae3c5e68ee92062b5305c5d7Mathias Agopian EGL_BLUE_SIZE, 8, 294a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian EGL_DEPTH_SIZE, 0, 295a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian EGL_NONE 296738b9a45399485893fa9541fae19c47e01bc4af4Mathias Agopian }; 297cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe EGLint w, h; 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGLint numConfigs; 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGLConfig config; 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGLSurface surface; 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGLContext context; 302627e7b50be41e4fdee758a1bfad3a55de56b4e27Mathias Agopian 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); 304627e7b50be41e4fdee758a1bfad3a55de56b4e27Mathias Agopian 305627e7b50be41e4fdee758a1bfad3a55de56b4e27Mathias Agopian eglInitialize(display, 0, 0); 3061b253b702a356619ae3c5e68ee92062b5305c5d7Mathias Agopian eglChooseConfig(display, attribs, &config, 1, &numConfigs); 3071473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian surface = eglCreateWindowSurface(display, config, s.get(), NULL); 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project context = eglCreateContext(display, config, NULL, NULL); 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project eglQuerySurface(display, surface, EGL_WIDTH, &w); 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project eglQuerySurface(display, surface, EGL_HEIGHT, &h); 311a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 312abac01052c1c40f8582fe9f010c2efe6013e25c6Mathias Agopian if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) 313abac01052c1c40f8582fe9f010c2efe6013e25c6Mathias Agopian return NO_INIT; 314a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDisplay = display; 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSurface = surface; 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWidth = w; 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHeight = h; 32017f638b39f2e8b610ecfa1290e5bc42ab7700c98Mathias Agopian mFlingerSurfaceControl = control; 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFlingerSurface = s; 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 323c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes // If the device has encryption turned on or is in process 324bd9a08d318f94a3d0b2f8f9d7b16b10736d80c5cJason parks // of being encrypted we show the encrypted boot animation. 325bd9a08d318f94a3d0b2f8f9d7b16b10736d80c5cJason parks char decrypt[PROPERTY_VALUE_MAX]; 326bd9a08d318f94a3d0b2f8f9d7b16b10736d80c5cJason parks property_get("vold.decrypt", decrypt, ""); 327bd9a08d318f94a3d0b2f8f9d7b16b10736d80c5cJason parks 328b593842063770f9e75c623a4bc7bb41b4c1830c6Keun-young Park bool encryptedAnimation = atoi(decrypt) != 0 || 329b593842063770f9e75c623a4bc7bb41b4c1830c6Keun-young Park !strcmp("trigger_restart_min_framework", decrypt); 330bd9a08d318f94a3d0b2f8f9d7b16b10736d80c5cJason parks 331b593842063770f9e75c623a4bc7bb41b4c1830c6Keun-young Park if (!mShuttingDown && encryptedAnimation && 332b593842063770f9e75c623a4bc7bb41b4c1830c6Keun-young Park (access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0)) { 33339218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy mZipFileName = SYSTEM_ENCRYPTED_BOOTANIMATION_FILE; 334b593842063770f9e75c623a4bc7bb41b4c1830c6Keun-young Park return NO_ERROR; 33539218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy } 336b593842063770f9e75c623a4bc7bb41b4c1830c6Keun-young Park static const char* bootFiles[] = {OEM_BOOTANIMATION_FILE, SYSTEM_BOOTANIMATION_FILE}; 337b593842063770f9e75c623a4bc7bb41b4c1830c6Keun-young Park static const char* shutdownFiles[] = 338b593842063770f9e75c623a4bc7bb41b4c1830c6Keun-young Park {OEM_SHUTDOWNANIMATION_FILE, SYSTEM_SHUTDOWNANIMATION_FILE}; 339b593842063770f9e75c623a4bc7bb41b4c1830c6Keun-young Park 340b593842063770f9e75c623a4bc7bb41b4c1830c6Keun-young Park for (const char* f : (!mShuttingDown ? bootFiles : shutdownFiles)) { 341b593842063770f9e75c623a4bc7bb41b4c1830c6Keun-young Park if (access(f, R_OK) == 0) { 342b593842063770f9e75c623a4bc7bb41b4c1830c6Keun-young Park mZipFileName = f; 343b593842063770f9e75c623a4bc7bb41b4c1830c6Keun-young Park return NO_ERROR; 344b593842063770f9e75c623a4bc7bb41b4c1830c6Keun-young Park } 345bd9a08d318f94a3d0b2f8f9d7b16b10736d80c5cJason parks } 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_ERROR; 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 349a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopianbool BootAnimation::threadLoop() 350a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian{ 351a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian bool r; 352afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath // We have no bootanimation file, so we use the stock android logo 353afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath // animation. 35439218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy if (mZipFileName.isEmpty()) { 355a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian r = android(); 356a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } else { 357a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian r = movie(); 358a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 359a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project eglDestroyContext(mDisplay, mContext); 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project eglDestroySurface(mDisplay, mSurface); 3636cf0db228ca275dfcda57d79c55e5fa306809632Mathias Agopian mFlingerSurface.clear(); 36417f638b39f2e8b610ecfa1290e5bc42ab7700c98Mathias Agopian mFlingerSurfaceControl.clear(); 365627e7b50be41e4fdee758a1bfad3a55de56b4e27Mathias Agopian eglTerminate(mDisplay); 3663eee9fbb6df1dbbcefe1f0dfdf1295c95ddf3279Sai Kiran Korwar eglReleaseThread(); 367627e7b50be41e4fdee758a1bfad3a55de56b4e27Mathias Agopian IPCThreadState::self()->stopProcess(); 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return r; 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 371a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopianbool BootAnimation::android() 372a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian{ 373d1794cdbb4183774ac68e9d445ca87835fbe6461Keun-young Park ALOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot", 374d1794cdbb4183774ac68e9d445ca87835fbe6461Keun-young Park elapsedRealtime()); 375b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png"); 376b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian initTexture(&mAndroid[1], mAssets, "images/android-logo-shine.png"); 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // clear screen 379a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glShadeModel(GL_FLAT); 380b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian glDisable(GL_DITHER); 381b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian glDisable(GL_SCISSOR_TEST); 38259f19e48c1c043bb9debdc35d166e397e2125d33Mathias Agopian glClearColor(0,0,0,1); 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project glClear(GL_COLOR_BUFFER_BIT); 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project eglSwapBuffers(mDisplay, mSurface); 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 386a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glEnable(GL_TEXTURE_2D); 387a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 388a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 389b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian const GLint xc = (mWidth - mAndroid[0].w) / 2; 390b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian const GLint yc = (mHeight - mAndroid[0].h) / 2; 391b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian const Rect updateRect(xc, yc, xc + mAndroid[0].w, yc + mAndroid[0].h); 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(), 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project updateRect.height()); 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 396b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian // Blend state 397b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 398b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 399b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const nsecs_t startTime = systemTime(); 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 4021379665abdb8330caf813fb77902914d1545bcd9Mathias Agopian nsecs_t now = systemTime(); 4031379665abdb8330caf813fb77902914d1545bcd9Mathias Agopian double time = now - startTime; 404b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian float t = 4.0f * float(time / us2ns(16667)) / mAndroid[1].w; 405b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian GLint offset = (1 - (t - floorf(t))) * mAndroid[1].w; 406b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian GLint x = xc - offset; 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4088166864e42bc20c1544b2028e8dd65b90f29a0eaMathias Agopian glDisable(GL_SCISSOR_TEST); 4098166864e42bc20c1544b2028e8dd65b90f29a0eaMathias Agopian glClear(GL_COLOR_BUFFER_BIT); 4108166864e42bc20c1544b2028e8dd65b90f29a0eaMathias Agopian 4118166864e42bc20c1544b2028e8dd65b90f29a0eaMathias Agopian glEnable(GL_SCISSOR_TEST); 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project glDisable(GL_BLEND); 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project glBindTexture(GL_TEXTURE_2D, mAndroid[1].name); 414b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian glDrawTexiOES(x, yc, 0, mAndroid[1].w, mAndroid[1].h); 415b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian glDrawTexiOES(x + mAndroid[1].w, yc, 0, mAndroid[1].w, mAndroid[1].h); 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 417b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian glEnable(GL_BLEND); 418b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian glBindTexture(GL_TEXTURE_2D, mAndroid[0].name); 419b2cf954cb47a73065aa4b7fed753877615614f41Mathias Agopian glDrawTexiOES(xc, yc, 0, mAndroid[0].w, mAndroid[0].h); 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 421627e7b50be41e4fdee758a1bfad3a55de56b4e27Mathias Agopian EGLBoolean res = eglSwapBuffers(mDisplay, mSurface); 422627e7b50be41e4fdee758a1bfad3a55de56b4e27Mathias Agopian if (res == EGL_FALSE) 423627e7b50be41e4fdee758a1bfad3a55de56b4e27Mathias Agopian break; 424627e7b50be41e4fdee758a1bfad3a55de56b4e27Mathias Agopian 4251379665abdb8330caf813fb77902914d1545bcd9Mathias Agopian // 12fps: don't animate too fast to preserve CPU 4261379665abdb8330caf813fb77902914d1545bcd9Mathias Agopian const nsecs_t sleepTime = 83333 - ns2us(systemTime() - now); 4271379665abdb8330caf813fb77902914d1545bcd9Mathias Agopian if (sleepTime > 0) 428a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian usleep(sleepTime); 429d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester 430d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester checkExit(); 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (!exitPending()); 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project glDeleteTextures(1, &mAndroid[0].name); 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project glDeleteTextures(1, &mAndroid[1].name); 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 438d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hestervoid BootAnimation::checkExit() { 439d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester // Allow surface flinger to gracefully request shutdown 440d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester char value[PROPERTY_VALUE_MAX]; 441d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester property_get(EXIT_PROP_NAME, value, "0"); 442d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester int exitnow = atoi(value); 443d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester if (exitnow) { 444d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester requestExit(); 445d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester } 446d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester} 447d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester 4480e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchibool BootAnimation::validClock(const Animation::Part& part) { 4490e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi return part.clockPosX != TEXT_MISSING_VALUE && part.clockPosY != TEXT_MISSING_VALUE; 4500e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi} 4510e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi 4520e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchibool parseTextCoord(const char* str, int* dest) { 4530e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi if (strcmp("c", str) == 0) { 4540e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi *dest = TEXT_CENTER_VALUE; 4550e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi return true; 4560e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi } 4570e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi 4580e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi char* end; 4590e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi int val = (int) strtol(str, &end, 0); 4600e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi if (end == str || *end != '\0' || val == INT_MAX || val == INT_MIN) { 4610e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi return false; 4620e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi } 4630e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi *dest = val; 4640e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi return true; 4650e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi} 4660e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi 4670e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi// Parse two position coordinates. If only string is non-empty, treat it as the y value. 4680e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchivoid parsePosition(const char* str1, const char* str2, int* x, int* y) { 4690e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi bool success = false; 4700e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi if (strlen(str1) == 0) { // No values were specified 4710e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi // success = false 4720e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi } else if (strlen(str2) == 0) { // we have only one value 4730e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi if (parseTextCoord(str1, y)) { 4740e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi *x = TEXT_CENTER_VALUE; 4750e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi success = true; 4760e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi } 4770e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi } else { 4780e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi if (parseTextCoord(str1, x) && parseTextCoord(str2, y)) { 4790e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi success = true; 4800e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi } 4810e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi } 4820e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi 4830e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi if (!success) { 4840e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi *x = TEXT_MISSING_VALUE; 4850e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi *y = TEXT_MISSING_VALUE; 4860e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi } 4870e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi} 4880e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi 489083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall// Parse a color represented as an HTML-style 'RRGGBB' string: each pair of 490083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall// characters in str is a hex number in [0, 255], which are converted to 491083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall// floating point values in the range [0.0, 1.0] and placed in the 492083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall// corresponding elements of color. 493083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall// 494083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall// If the input string isn't valid, parseColor returns false and color is 495083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall// left unchanged. 496083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hallstatic bool parseColor(const char str[7], float color[3]) { 497083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall float tmpColor[3]; 498083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall for (int i = 0; i < 3; i++) { 499083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall int val = 0; 500083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall for (int j = 0; j < 2; j++) { 501083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall val *= 16; 502083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall char c = str[2*i + j]; 503083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall if (c >= '0' && c <= '9') val += c - '0'; 504083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall else if (c >= 'A' && c <= 'F') val += (c - 'A') + 10; 505083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall else if (c >= 'a' && c <= 'f') val += (c - 'a') + 10; 506083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall else return false; 507083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall } 508083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall tmpColor[i] = static_cast<float>(val) / 255.0f; 509083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall } 510083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall memcpy(color, tmpColor, sizeof(tmpColor)); 511083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall return true; 512083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall} 513083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall 51439218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy 51539218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyystatic bool readFile(ZipFileRO* zip, const char* name, String8& outString) 516a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian{ 51739218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy ZipEntryRO entry = zip->findEntryByName(name); 518ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood ALOGE_IF(!entry, "couldn't find %s", name); 519ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood if (!entry) { 520afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath return false; 521afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath } 522a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 52339218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy FileMap* entryMap = zip->createEntryFileMap(entry); 52439218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy zip->releaseEntry(entry); 525ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood ALOGE_IF(!entryMap, "entryMap is null"); 526ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood if (!entryMap) { 527a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian return false; 528a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 529a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 530ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood outString.setTo((char const*)entryMap->getDataPtr(), entryMap->getDataLength()); 531688ff4cf0f93d1a886437884f23874e5595d59a3Narayan Kamath delete entryMap; 532ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood return true; 533ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood} 534ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood 5350e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi// The font image should be a 96x2 array of character images. The 5360e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi// columns are the printable ASCII characters 0x20 - 0x7f. The 5370e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi// top row is regular text; the bottom row is bold. 5380e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchistatus_t BootAnimation::initFont(Font* font, const char* fallback) { 5390e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi status_t status = NO_ERROR; 540a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi 5410e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi if (font->map != nullptr) { 5420e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi glGenTextures(1, &font->texture.name); 5430e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi glBindTexture(GL_TEXTURE_2D, font->texture.name); 544a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi 5450e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi status = initTexture(font->map, &font->texture.w, &font->texture.h); 5460e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi 5470e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 5480e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 5490e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 5500e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 5510e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi } else if (fallback != nullptr) { 5520e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi status = initTexture(&font->texture, mAssets, fallback); 5530e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi } else { 5540e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi return NO_INIT; 555a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi } 556a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi 5570e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi if (status == NO_ERROR) { 5580e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi font->char_width = font->texture.w / FONT_NUM_COLS; 5590e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi font->char_height = font->texture.h / FONT_NUM_ROWS / 2; // There are bold and regular rows 5600e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi } 561a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi 5620e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi return status; 5630e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi} 564a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi 5650e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchivoid BootAnimation::drawText(const char* str, const Font& font, bool bold, int* x, int* y) { 5660e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi glEnable(GL_BLEND); // Allow us to draw on top of the animation 5670e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi glBindTexture(GL_TEXTURE_2D, font.texture.name); 5680e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi 5690e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi const int len = strlen(str); 5700e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi const int strWidth = font.char_width * len; 5710e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi 5720e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi if (*x == TEXT_CENTER_VALUE) { 5730e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi *x = (mWidth - strWidth) / 2; 5740e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi } else if (*x < 0) { 5750e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi *x = mWidth + *x - strWidth; 5760e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi } 5770e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi if (*y == TEXT_CENTER_VALUE) { 5780e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi *y = (mHeight - font.char_height) / 2; 5790e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi } else if (*y < 0) { 5800e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi *y = mHeight + *y - font.char_height; 581a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi } 582a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi 5830e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi int cropRect[4] = { 0, 0, font.char_width, -font.char_height }; 584a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi 5850e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi for (int i = 0; i < len; i++) { 5860e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi char c = str[i]; 587a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi 5880e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi if (c < FONT_BEGIN_CHAR || c > FONT_END_CHAR) { 5890e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi c = '?'; 590a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi } 591a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi 592a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi // Crop the texture to only the pixels in the current glyph 5930e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi const int charPos = (c - FONT_BEGIN_CHAR); // Position in the list of valid characters 5940e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi const int row = charPos / FONT_NUM_COLS; 5950e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi const int col = charPos % FONT_NUM_COLS; 5960e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi cropRect[0] = col * font.char_width; // Left of column 5970e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi cropRect[1] = row * font.char_height * 2; // Top of row 5980e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi // Move down to bottom of regular (one char_heigh) or bold (two char_heigh) line 5990e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi cropRect[1] += bold ? 2 * font.char_height : font.char_height; 600a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect); 601a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi 6020e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi glDrawTexiOES(*x, *y, 0, font.char_width, font.char_height); 603a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi 6040e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi *x += font.char_width; 605a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi } 606a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi 607a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi glDisable(GL_BLEND); // Return to the animation's default behaviour 608a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi glBindTexture(GL_TEXTURE_2D, 0); 609a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi} 610a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi 6119071db1d370573bad80f127898e34066f56c4e64Damien Bargiacchi// We render 12 or 24 hour time. 6120e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchivoid BootAnimation::drawClock(const Font& font, const int xPos, const int yPos) { 6139071db1d370573bad80f127898e34066f56c4e64Damien Bargiacchi static constexpr char TIME_FORMAT_12[] = "%l:%M"; 6149071db1d370573bad80f127898e34066f56c4e64Damien Bargiacchi static constexpr char TIME_FORMAT_24[] = "%H:%M"; 6150e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi static constexpr int TIME_LENGTH = 6; 6160e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi 6170e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi time_t rawtime; 6180e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi time(&rawtime); 6190e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi struct tm* timeInfo = localtime(&rawtime); 6200e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi 6210e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi char timeBuff[TIME_LENGTH]; 6229071db1d370573bad80f127898e34066f56c4e64Damien Bargiacchi const char* timeFormat = mTimeFormat12Hour ? TIME_FORMAT_12 : TIME_FORMAT_24; 6239071db1d370573bad80f127898e34066f56c4e64Damien Bargiacchi size_t length = strftime(timeBuff, TIME_LENGTH, timeFormat, timeInfo); 6240e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi 6250e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi if (length != TIME_LENGTH - 1) { 6260e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi ALOGE("Couldn't format time; abandoning boot animation clock"); 6270e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi mClockEnabled = false; 6280e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi return; 6290e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi } 6300e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi 63145a764400485fb6fb9b0d3566e24feac446e616cDamien Bargiacchi char* out = timeBuff[0] == ' ' ? &timeBuff[1] : &timeBuff[0]; 6320e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi int x = xPos; 6330e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi int y = yPos; 63445a764400485fb6fb9b0d3566e24feac446e616cDamien Bargiacchi drawText(out, font, false, &x, &y); 6350e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi} 6360e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi 63739218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyybool BootAnimation::parseAnimationDesc(Animation& animation) 638ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood{ 639ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood String8 desString; 640ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood 64139218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy if (!readFile(animation.zip, "desc.txt", desString)) { 642ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood return false; 643ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood } 644a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian char const* s = desString.string(); 645a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 646a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian // Parse the description file 647a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian for (;;) { 648a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian const char* endl = strstr(s, "\n"); 649cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe if (endl == NULL) break; 650a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian String8 line(s, endl - s); 651a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian const char* l = line.string(); 652a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi int fps = 0; 653a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi int width = 0; 654a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi int height = 0; 655a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi int count = 0; 656a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi int pause = 0; 657afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath char path[ANIM_ENTRY_NAME_MAX]; 658083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall char color[7] = "000000"; // default to black if unspecified 6590e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi char clockPos1[TEXT_POS_LEN_MAX + 1] = ""; 6600e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi char clockPos2[TEXT_POS_LEN_MAX + 1] = ""; 661083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall 662d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester char pathType; 663a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian if (sscanf(l, "%d %d %d", &width, &height, &fps) == 3) { 664083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall // ALOGD("> w=%d, h=%d, fps=%d", width, height, fps); 665a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian animation.width = width; 666a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian animation.height = height; 667a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian animation.fps = fps; 6680e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi } else if (sscanf(l, " %c %d %d %s #%6s %16s %16s", 6690e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi &pathType, &count, &pause, path, color, clockPos1, clockPos2) >= 4) { 6700e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi //ALOGD("> type=%c, count=%d, pause=%d, path=%s, color=%s, clockPos1=%s, clockPos2=%s", 6710e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi // pathType, count, pause, path, color, clockPos1, clockPos2); 672a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian Animation::Part part; 673d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester part.playUntilComplete = pathType == 'c'; 674a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian part.count = count; 675a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian part.pause = pause; 676a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian part.path = path; 677d6d9a1d0b9cf6fa740d9fe410015b094475c5a4cGeoffrey Pitsch part.audioData = NULL; 67839218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy part.animation = NULL; 679083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall if (!parseColor(color, part.backgroundColor)) { 680083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall ALOGE("> invalid color '#%s'", color); 681083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall part.backgroundColor[0] = 0.0f; 682083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall part.backgroundColor[1] = 0.0f; 683083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall part.backgroundColor[2] = 0.0f; 684083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall } 6850e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi parsePosition(clockPos1, clockPos2, &part.clockPosX, &part.clockPosY); 686a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian animation.parts.add(part); 687a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 68839218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy else if (strcmp(l, "$SYSTEM") == 0) { 68939218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy // ALOGD("> SYSTEM"); 69039218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy Animation::Part part; 69139218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy part.playUntilComplete = false; 69239218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy part.count = 1; 69339218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy part.pause = 0; 694d6d9a1d0b9cf6fa740d9fe410015b094475c5a4cGeoffrey Pitsch part.audioData = NULL; 69539218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy part.animation = loadAnimation(String8(SYSTEM_BOOTANIMATION_FILE)); 69639218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy if (part.animation != NULL) 69739218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy animation.parts.add(part); 69839218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy } 699a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian s = ++endl; 700a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 701a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 70239218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy return true; 70339218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy} 70439218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy 70539218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyybool BootAnimation::preloadZip(Animation& animation) 70639218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy{ 707a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian // read all the data structures 708a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian const size_t pcount = animation.parts.size(); 709afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath void *cookie = NULL; 710dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch ZipFileRO* zip = animation.zip; 711dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch if (!zip->startIteration(&cookie)) { 712afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath return false; 713afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath } 714afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath 715a91a2d737586ebd0040129333055d8093899751bGeoffrey Pitsch Animation::Part* partWithAudio = NULL; 716afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath ZipEntryRO entry; 717afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath char name[ANIM_ENTRY_NAME_MAX]; 718dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch while ((entry = zip->nextEntry(cookie)) != NULL) { 719dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch const int foundEntryName = zip->getEntryFileName(entry, name, ANIM_ENTRY_NAME_MAX); 720afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath if (foundEntryName > ANIM_ENTRY_NAME_MAX || foundEntryName == -1) { 721afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath ALOGE("Error fetching entry file name"); 722afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath continue; 723afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath } 724afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath 725afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath const String8 entryName(name); 726afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath const String8 path(entryName.getPathDir()); 727afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath const String8 leaf(entryName.getPathLeaf()); 728afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath if (leaf.size() > 0) { 7290e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi if (entryName == CLOCK_FONT_ZIP_NAME) { 7300e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi FileMap* map = zip->createEntryFileMap(entry); 7310e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi if (map) { 7320e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi animation.clockFont.map = map; 7330e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi } 7340e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi continue; 7350e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi } 7360e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi 737dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch for (size_t j = 0; j < pcount; j++) { 738afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath if (path == animation.parts[j].path) { 7394600dd053dbdbd4b95f3b11057a1cc55b99f9c77Narayan Kamath uint16_t method; 740afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath // supports only stored png files 741dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch if (zip->getEntryInfo(entry, &method, NULL, NULL, NULL, NULL, NULL)) { 742afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath if (method == ZipFileRO::kCompressStored) { 743dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch FileMap* map = zip->createEntryFileMap(entry); 744afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath if (map) { 745afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath Animation::Part& part(animation.parts.editItemAt(j)); 746ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood if (leaf == "audio.wav") { 747ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood // a part may have at most one audio file 748d6d9a1d0b9cf6fa740d9fe410015b094475c5a4cGeoffrey Pitsch part.audioData = (uint8_t *)map->getDataPtr(); 749d6d9a1d0b9cf6fa740d9fe410015b094475c5a4cGeoffrey Pitsch part.audioLength = map->getDataLength(); 750a91a2d737586ebd0040129333055d8093899751bGeoffrey Pitsch partWithAudio = ∂ 751dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch } else if (leaf == "trim.txt") { 752dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch part.trimData.setTo((char const*)map->getDataPtr(), 753dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch map->getDataLength()); 754ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood } else { 755ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood Animation::Frame frame; 756ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood frame.name = leaf; 757ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood frame.map = map; 758dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch frame.trimWidth = animation.width; 759dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch frame.trimHeight = animation.height; 760dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch frame.trimX = 0; 761dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch frame.trimY = 0; 762ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood part.frames.add(frame); 763ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood } 764a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 765d6d9a1d0b9cf6fa740d9fe410015b094475c5a4cGeoffrey Pitsch } else { 766d6d9a1d0b9cf6fa740d9fe410015b094475c5a4cGeoffrey Pitsch ALOGE("bootanimation.zip is compressed; must be only stored"); 767a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 768a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 769a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 770a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 771a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 772a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 773a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 774dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch // If there is trimData present, override the positioning defaults. 775dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch for (Animation::Part& part : animation.parts) { 776dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch const char* trimDataStr = part.trimData.string(); 777dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch for (size_t frameIdx = 0; frameIdx < part.frames.size(); frameIdx++) { 778dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch const char* endl = strstr(trimDataStr, "\n"); 779dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch // No more trimData for this part. 780dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch if (endl == NULL) { 781dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch break; 782dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch } 783dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch String8 line(trimDataStr, endl - trimDataStr); 784dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch const char* lineStr = line.string(); 785dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch trimDataStr = ++endl; 786dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch int width = 0, height = 0, x = 0, y = 0; 787dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch if (sscanf(lineStr, "%dx%d+%d+%d", &width, &height, &x, &y) == 4) { 788dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch Animation::Frame& frame(part.frames.editItemAt(frameIdx)); 789dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch frame.trimWidth = width; 790dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch frame.trimHeight = height; 791dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch frame.trimX = x; 792dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch frame.trimY = y; 793dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch } else { 794dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch ALOGE("Error parsing trim.txt, line: %s", lineStr); 795dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch break; 796dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch } 797dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch } 798dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch } 799dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch 800d6d9a1d0b9cf6fa740d9fe410015b094475c5a4cGeoffrey Pitsch // Create and initialize audioplay if there is a wav file in any of the animations. 801a917353da0ed6079d45487a8c96b892c5d754637Geoffrey Pitsch // Do it on a separate thread so we don't hold up the animation intro. 802a91a2d737586ebd0040129333055d8093899751bGeoffrey Pitsch if (partWithAudio != NULL) { 803d6d9a1d0b9cf6fa740d9fe410015b094475c5a4cGeoffrey Pitsch ALOGD("found audio.wav, creating playback engine"); 804a917353da0ed6079d45487a8c96b892c5d754637Geoffrey Pitsch mInitAudioThread = new InitAudioThread(partWithAudio->audioData, 805a917353da0ed6079d45487a8c96b892c5d754637Geoffrey Pitsch partWithAudio->audioLength); 806a917353da0ed6079d45487a8c96b892c5d754637Geoffrey Pitsch mInitAudioThread->run("BootAnimation::InitAudioThread", PRIORITY_NORMAL); 807d6d9a1d0b9cf6fa740d9fe410015b094475c5a4cGeoffrey Pitsch } 808d6d9a1d0b9cf6fa740d9fe410015b094475c5a4cGeoffrey Pitsch 809dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch zip->endIteration(cookie); 810afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath 81139218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy return true; 81239218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy} 81339218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy 81439218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyybool BootAnimation::movie() 81539218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy{ 81639218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy Animation* animation = loadAnimation(mZipFileName); 81739218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy if (animation == NULL) 81839218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy return false; 81939218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy 8209748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi bool anyPartHasClock = false; 8219748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi for (size_t i=0; i < animation->parts.size(); i++) { 8220e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi if(validClock(animation->parts[i])) { 8239748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi anyPartHasClock = true; 8249748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi break; 8259748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 8269748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 8279748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi if (!anyPartHasClock) { 8289748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi mClockEnabled = false; 8299748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 8309748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 831271674930a1f9020a291827a8ecb6ab68782c4faSai Kiran Korwar // Check if npot textures are supported 832271674930a1f9020a291827a8ecb6ab68782c4faSai Kiran Korwar mUseNpotTextures = false; 833271674930a1f9020a291827a8ecb6ab68782c4faSai Kiran Korwar String8 gl_extensions; 834271674930a1f9020a291827a8ecb6ab68782c4faSai Kiran Korwar const char* exts = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)); 835271674930a1f9020a291827a8ecb6ab68782c4faSai Kiran Korwar if (!exts) { 836271674930a1f9020a291827a8ecb6ab68782c4faSai Kiran Korwar glGetError(); 837271674930a1f9020a291827a8ecb6ab68782c4faSai Kiran Korwar } else { 838271674930a1f9020a291827a8ecb6ab68782c4faSai Kiran Korwar gl_extensions.setTo(exts); 839271674930a1f9020a291827a8ecb6ab68782c4faSai Kiran Korwar if ((gl_extensions.find("GL_ARB_texture_non_power_of_two") != -1) || 840271674930a1f9020a291827a8ecb6ab68782c4faSai Kiran Korwar (gl_extensions.find("GL_OES_texture_npot") != -1)) { 841271674930a1f9020a291827a8ecb6ab68782c4faSai Kiran Korwar mUseNpotTextures = true; 842271674930a1f9020a291827a8ecb6ab68782c4faSai Kiran Korwar } 843271674930a1f9020a291827a8ecb6ab68782c4faSai Kiran Korwar } 844271674930a1f9020a291827a8ecb6ab68782c4faSai Kiran Korwar 845a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi // Blend required to draw time on top of animation frames. 846a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 847a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glShadeModel(GL_FLAT); 848a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glDisable(GL_DITHER); 849a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glDisable(GL_SCISSOR_TEST); 850a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glDisable(GL_BLEND); 851a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 852a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glBindTexture(GL_TEXTURE_2D, 0); 853a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glEnable(GL_TEXTURE_2D); 854a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 855a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 856a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 857a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 858a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 859a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 8600e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi bool clockFontInitialized = false; 861a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi if (mClockEnabled) { 8620e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi clockFontInitialized = 8630e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi (initFont(&animation->clockFont, CLOCK_FONT_ASSET) == NO_ERROR); 8640e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi mClockEnabled = clockFontInitialized; 865a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi } 866a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi 8679748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi if (mClockEnabled && !updateIsTimeAccurate()) { 8689748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi mTimeCheckThread = new TimeCheckThread(this); 8699748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi mTimeCheckThread->run("BootAnimation::TimeCheckThread", PRIORITY_NORMAL); 8709748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 8719748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 87239218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy playAnimation(*animation); 8739748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 874a917353da0ed6079d45487a8c96b892c5d754637Geoffrey Pitsch if (mTimeCheckThread != nullptr) { 8759748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi mTimeCheckThread->requestExit(); 876a917353da0ed6079d45487a8c96b892c5d754637Geoffrey Pitsch mTimeCheckThread = nullptr; 877a917353da0ed6079d45487a8c96b892c5d754637Geoffrey Pitsch } 878a917353da0ed6079d45487a8c96b892c5d754637Geoffrey Pitsch 879a90c54c90e1cb668cd74f218370f868763bbd009Wei Wang // We should have joined mInitAudioThread thread in playAnimation 880a917353da0ed6079d45487a8c96b892c5d754637Geoffrey Pitsch if (mInitAudioThread != nullptr) { 881a917353da0ed6079d45487a8c96b892c5d754637Geoffrey Pitsch mInitAudioThread = nullptr; 8829748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 8839748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 88439218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy releaseAnimation(animation); 88539218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy 8860e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi if (clockFontInitialized) { 8870e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi glDeleteTextures(1, &animation->clockFont.texture.name); 888815e51d76cc284f3ca59534d9f9372d3dd50f574Andriy Naborskyy } 889815e51d76cc284f3ca59534d9f9372d3dd50f574Andriy Naborskyy 89039218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy return false; 89139218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy} 89239218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy 89339218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyybool BootAnimation::playAnimation(const Animation& animation) 89439218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy{ 89539218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy const size_t pcount = animation.parts.size(); 896a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian nsecs_t frameDuration = s2ns(1) / animation.fps; 897dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch const int animationX = (mWidth - animation.width) / 2; 898dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch const int animationY = (mHeight - animation.height) / 2; 8999f3020db15e50d07ee1ace42e47d90b076f2ce54Mathias Agopian 900d1794cdbb4183774ac68e9d445ca87835fbe6461Keun-young Park ALOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot", 901d1794cdbb4183774ac68e9d445ca87835fbe6461Keun-young Park elapsedRealtime()); 902afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath for (size_t i=0 ; i<pcount ; i++) { 903a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian const Animation::Part& part(animation.parts[i]); 904a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian const size_t fcount = part.frames.size(); 905a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glBindTexture(GL_TEXTURE_2D, 0); 906a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 90739218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy // Handle animation package 90839218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy if (part.animation != NULL) { 90939218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy playAnimation(*part.animation); 91039218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy if (exitPending()) 91139218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy break; 91239218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy continue; //to next part 91339218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy } 91439218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy 915a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian for (int r=0 ; !part.count || r<part.count ; r++) { 916d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester // Exit any non playuntil complete parts immediately 917d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester if(exitPending() && !part.playUntilComplete) 918d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester break; 919d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester 920ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood // only play audio file the first time we animate the part 921290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitsch if (r == 0 && part.audioData && playSoundsAllowed()) { 922290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitsch ALOGD("playing clip for part%d, size=%d", (int) i, part.audioLength); 923a917353da0ed6079d45487a8c96b892c5d754637Geoffrey Pitsch // Block until the audio engine is finished initializing. 924a917353da0ed6079d45487a8c96b892c5d754637Geoffrey Pitsch if (mInitAudioThread != nullptr) { 925a917353da0ed6079d45487a8c96b892c5d754637Geoffrey Pitsch mInitAudioThread->join(); 926a917353da0ed6079d45487a8c96b892c5d754637Geoffrey Pitsch } 927290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitsch audioplay::playClip(part.audioData, part.audioLength); 928ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood } 929ebf9a0d8a888042c16ec0cb6dd8419f18038663fMike Lockwood 930083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall glClearColor( 931083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall part.backgroundColor[0], 932083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall part.backgroundColor[1], 933083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall part.backgroundColor[2], 934083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall 1.0f); 935083b84cf8880bb7f0d2c2dc1b45c7d610656dbd1Jesse Hall 936afd31e08299008fdc5c2813f21b2573f29dc53dfNarayan Kamath for (size_t j=0 ; j<fcount && (!exitPending() || part.playUntilComplete) ; j++) { 937a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian const Animation::Frame& frame(part.frames[j]); 938db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian nsecs_t lastFrame = systemTime(); 939a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 940a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian if (r > 0) { 941a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glBindTexture(GL_TEXTURE_2D, frame.tid); 942a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } else { 943a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian if (part.count != 1) { 944a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glGenTextures(1, &frame.tid); 945a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glBindTexture(GL_TEXTURE_2D, frame.tid); 946a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 947a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 948a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 9490e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi int w, h; 9500e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi initTexture(frame.map, &w, &h); 951a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 952a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 953dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch const int xc = animationX + frame.trimX; 954dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch const int yc = animationY + frame.trimY; 955dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch Region clearReg(Rect(mWidth, mHeight)); 956dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch clearReg.subtractSelf(Rect(xc, yc, xc+frame.trimWidth, yc+frame.trimHeight)); 9579f3020db15e50d07ee1ace42e47d90b076f2ce54Mathias Agopian if (!clearReg.isEmpty()) { 9589f3020db15e50d07ee1ace42e47d90b076f2ce54Mathias Agopian Region::const_iterator head(clearReg.begin()); 9599f3020db15e50d07ee1ace42e47d90b076f2ce54Mathias Agopian Region::const_iterator tail(clearReg.end()); 9609f3020db15e50d07ee1ace42e47d90b076f2ce54Mathias Agopian glEnable(GL_SCISSOR_TEST); 9619f3020db15e50d07ee1ace42e47d90b076f2ce54Mathias Agopian while (head != tail) { 962cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe const Rect& r2(*head++); 963dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch glScissor(r2.left, mHeight - r2.bottom, r2.width(), r2.height()); 9649f3020db15e50d07ee1ace42e47d90b076f2ce54Mathias Agopian glClear(GL_COLOR_BUFFER_BIT); 9659f3020db15e50d07ee1ace42e47d90b076f2ce54Mathias Agopian } 9669f3020db15e50d07ee1ace42e47d90b076f2ce54Mathias Agopian glDisable(GL_SCISSOR_TEST); 9679f3020db15e50d07ee1ace42e47d90b076f2ce54Mathias Agopian } 968dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch // specify the y center as ceiling((mHeight - frame.trimHeight) / 2) 969dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch // which is equivalent to mHeight - (yc + frame.trimHeight) 970dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch glDrawTexiOES(xc, mHeight - (yc + frame.trimHeight), 971dd214a796f8b97070645226d6a61f8651f9e13a0Geoffrey Pitsch 0, frame.trimWidth, frame.trimHeight); 9720e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi if (mClockEnabled && mTimeIsAccurate && validClock(part)) { 9730e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi drawClock(animation.clockFont, part.clockPosX, part.clockPosY); 974a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi } 975a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi 976a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian eglSwapBuffers(mDisplay, mSurface); 977a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 978a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian nsecs_t now = systemTime(); 979a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian nsecs_t delay = frameDuration - (now - lastFrame); 980db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian //ALOGD("%lld, %lld", ns2ms(now - lastFrame), ns2ms(delay)); 981a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian lastFrame = now; 982db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian 983db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian if (delay > 0) { 984db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian struct timespec spec; 985db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian spec.tv_sec = (now + delay) / 1000000000; 986db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian spec.tv_nsec = (now + delay) % 1000000000; 987db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian int err; 988db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian do { 989db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL); 990db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian } while (err<0 && errno == EINTR); 991db7dd2af93ae96e5749cfbe978c2695049d9d782Mathias Agopian } 992d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester 993d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester checkExit(); 994a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 995d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester 996a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian usleep(part.pause * ns2us(frameDuration)); 997d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester 998d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester // For infinite parts, we've now played them at least once, so perhaps exit 999d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester if(exitPending() && !part.count) 1000d3782b26b2026e60a8e0d4b967a156369f2a46f8Kevin Hester break; 1001a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 1002a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 10032fb30fb68e9acb121a3e0dae0cd2790b3a7cc17dGeoffrey Pitsch } 10042fb30fb68e9acb121a3e0dae0cd2790b3a7cc17dGeoffrey Pitsch 10052fb30fb68e9acb121a3e0dae0cd2790b3a7cc17dGeoffrey Pitsch // Free textures created for looping parts now that the animation is done. 10062fb30fb68e9acb121a3e0dae0cd2790b3a7cc17dGeoffrey Pitsch for (const Animation::Part& part : animation.parts) { 1007a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian if (part.count != 1) { 10082fb30fb68e9acb121a3e0dae0cd2790b3a7cc17dGeoffrey Pitsch const size_t fcount = part.frames.size(); 10092fb30fb68e9acb121a3e0dae0cd2790b3a7cc17dGeoffrey Pitsch for (size_t j = 0; j < fcount; j++) { 1010a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian const Animation::Frame& frame(part.frames[j]); 1011a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian glDeleteTextures(1, &frame.tid); 1012a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 1013a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 1014a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian } 1015d6d9a1d0b9cf6fa740d9fe410015b094475c5a4cGeoffrey Pitsch 1016d6d9a1d0b9cf6fa740d9fe410015b094475c5a4cGeoffrey Pitsch // we've finally played everything we're going to play 1017d6d9a1d0b9cf6fa740d9fe410015b094475c5a4cGeoffrey Pitsch audioplay::setPlaying(false); 1018d6d9a1d0b9cf6fa740d9fe410015b094475c5a4cGeoffrey Pitsch audioplay::destroy(); 1019d6d9a1d0b9cf6fa740d9fe410015b094475c5a4cGeoffrey Pitsch 102039218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy return true; 102139218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy} 1022a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 102339218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyyvoid BootAnimation::releaseAnimation(Animation* animation) const 102439218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy{ 102539218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy for (Vector<Animation::Part>::iterator it = animation->parts.begin(), 102639218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy e = animation->parts.end(); it != e; ++it) { 102739218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy if (it->animation) 102839218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy releaseAnimation(it->animation); 102939218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy } 103039218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy if (animation->zip) 103139218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy delete animation->zip; 103239218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy delete animation; 1033a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian} 1034a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 103539218ba26d5bb8646f04273f2c3731598721c1daAndriy NaborskyyBootAnimation::Animation* BootAnimation::loadAnimation(const String8& fn) 103639218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy{ 103739218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy if (mLoadedFiles.indexOf(fn) >= 0) { 103839218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy ALOGE("File \"%s\" is already loaded. Cyclic ref is not allowed", 103939218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy fn.string()); 104039218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy return NULL; 104139218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy } 104239218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy ZipFileRO *zip = ZipFileRO::open(fn); 104339218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy if (zip == NULL) { 104439218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy ALOGE("Failed to open animation zip \"%s\": %s", 104539218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy fn.string(), strerror(errno)); 104639218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy return NULL; 1047a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi } 1048a704b7d3444d218fe3b3f977fd242d2cd626058eDamien Bargiacchi 104939218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy Animation *animation = new Animation; 105039218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy animation->fileName = fn; 105139218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy animation->zip = zip; 10520e3d2ab6d2988a1ae70d13d6d77a0f8109eb66e1Damien Bargiacchi animation->clockFont.map = nullptr; 105339218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy mLoadedFiles.add(animation->fileName); 105439218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy 105539218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy parseAnimationDesc(*animation); 1056a91a2d737586ebd0040129333055d8093899751bGeoffrey Pitsch if (!preloadZip(*animation)) { 1057a91a2d737586ebd0040129333055d8093899751bGeoffrey Pitsch return NULL; 1058a91a2d737586ebd0040129333055d8093899751bGeoffrey Pitsch } 1059a91a2d737586ebd0040129333055d8093899751bGeoffrey Pitsch 1060a8826d67097b12cf9d6b14a7e32c0862f17b189aMathias Agopian 106139218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy mLoadedFiles.remove(fn); 106239218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy return animation; 106339218ba26d5bb8646f04273f2c3731598721c1daAndriy Naborskyy} 10649748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 1065290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitschbool BootAnimation::playSoundsAllowed() const { 1066290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitsch // Only play sounds for system boots, not runtime restarts. 1067290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitsch if (!mSystemBoot) { 1068290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitsch return false; 1069290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitsch } 1070b593842063770f9e75c623a4bc7bb41b4c1830c6Keun-young Park if (mShuttingDown) { // no audio while shutting down 1071b593842063770f9e75c623a4bc7bb41b4c1830c6Keun-young Park return false; 1072b593842063770f9e75c623a4bc7bb41b4c1830c6Keun-young Park } 1073290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitsch // Read the system property to see if we should play the sound. 1074290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitsch // If it's not present, default to allowed. 1075290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitsch if (!property_get_bool(PLAY_SOUND_PROP_NAME, 1)) { 1076290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitsch return false; 1077290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitsch } 1078290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitsch 1079290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitsch // Don't play sounds if this is a reboot due to an error. 1080290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitsch char bootreason[PROPERTY_VALUE_MAX]; 1081290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitsch if (property_get(BOOTREASON_PROP_NAME, bootreason, nullptr) > 0) { 1082290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitsch for (const auto& str : PLAY_SOUND_BOOTREASON_BLACKLIST) { 1083290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitsch if (strcasecmp(str.c_str(), bootreason) == 0) { 1084290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitsch return false; 1085290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitsch } 1086290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitsch } 1087290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitsch } 1088290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitsch return true; 1089290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitsch} 1090290c4350edc66de5663e27c54e694c8ee8cf0e0eGeoffrey Pitsch 10919748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchibool BootAnimation::updateIsTimeAccurate() { 10929748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi static constexpr long long MAX_TIME_IN_PAST = 60000LL * 60LL * 24LL * 30LL; // 30 days 10939748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi static constexpr long long MAX_TIME_IN_FUTURE = 60000LL * 90LL; // 90 minutes 10949748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 10959748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi if (mTimeIsAccurate) { 10969748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi return true; 10979748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 1098b593842063770f9e75c623a4bc7bb41b4c1830c6Keun-young Park if (mShuttingDown) return true; 10999748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi struct stat statResult; 11009071db1d370573bad80f127898e34066f56c4e64Damien Bargiacchi 11019071db1d370573bad80f127898e34066f56c4e64Damien Bargiacchi if(stat(TIME_FORMAT_12_HOUR_FLAG_FILE_PATH, &statResult) == 0) { 11029071db1d370573bad80f127898e34066f56c4e64Damien Bargiacchi mTimeFormat12Hour = true; 11039071db1d370573bad80f127898e34066f56c4e64Damien Bargiacchi } 11049071db1d370573bad80f127898e34066f56c4e64Damien Bargiacchi 11059748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi if(stat(ACCURATE_TIME_FLAG_FILE_PATH, &statResult) == 0) { 11069748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi mTimeIsAccurate = true; 11079748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi return true; 11089748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 11099748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 11109748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi FILE* file = fopen(LAST_TIME_CHANGED_FILE_PATH, "r"); 11119748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi if (file != NULL) { 11129748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi long long lastChangedTime = 0; 11139748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi fscanf(file, "%lld", &lastChangedTime); 11149748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi fclose(file); 11159748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi if (lastChangedTime > 0) { 11169748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi struct timespec now; 11179748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi clock_gettime(CLOCK_REALTIME, &now); 11189748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi // Match the Java timestamp format 11199748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi long long rtcNow = (now.tv_sec * 1000LL) + (now.tv_nsec / 1000000LL); 11209676281c4f0b34707e34cf9d2f5a866f1979c405Damien Bargiacchi if (ACCURATE_TIME_EPOCH < rtcNow 11219676281c4f0b34707e34cf9d2f5a866f1979c405Damien Bargiacchi && lastChangedTime > (rtcNow - MAX_TIME_IN_PAST) 11229676281c4f0b34707e34cf9d2f5a866f1979c405Damien Bargiacchi && lastChangedTime < (rtcNow + MAX_TIME_IN_FUTURE)) { 11239748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi mTimeIsAccurate = true; 11249748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 11259748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 11269748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 11279748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 11289748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi return mTimeIsAccurate; 11299748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi} 11309748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 11319748086fe267e21d243a49df1775905094a28dd9Damien BargiacchiBootAnimation::TimeCheckThread::TimeCheckThread(BootAnimation* bootAnimation) : Thread(false), 11329748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi mInotifyFd(-1), mSystemWd(-1), mTimeWd(-1), mBootAnimation(bootAnimation) {} 11339748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 11349748086fe267e21d243a49df1775905094a28dd9Damien BargiacchiBootAnimation::TimeCheckThread::~TimeCheckThread() { 11359748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi // mInotifyFd may be -1 but that's ok since we're not at risk of attempting to close a valid FD. 11369748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi close(mInotifyFd); 11379748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi} 11389748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 11399748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchibool BootAnimation::TimeCheckThread::threadLoop() { 11409748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi bool shouldLoop = doThreadLoop() && !mBootAnimation->mTimeIsAccurate 11419748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi && mBootAnimation->mClockEnabled; 11429748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi if (!shouldLoop) { 11439748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi close(mInotifyFd); 11449748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi mInotifyFd = -1; 11459748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 11469748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi return shouldLoop; 11479748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi} 11489748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 11499748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchibool BootAnimation::TimeCheckThread::doThreadLoop() { 11509748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi static constexpr int BUFF_LEN (10 * (sizeof(struct inotify_event) + NAME_MAX + 1)); 11519748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 11529748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi // Poll instead of doing a blocking read so the Thread can exit if requested. 11539748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi struct pollfd pfd = { mInotifyFd, POLLIN, 0 }; 11549748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi ssize_t pollResult = poll(&pfd, 1, 1000); 11559748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 11569748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi if (pollResult == 0) { 11579748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi return true; 11589748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } else if (pollResult < 0) { 11599748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi ALOGE("Could not poll inotify events"); 11609748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi return false; 11619748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 11629748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 11639748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi char buff[BUFF_LEN] __attribute__ ((aligned(__alignof__(struct inotify_event))));; 11649748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi ssize_t length = read(mInotifyFd, buff, BUFF_LEN); 11659748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi if (length == 0) { 11669748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi return true; 11679748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } else if (length < 0) { 11689748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi ALOGE("Could not read inotify events"); 11699748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi return false; 11709748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 11719748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 11729748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi const struct inotify_event *event; 11739748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi for (char* ptr = buff; ptr < buff + length; ptr += sizeof(struct inotify_event) + event->len) { 11749748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi event = (const struct inotify_event *) ptr; 11759748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi if (event->wd == mSystemWd && strcmp(SYSTEM_TIME_DIR_NAME, event->name) == 0) { 11769748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi addTimeDirWatch(); 11779748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } else if (event->wd == mTimeWd && (strcmp(LAST_TIME_CHANGED_FILE_NAME, event->name) == 0 11789748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi || strcmp(ACCURATE_TIME_FLAG_FILE_NAME, event->name) == 0)) { 11799748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi return !mBootAnimation->updateIsTimeAccurate(); 11809748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 11819748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 11829748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 11839748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi return true; 11849748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi} 11859748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 11869748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchivoid BootAnimation::TimeCheckThread::addTimeDirWatch() { 11879748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi mTimeWd = inotify_add_watch(mInotifyFd, SYSTEM_TIME_DIR_PATH, 11889748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi IN_CLOSE_WRITE | IN_MOVED_TO | IN_ATTRIB); 11899748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi if (mTimeWd > 0) { 11909748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi // No need to watch for the time directory to be created if it already exists 11919748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi inotify_rm_watch(mInotifyFd, mSystemWd); 11929748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi mSystemWd = -1; 11939748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 11949748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi} 11959748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 11969748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchistatus_t BootAnimation::TimeCheckThread::readyToRun() { 11979748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi mInotifyFd = inotify_init(); 11989748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi if (mInotifyFd < 0) { 11999748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi ALOGE("Could not initialize inotify fd"); 12009748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi return NO_INIT; 12019748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 12029748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 12039748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi mSystemWd = inotify_add_watch(mInotifyFd, SYSTEM_DATA_DIR_PATH, IN_CREATE | IN_ATTRIB); 12049748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi if (mSystemWd < 0) { 12059748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi close(mInotifyFd); 12069748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi mInotifyFd = -1; 12079748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi ALOGE("Could not add watch for %s", SYSTEM_DATA_DIR_PATH); 12089748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi return NO_INIT; 12099748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 12109748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 12119748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi addTimeDirWatch(); 12129748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 12139748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi if (mBootAnimation->updateIsTimeAccurate()) { 12149748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi close(mInotifyFd); 12159748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi mInotifyFd = -1; 12169748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi return ALREADY_EXISTS; 12179748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi } 12189748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 12199748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi return NO_ERROR; 12209748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi} 12219748086fe267e21d243a49df1775905094a28dd9Damien Bargiacchi 1222a917353da0ed6079d45487a8c96b892c5d754637Geoffrey PitschBootAnimation::InitAudioThread::InitAudioThread(uint8_t* exampleAudioData, int exampleAudioLength) 1223a917353da0ed6079d45487a8c96b892c5d754637Geoffrey Pitsch : Thread(false), 1224a917353da0ed6079d45487a8c96b892c5d754637Geoffrey Pitsch mExampleAudioData(exampleAudioData), 1225a917353da0ed6079d45487a8c96b892c5d754637Geoffrey Pitsch mExampleAudioLength(exampleAudioLength) {} 1226a917353da0ed6079d45487a8c96b892c5d754637Geoffrey Pitsch 1227a917353da0ed6079d45487a8c96b892c5d754637Geoffrey Pitschbool BootAnimation::InitAudioThread::threadLoop() { 1228a917353da0ed6079d45487a8c96b892c5d754637Geoffrey Pitsch audioplay::create(mExampleAudioData, mExampleAudioLength); 1229a917353da0ed6079d45487a8c96b892c5d754637Geoffrey Pitsch // Exit immediately 1230a917353da0ed6079d45487a8c96b892c5d754637Geoffrey Pitsch return false; 1231a917353da0ed6079d45487a8c96b892c5d754637Geoffrey Pitsch} 1232a917353da0ed6079d45487a8c96b892c5d754637Geoffrey Pitsch 12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// --------------------------------------------------------------------------- 12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project; // namespace android 1237