summaryrefslogtreecommitdiffstats
path: root/cmds/bootanimation/BootAnimation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cmds/bootanimation/BootAnimation.cpp')
-rw-r--r--cmds/bootanimation/BootAnimation.cpp145
1 files changed, 112 insertions, 33 deletions
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 7f7ae2c..b2474f2 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#define LOG_NDEBUG 0
#define LOG_TAG "BootAnimation"
#include <stdint.h>
@@ -30,28 +31,28 @@
#include <utils/Atomic.h>
#include <utils/Errors.h>
#include <utils/Log.h>
-#include <utils/threads.h>
#include <ui/PixelFormat.h>
#include <ui/Rect.h>
#include <ui/Region.h>
#include <ui/DisplayInfo.h>
-#include <ui/FramebufferNativeWindow.h>
#include <gui/ISurfaceComposer.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
-#include <core/SkBitmap.h>
-#include <core/SkStream.h>
-#include <core/SkImageDecoder.h>
+#include <SkBitmap.h>
+#include <SkStream.h>
+#include <SkImageDecoder.h>
#include <GLES/gl.h>
#include <GLES/glext.h>
#include <EGL/eglext.h>
#include "BootAnimation.h"
+#include "AudioPlayer.h"
+#define OEM_BOOTANIMATION_FILE "/oem/media/bootanimation.zip"
#define SYSTEM_BOOTANIMATION_FILE "/system/media/bootanimation.zip"
#define SYSTEM_ENCRYPTED_BOOTANIMATION_FILE "/system/media/bootanimation-encrypted.zip"
#define EXIT_PROP_NAME "service.bootanim.exit"
@@ -99,6 +100,9 @@ void BootAnimation::binderDied(const wp<IBinder>&)
// might be blocked on a condition variable that will never be updated.
kill( getpid(), SIGKILL );
requestExit();
+ if (mAudioPlayer != NULL) {
+ mAudioPlayer->requestExit();
+ }
}
status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets,
@@ -108,7 +112,7 @@ status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets,
return NO_INIT;
SkBitmap bitmap;
SkImageDecoder::DecodeMemory(asset->getBuffer(false), asset->getLength(),
- &bitmap, SkBitmap::kNo_Config, SkImageDecoder::kDecodePixels_Mode);
+ &bitmap, kUnknown_SkColorType, SkImageDecoder::kDecodePixels_Mode);
asset->close();
delete asset;
@@ -127,20 +131,20 @@ status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets,
glGenTextures(1, &texture->name);
glBindTexture(GL_TEXTURE_2D, texture->name);
- switch (bitmap.getConfig()) {
- case SkBitmap::kA8_Config:
+ switch (bitmap.colorType()) {
+ case kAlpha_8_SkColorType:
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_ALPHA,
GL_UNSIGNED_BYTE, p);
break;
- case SkBitmap::kARGB_4444_Config:
+ case kARGB_4444_SkColorType:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA,
GL_UNSIGNED_SHORT_4_4_4_4, p);
break;
- case SkBitmap::kARGB_8888_Config:
+ case kN32_SkColorType:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA,
GL_UNSIGNED_BYTE, p);
break;
- case SkBitmap::kRGB_565_Config:
+ case kRGB_565_SkColorType:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB,
GL_UNSIGNED_SHORT_5_6_5, p);
break;
@@ -166,7 +170,7 @@ status_t BootAnimation::initTexture(const Animation::Frame& frame)
if (codec) {
codec->setDitherImage(false);
codec->decode(&stream, &bitmap,
- SkBitmap::kARGB_8888_Config,
+ kN32_SkColorType,
SkImageDecoder::kDecodePixels_Mode);
delete codec;
}
@@ -190,8 +194,8 @@ status_t BootAnimation::initTexture(const Animation::Frame& frame)
if (tw < w) tw <<= 1;
if (th < h) th <<= 1;
- switch (bitmap.getConfig()) {
- case SkBitmap::kARGB_8888_Config:
+ switch (bitmap.colorType()) {
+ case kN32_SkColorType:
if (tw != w || th != h) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tw, th, 0, GL_RGBA,
GL_UNSIGNED_BYTE, 0);
@@ -203,7 +207,7 @@ status_t BootAnimation::initTexture(const Animation::Frame& frame)
}
break;
- case SkBitmap::kRGB_565_Config:
+ case kRGB_565_SkColorType:
if (tw != w || th != h) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tw, th, 0, GL_RGB,
GL_UNSIGNED_SHORT_5_6_5, 0);
@@ -289,6 +293,9 @@ status_t BootAnimation::readyToRun() {
(access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0) &&
((zipFile = ZipFileRO::open(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE)) != NULL)) ||
+ ((access(OEM_BOOTANIMATION_FILE, R_OK) == 0) &&
+ ((zipFile = ZipFileRO::open(OEM_BOOTANIMATION_FILE)) != NULL)) ||
+
((access(SYSTEM_BOOTANIMATION_FILE, R_OK) == 0) &&
((zipFile = ZipFileRO::open(SYSTEM_BOOTANIMATION_FILE)) != NULL))) {
mZip = zipFile;
@@ -391,29 +398,76 @@ void BootAnimation::checkExit() {
int exitnow = atoi(value);
if (exitnow) {
requestExit();
+ if (mAudioPlayer != NULL) {
+ mAudioPlayer->requestExit();
+ }
}
}
-bool BootAnimation::movie()
+// Parse a color represented as an HTML-style 'RRGGBB' string: each pair of
+// characters in str is a hex number in [0, 255], which are converted to
+// floating point values in the range [0.0, 1.0] and placed in the
+// corresponding elements of color.
+//
+// If the input string isn't valid, parseColor returns false and color is
+// left unchanged.
+static bool parseColor(const char str[7], float color[3]) {
+ float tmpColor[3];
+ for (int i = 0; i < 3; i++) {
+ int val = 0;
+ for (int j = 0; j < 2; j++) {
+ val *= 16;
+ char c = str[2*i + j];
+ if (c >= '0' && c <= '9') val += c - '0';
+ else if (c >= 'A' && c <= 'F') val += (c - 'A') + 10;
+ else if (c >= 'a' && c <= 'f') val += (c - 'a') + 10;
+ else return false;
+ }
+ tmpColor[i] = static_cast<float>(val) / 255.0f;
+ }
+ memcpy(color, tmpColor, sizeof(tmpColor));
+ return true;
+}
+
+bool BootAnimation::readFile(const char* name, String8& outString)
{
- ZipEntryRO desc = mZip->findEntryByName("desc.txt");
- ALOGE_IF(!desc, "couldn't find desc.txt");
- if (!desc) {
+ ZipEntryRO entry = mZip->findEntryByName(name);
+ ALOGE_IF(!entry, "couldn't find %s", name);
+ if (!entry) {
return false;
}
- FileMap* descMap = mZip->createEntryFileMap(desc);
- mZip->releaseEntry(desc);
- ALOGE_IF(!descMap, "descMap is null");
- if (!descMap) {
+ FileMap* entryMap = mZip->createEntryFileMap(entry);
+ mZip->releaseEntry(entry);
+ ALOGE_IF(!entryMap, "entryMap is null");
+ if (!entryMap) {
return false;
}
- String8 desString((char const*)descMap->getDataPtr(),
- descMap->getDataLength());
- descMap->release();
+ outString.setTo((char const*)entryMap->getDataPtr(), entryMap->getDataLength());
+ entryMap->release();
+ return true;
+}
+
+bool BootAnimation::movie()
+{
+ String8 desString;
+
+ if (!readFile("desc.txt", desString)) {
+ return false;
+ }
char const* s = desString.string();
+ // Create and initialize an AudioPlayer if we have an audio_conf.txt file
+ String8 audioConf;
+ if (readFile("audio_conf.txt", audioConf)) {
+ mAudioPlayer = new AudioPlayer;
+ if (!mAudioPlayer->init(audioConf.string())) {
+ ALOGE("mAudioPlayer.init failed");
+ mAudioPlayer = NULL;
+ }
+ }
+
Animation animation;
// Parse the description file
@@ -424,20 +478,29 @@ bool BootAnimation::movie()
const char* l = line.string();
int fps, width, height, count, pause;
char path[ANIM_ENTRY_NAME_MAX];
+ char color[7] = "000000"; // default to black if unspecified
+
char pathType;
if (sscanf(l, "%d %d %d", &width, &height, &fps) == 3) {
- //LOGD("> w=%d, h=%d, fps=%d", width, height, fps);
+ // ALOGD("> w=%d, h=%d, fps=%d", width, height, fps);
animation.width = width;
animation.height = height;
animation.fps = fps;
}
- else if (sscanf(l, " %c %d %d %s", &pathType, &count, &pause, path) == 4) {
- //LOGD("> type=%c, count=%d, pause=%d, path=%s", pathType, count, pause, path);
+ else if (sscanf(l, " %c %d %d %s #%6s", &pathType, &count, &pause, path, color) >= 4) {
+ // ALOGD("> type=%c, count=%d, pause=%d, path=%s, color=%s", pathType, count, pause, path, color);
Animation::Part part;
part.playUntilComplete = pathType == 'c';
part.count = count;
part.pause = pause;
part.path = path;
+ part.audioFile = NULL;
+ if (!parseColor(color, part.backgroundColor)) {
+ ALOGE("> invalid color '#%s'", color);
+ part.backgroundColor[0] = 0.0f;
+ part.backgroundColor[1] = 0.0f;
+ part.backgroundColor[2] = 0.0f;
+ }
animation.parts.add(part);
}
@@ -472,11 +535,16 @@ bool BootAnimation::movie()
if (method == ZipFileRO::kCompressStored) {
FileMap* map = mZip->createEntryFileMap(entry);
if (map) {
- Animation::Frame frame;
- frame.name = leaf;
- frame.map = map;
Animation::Part& part(animation.parts.editItemAt(j));
- part.frames.add(frame);
+ if (leaf == "audio.wav") {
+ // a part may have at most one audio file
+ part.audioFile = map;
+ } else {
+ Animation::Frame frame;
+ frame.name = leaf;
+ frame.map = map;
+ part.frames.add(frame);
+ }
}
}
}
@@ -523,6 +591,17 @@ bool BootAnimation::movie()
if(exitPending() && !part.playUntilComplete)
break;
+ // only play audio file the first time we animate the part
+ if (r == 0 && mAudioPlayer != NULL && part.audioFile) {
+ mAudioPlayer->playFile(part.audioFile);
+ }
+
+ glClearColor(
+ part.backgroundColor[0],
+ part.backgroundColor[1],
+ part.backgroundColor[2],
+ 1.0f);
+
for (size_t j=0 ; j<fcount && (!exitPending() || part.playUntilComplete) ; j++) {
const Animation::Frame& frame(part.frames[j]);
nsecs_t lastFrame = systemTime();