summaryrefslogtreecommitdiffstats
path: root/cmds
diff options
context:
space:
mode:
authorChiou-Hao Hsu <chsu@codeaurora.org>2014-10-13 17:55:42 -0700
committerSteve Kondik <steve@cyngn.com>2015-10-26 16:09:10 -0700
commitd168891d421662aa2ed561a6657daf762a20fe53 (patch)
tree342363670a2769a9fdacfbd8705e30a1ff8cac0a /cmds
parentdc1604549bb8ab3a3e35dd48c4d6eae99e75503a (diff)
downloadframeworks_base-d168891d421662aa2ed561a6657daf762a20fe53.zip
frameworks_base-d168891d421662aa2ed561a6657daf762a20fe53.tar.gz
frameworks_base-d168891d421662aa2ed561a6657daf762a20fe53.tar.bz2
BootAnimation: Play boot/shutdown animation and music
Add support to show customized boot and shut down animation, as well as music. Change-Id: I69c87640175a96a18833a763a34afd362bbfb487 Conflicts: cmds/bootanimation/Android.mk cmds/bootanimation/BootAnimation.cpp Bootanimation: Fix the low memory device oom when run boot animation Low memory device is easily to be oom when run boot animation. Here we do optimize the boot animation GL Texture only one frame needed. That is free timely and re-init it again. When in boot animation, the fps=15, so it is ok to do the delete and re-init. CRs-Fixed: 572325 Change-Id: I1e81c3d0f3600ac895f9bd7bd00a284f3d4b7d4c bootanimtion: fix no boot sound due to error file descriptor -wrong file descriptor passed to setDataSource(fd, offset, length) API and causes no sound -use the default setDataSource(httpService,url,header) to parse the file of boot sound CRs-Fixed: 731547 Change-Id: I437e7d797cd13b7f8f8e0fbf81d5de99c55c27d1
Diffstat (limited to 'cmds')
-rw-r--r--cmds/bootanimation/Android.mk3
-rw-r--r--cmds/bootanimation/BootAnimation.cpp283
-rw-r--r--cmds/bootanimation/BootAnimation.h9
3 files changed, 287 insertions, 8 deletions
diff --git a/cmds/bootanimation/Android.mk b/cmds/bootanimation/Android.mk
index cc3b6f8..a2d5675 100644
--- a/cmds/bootanimation/Android.mk
+++ b/cmds/bootanimation/Android.mk
@@ -23,7 +23,8 @@ LOCAL_SHARED_LIBRARIES := \
libEGL \
libGLESv1_CM \
libgui \
- libtinyalsa
+ libtinyalsa \
+ libmedia
ifeq ($(TARGET_CONTINUOUS_SPLASH_ENABLED),true)
LOCAL_CFLAGS += -DCONTINUOUS_SPLASH
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 5b9ecd0..f7a75d3 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2007 The Android Open Source Project
+ * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,6 +25,8 @@
#include <utils/misc.h>
#include <signal.h>
#include <time.h>
+#include <pthread.h>
+#include <sys/select.h>
#include <cutils/properties.h>
@@ -54,6 +57,10 @@
#include <GLES/glext.h>
#include <EGL/eglext.h>
+#include <media/AudioSystem.h>
+#include <media/mediaplayer.h>
+#include <media/IMediaHTTPService.h>
+
#include "BootAnimation.h"
#include "AudioPlayer.h"
@@ -62,6 +69,16 @@
#define SYSTEM_ENCRYPTED_BOOTANIMATION_FILE "/system/media/bootanimation-encrypted.zip"
#define THEME_BOOTANIMATION_FILE "/data/system/theme/bootanimation.zip"
+#define OEM_SHUTDOWN_ANIMATION_FILE "/oem/media/shutdownanimation.zip"
+#define SYSTEM_SHUTDOWN_ANIMATION_FILE "/system/media/shutdownanimation.zip"
+#define SYSTEM_ENCRYPTED_SHUTDOWN_ANIMATION_FILE "/system/media/shutdownanimation-encrypted.zip"
+
+#define OEM_BOOT_MUSIC_FILE "/oem/media/boot.wav"
+#define SYSTEM_BOOT_MUSIC_FILE "/system/media/boot.wav"
+
+#define OEM_SHUTDOWN_MUSIC_FILE "/oem/media/shutdown.wav"
+#define SYSTEM_SHUTDOWN_MUSIC_FILE "/system/media/shutdown.wav"
+
#define EXIT_PROP_NAME "service.bootanim.exit"
namespace android {
@@ -70,6 +87,87 @@ static const int ANIM_ENTRY_NAME_MAX = 256;
// ---------------------------------------------------------------------------
+static pthread_mutex_t mp_lock;
+static pthread_cond_t mp_cond;
+static bool isMPlayerPrepared = false;
+static bool isMPlayerCompleted = false;
+
+class MPlayerListener : public MediaPlayerListener
+{
+ void notify(int msg, int ext1, int ext2, const Parcel *obj)
+ {
+ switch (msg) {
+ case MEDIA_NOP: // interface test message
+ break;
+ case MEDIA_PREPARED:
+ pthread_mutex_lock(&mp_lock);
+ isMPlayerPrepared = true;
+ pthread_cond_signal(&mp_cond);
+ pthread_mutex_unlock(&mp_lock);
+ break;
+ case MEDIA_PLAYBACK_COMPLETE:
+ pthread_mutex_lock(&mp_lock);
+ isMPlayerCompleted = true;
+ pthread_cond_signal(&mp_cond);
+ pthread_mutex_unlock(&mp_lock);
+ break;
+ default:
+ break;
+ }
+ }
+};
+
+static long getFreeMemory(void)
+{
+ int fd = open("/proc/meminfo", O_RDONLY);
+ const char* const sums[] = { "MemFree:", "Cached:", NULL };
+ const int sumsLen[] = { strlen("MemFree:"), strlen("Cached:"), 0 };
+ int num = 2;
+
+ if (fd < 0) {
+ ALOGW("Unable to open /proc/meminfo");
+ return -1;
+ }
+
+ char buffer[256];
+ const int len = read(fd, buffer, sizeof(buffer)-1);
+ close(fd);
+
+ if (len < 0) {
+ ALOGW("Unable to read /proc/meminfo");
+ return -1;
+ }
+ buffer[len] = 0;
+
+ size_t numFound = 0;
+ long mem = 0;
+
+ char* p = buffer;
+ while (*p && numFound < num) {
+ int i = 0;
+ while (sums[i]) {
+ if (strncmp(p, sums[i], sumsLen[i]) == 0) {
+ p += sumsLen[i];
+ while (*p == ' ') p++;
+ char* num = p;
+ while (*p >= '0' && *p <= '9') p++;
+ if (*p != 0) {
+ *p = 0;
+ p++;
+ if (*p == 0) p--;
+ }
+ mem += atoll(num);
+ numFound++;
+ break;
+ }
+ i++;
+ }
+ p++;
+ }
+
+ return numFound > 0 ? mem : -1;
+}
+
BootAnimation::BootAnimation() : Thread(false), mZip(NULL)
{
mSession = new SurfaceComposerClient();
@@ -289,12 +387,14 @@ status_t BootAnimation::readyToRun() {
char decrypt[PROPERTY_VALUE_MAX];
property_get("vold.decrypt", decrypt, "");
+ // Use customized resources for boot and showdown animation
+ // instead of system predefined boot animation files.
bool encryptedAnimation = atoi(decrypt) != 0 || !strcmp("trigger_restart_min_framework", decrypt);
ZipFileRO* zipFile = NULL;
if ((encryptedAnimation &&
- (access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0) &&
- ((zipFile = ZipFileRO::open(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE)) != NULL)) ||
+ (access(getAnimationFileName(IMG_ENC), R_OK) == 0) &&
+ ((zipFile = ZipFileRO::open(getAnimationFileName(IMG_ENC))) != NULL)) ||
((access(THEME_BOOTANIMATION_FILE, R_OK) == 0) &&
((zipFile = ZipFileRO::open(THEME_BOOTANIMATION_FILE)) != NULL)) ||
@@ -303,8 +403,13 @@ status_t BootAnimation::readyToRun() {
((zipFile = ZipFileRO::open(OEM_BOOTANIMATION_FILE)) != NULL)) ||
((access(SYSTEM_BOOTANIMATION_FILE, R_OK) == 0) &&
- ((zipFile = ZipFileRO::open(SYSTEM_BOOTANIMATION_FILE)) != NULL))) {
+ ((zipFile = ZipFileRO::open(SYSTEM_BOOTANIMATION_FILE)) != NULL)) ||
+ ((access(getAnimationFileName(IMG_DATA), R_OK) == 0) &&
+ ((zipFile = ZipFileRO::open(getAnimationFileName(IMG_DATA))) != NULL)) ||
+
+ ((access(getAnimationFileName(IMG_SYS), R_OK) == 0) &&
+ ((zipFile = ZipFileRO::open(getAnimationFileName(IMG_SYS))) != NULL))) {
mZip = zipFile;
}
@@ -458,6 +563,7 @@ bool BootAnimation::readFile(const char* name, String8& outString)
bool BootAnimation::movie()
{
+ char value[PROPERTY_VALUE_MAX];
String8 desString;
if (!readFile("desc.txt", desString)) {
@@ -589,11 +695,37 @@ bool BootAnimation::movie()
Region clearReg(Rect(mWidth, mHeight));
clearReg.subtractSelf(Rect(xc, yc, xc+animation.width, yc+animation.height));
+ pthread_mutex_init(&mp_lock, NULL);
+ pthread_cond_init(&mp_cond, NULL);
+
+ property_get("persist.sys.silent", value, "null");
+ if (strncmp(value, "1", 1) != 0) {
+ playBackgroundMusic();
+ }
for (size_t i=0 ; i<pcount ; i++) {
const Animation::Part& part(animation.parts[i]);
const size_t fcount = part.frames.size();
glBindTexture(GL_TEXTURE_2D, 0);
+ /*calculate if we need to runtime save memory
+ * condition: runtime free memory is less than the textures that will used.
+ * needSaveMem default to be false
+ */
+ GLint mMaxTextureSize;
+ bool needSaveMem = false;
+ GLuint mTextureid;
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
+ //ALOGD("freemem:%ld, %d", getFreeMemory(), mMaxTextureSize);
+ if(getFreeMemory() < mMaxTextureSize * mMaxTextureSize * fcount / 1024) {
+ ALOGD("Use save memory method, maybe small fps in actual.");
+ needSaveMem = true;
+ glGenTextures(1, &mTextureid);
+ glBindTexture(GL_TEXTURE_2D, mTextureid);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ }
+
for (int r=0 ; !part.count || r<part.count ; r++) {
// Exit any non playuntil complete parts immediately
if(exitPending() && !part.playUntilComplete)
@@ -614,10 +746,10 @@ bool BootAnimation::movie()
const Animation::Frame& frame(part.frames[j]);
nsecs_t lastFrame = systemTime();
- if (r > 0) {
+ if (r > 0 && !needSaveMem) {
glBindTexture(GL_TEXTURE_2D, frame.tid);
} else {
- if (part.count != 1) {
+ if (!needSaveMem && part.count != 1) {
glGenTextures(1, &frame.tid);
glBindTexture(GL_TEXTURE_2D, frame.tid);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@@ -670,17 +802,156 @@ bool BootAnimation::movie()
}
// free the textures for this part
- if (part.count != 1) {
+ if (!needSaveMem && part.count != 1) {
for (size_t j=0 ; j<fcount ; j++) {
const Animation::Frame& frame(part.frames[j]);
glDeleteTextures(1, &frame.tid);
}
}
+
+ if (needSaveMem) {
+ glDeleteTextures(1, &mTextureid);
+ }
+
+ }
+
+ ALOGD("waiting for media player to complete.");
+ struct timespec timeout;
+ clock_gettime(CLOCK_REALTIME, &timeout);
+ timeout.tv_sec += 5; //timeout after 5s.
+
+ pthread_mutex_lock(&mp_lock);
+ while (!isMPlayerCompleted) {
+ int err = pthread_cond_timedwait(&mp_cond, &mp_lock, &timeout);
+ if (err == ETIMEDOUT) {
+ break;
+ }
}
+ pthread_mutex_unlock(&mp_lock);
+ ALOGD("media player is completed.");
+
+ pthread_cond_destroy(&mp_cond);
+ pthread_mutex_destroy(&mp_lock);
return false;
}
+char *BootAnimation::getAnimationFileName(ImageID image)
+{
+ char *fileName[2][3] = { { OEM_BOOTANIMATION_FILE,
+ SYSTEM_BOOTANIMATION_FILE,
+ SYSTEM_ENCRYPTED_BOOTANIMATION_FILE }, {
+ OEM_SHUTDOWN_ANIMATION_FILE,
+ SYSTEM_SHUTDOWN_ANIMATION_FILE,
+ SYSTEM_ENCRYPTED_SHUTDOWN_ANIMATION_FILE} };
+ int state;
+
+ state = checkBootState() ? 0 : 1;
+
+ return fileName[state][image];
+}
+
+char *BootAnimation::getBootRingtoneFileName(ImageID image)
+{
+ if (image == IMG_ENC) {
+ return NULL;
+ }
+
+ char *fileName[2][2] = { { OEM_BOOT_MUSIC_FILE,
+ SYSTEM_BOOT_MUSIC_FILE }, {
+ OEM_SHUTDOWN_MUSIC_FILE,
+ SYSTEM_SHUTDOWN_MUSIC_FILE } };
+ int state;
+
+ state = checkBootState() ? 0 : 1;
+
+ return fileName[state][image];
+}
+
+
+void BootAnimation::playBackgroundMusic(void)
+{
+ //Shutdown music is playing in ShutdownThread.java
+ if (!checkBootState()) {
+ return;
+ }
+
+ /* Make sure sound cards are populated */
+ FILE* fp = NULL;
+ if ((fp = fopen("/proc/asound/cards", "r")) == NULL) {
+ ALOGW("Cannot open /proc/asound/cards file to get sound card info.");
+ }
+
+ char value[PROPERTY_VALUE_MAX];
+ property_get("qcom.audio.init", value, "null");
+ if (strncmp(value, "complete", 8) != 0) {
+ ALOGW("Audio service is not initiated.");
+ }
+
+ fclose(fp);
+
+ char *fileName;
+ if (((fileName = getBootRingtoneFileName(IMG_DATA)) != NULL && access(fileName, R_OK) == 0) ||
+ ((fileName = getBootRingtoneFileName(IMG_SYS)) != NULL
+ && access(fileName, R_OK) == 0)) {
+ pthread_t tid;
+ pthread_create(&tid, NULL, playMusic, (void *)fileName);
+ pthread_join(tid, NULL);
+ }
+}
+bool BootAnimation::checkBootState(void)
+{
+ char value[PROPERTY_VALUE_MAX];
+ bool ret = true;
+
+ property_get("sys.shutdown.requested", value, "null");
+ if (strncmp(value, "null", 4) != 0) {
+ ret = false;
+ }
+
+ return ret;
+}
+
+void* playMusic(void* arg)
+{
+ int index = 0;
+ char *fileName = (char *)arg;
+ sp<MediaPlayer> mp = new MediaPlayer();
+ sp<MPlayerListener> mListener = new MPlayerListener();
+ if (mp != NULL) {
+ ALOGD("starting to play %s", fileName);
+ mp->setListener(mListener);
+
+ if (mp->setDataSource(NULL, fileName, NULL) == NO_ERROR) {
+ mp->setAudioStreamType(AUDIO_STREAM_ENFORCED_AUDIBLE);
+ mp->prepare();
+ } else {
+ ALOGE("failed to setDataSource for %s", fileName);
+ return NULL;
+ }
+
+ //waiting for media player is prepared.
+ pthread_mutex_lock(&mp_lock);
+ while (!isMPlayerPrepared) {
+ pthread_cond_wait(&mp_cond, &mp_lock);
+ }
+ pthread_mutex_unlock(&mp_lock);
+
+ audio_devices_t device = AudioSystem::getDevicesForStream(AUDIO_STREAM_ENFORCED_AUDIBLE);
+ AudioSystem::initStreamVolume(AUDIO_STREAM_ENFORCED_AUDIBLE,0,7);
+ AudioSystem::setStreamVolumeIndex(AUDIO_STREAM_ENFORCED_AUDIBLE, 7, device);
+
+ AudioSystem::getStreamVolumeIndex(AUDIO_STREAM_ENFORCED_AUDIBLE, &index, device);
+ if (index != 0) {
+ ALOGD("playing %s", fileName);
+ mp->seekTo(0);
+ mp->start();
+ } else {
+ ALOGW("current volume is zero.");
+ }
+ }
+ return NULL;
+}
// ---------------------------------------------------------------------------
}
diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
index f968b25..758f7f7 100644
--- a/cmds/bootanimation/BootAnimation.h
+++ b/cmds/bootanimation/BootAnimation.h
@@ -87,12 +87,18 @@ private:
bool readFile(const char* name, String8& outString);
bool movie();
+ enum ImageID { IMG_DATA = 0, IMG_SYS = 1, IMG_ENC = 2 };
+ char *getAnimationFileName(ImageID image);
+ char *getBootRingtoneFileName(ImageID image);
+ void playBackgroundMusic();
+ bool checkBootState();
void checkExit();
+ void checkShowAndroid();
sp<SurfaceComposerClient> mSession;
sp<AudioPlayer> mAudioPlayer;
AssetManager mAssets;
- Texture mAndroid[2];
+ Texture mAndroid[3];
int mWidth;
int mHeight;
EGLDisplay mDisplay;
@@ -103,6 +109,7 @@ private:
ZipFileRO *mZip;
};
+static void* playMusic(void* arg);
// ---------------------------------------------------------------------------
}; // namespace android