summaryrefslogtreecommitdiff
path: root/cmds/bootanimation/BootAnimation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cmds/bootanimation/BootAnimation.cpp')
-rw-r--r--cmds/bootanimation/BootAnimation.cpp182
1 files changed, 113 insertions, 69 deletions
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 95bdc4a79af9..db384baff4d7 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -70,8 +70,10 @@
namespace android {
static const char OEM_BOOTANIMATION_FILE[] = "/oem/media/bootanimation.zip";
+static const char PRODUCT_BOOTANIMATION_DARK_FILE[] = "/product/media/bootanimation-dark.zip";
static const char PRODUCT_BOOTANIMATION_FILE[] = "/product/media/bootanimation.zip";
static const char SYSTEM_BOOTANIMATION_FILE[] = "/system/media/bootanimation.zip";
+static const char APEX_BOOTANIMATION_FILE[] = "/apex/com.android.bootanimation/etc/bootanimation.zip";
static const char PRODUCT_ENCRYPTED_BOOTANIMATION_FILE[] = "/product/media/bootanimation-encrypted.zip";
static const char SYSTEM_ENCRYPTED_BOOTANIMATION_FILE[] = "/system/media/bootanimation-encrypted.zip";
static const char OEM_SHUTDOWNANIMATION_FILE[] = "/oem/media/shutdownanimation.zip";
@@ -105,7 +107,7 @@ static constexpr size_t TEXT_POS_LEN_MAX = 16;
BootAnimation::BootAnimation(sp<Callbacks> callbacks)
: Thread(false), mClockEnabled(true), mTimeIsAccurate(false),
- mTimeFormat12Hour(false), mTimeCheckThread(NULL), mCallbacks(callbacks) {
+ mTimeFormat12Hour(false), mTimeCheckThread(nullptr), mCallbacks(callbacks) {
mSession = new SurfaceComposerClient();
std::string powerCtl = android::base::GetProperty("sys.powerctl", "");
@@ -114,13 +116,30 @@ BootAnimation::BootAnimation(sp<Callbacks> callbacks)
} else {
mShuttingDown = true;
}
+ ALOGD("%sAnimationStartTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",
+ elapsedRealtime());
+}
+
+BootAnimation::~BootAnimation() {
+ if (mAnimation != nullptr) {
+ releaseAnimation(mAnimation);
+ mAnimation = nullptr;
+ }
+ ALOGD("%sAnimationStopTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",
+ elapsedRealtime());
}
void BootAnimation::onFirstRef() {
status_t err = mSession->linkToComposerDeath(this);
- ALOGE_IF(err, "linkToComposerDeath failed (%s) ", strerror(-err));
+ SLOGE_IF(err, "linkToComposerDeath failed (%s) ", strerror(-err));
if (err == NO_ERROR) {
- run("BootAnimation", PRIORITY_DISPLAY);
+ // Load the animation content -- this can be slow (eg 200ms)
+ // called before waitForSurfaceFlinger() in main() to avoid wait
+ ALOGD("%sAnimationPreloadTiming start time: %" PRId64 "ms",
+ mShuttingDown ? "Shutdown" : "Boot", elapsedRealtime());
+ preloadAnimation();
+ ALOGD("%sAnimationPreloadStopTiming start time: %" PRId64 "ms",
+ mShuttingDown ? "Shutdown" : "Boot", elapsedRealtime());
}
}
@@ -128,11 +147,10 @@ sp<SurfaceComposerClient> BootAnimation::session() const {
return mSession;
}
-
void BootAnimation::binderDied(const wp<IBinder>&)
{
// woah, surfaceflinger died!
- ALOGD("SurfaceFlinger died, exiting...");
+ SLOGD("SurfaceFlinger died, exiting...");
// calling requestExit() is not enough here because the Surface code
// might be blocked on a condition variable that will never be updated.
@@ -143,7 +161,7 @@ void BootAnimation::binderDied(const wp<IBinder>&)
status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets,
const char* name) {
Asset* asset = assets.open(name, Asset::ACCESS_BUFFER);
- if (asset == NULL)
+ if (asset == nullptr)
return NO_INIT;
SkBitmap bitmap;
sk_sp<SkData> data = SkData::MakeWithoutCopy(asset->getBuffer(false),
@@ -221,7 +239,7 @@ status_t BootAnimation::initTexture(FileMap* map, int* width, int* height)
case kN32_SkColorType:
if (!mUseNpotTextures && (tw != w || th != h)) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tw, th, 0, GL_RGBA,
- GL_UNSIGNED_BYTE, 0);
+ GL_UNSIGNED_BYTE, nullptr);
glTexSubImage2D(GL_TEXTURE_2D, 0,
0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, p);
} else {
@@ -233,7 +251,7 @@ status_t BootAnimation::initTexture(FileMap* map, int* width, int* height)
case kRGB_565_SkColorType:
if (!mUseNpotTextures && (tw != w || th != h)) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tw, th, 0, GL_RGB,
- GL_UNSIGNED_SHORT_5_6_5, 0);
+ GL_UNSIGNED_SHORT_5_6_5, nullptr);
glTexSubImage2D(GL_TEXTURE_2D, 0,
0, 0, w, h, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, p);
} else {
@@ -256,10 +274,12 @@ status_t BootAnimation::initTexture(FileMap* map, int* width, int* height)
status_t BootAnimation::readyToRun() {
mAssets.addDefaultAssets();
- sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(
- ISurfaceComposer::eDisplayIdMain));
+ mDisplayToken = SurfaceComposerClient::getInternalDisplayToken();
+ if (mDisplayToken == nullptr)
+ return -1;
+
DisplayInfo dinfo;
- status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &dinfo);
+ status_t status = SurfaceComposerClient::getDisplayInfo(mDisplayToken, &dinfo);
if (status)
return -1;
@@ -289,10 +309,10 @@ status_t BootAnimation::readyToRun() {
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- eglInitialize(display, 0, 0);
+ eglInitialize(display, nullptr, nullptr);
eglChooseConfig(display, attribs, &config, 1, &numConfigs);
- surface = eglCreateWindowSurface(display, config, s.get(), NULL);
- context = eglCreateContext(display, config, NULL, NULL);
+ surface = eglCreateWindowSurface(display, config, s.get(), nullptr);
+ context = eglCreateContext(display, config, nullptr, nullptr);
eglQuerySurface(display, surface, EGL_WIDTH, &w);
eglQuerySurface(display, surface, EGL_HEIGHT, &h);
@@ -308,6 +328,20 @@ status_t BootAnimation::readyToRun() {
mFlingerSurface = s;
mTargetInset = -1;
+ return NO_ERROR;
+}
+
+bool BootAnimation::preloadAnimation() {
+ findBootAnimationFile();
+ if (!mZipFileName.isEmpty()) {
+ mAnimation = loadAnimation(mZipFileName);
+ return (mAnimation != nullptr);
+ }
+
+ return false;
+}
+
+void BootAnimation::findBootAnimationFile() {
// If the device has encryption turned on or is in process
// of being encrypted we show the encrypted boot animation.
char decrypt[PROPERTY_VALUE_MAX];
@@ -322,22 +356,24 @@ status_t BootAnimation::readyToRun() {
for (const char* f : encryptedBootFiles) {
if (access(f, R_OK) == 0) {
mZipFileName = f;
- return NO_ERROR;
+ return;
}
}
}
+
+ const bool playDarkAnim = android::base::GetIntProperty("ro.boot.theme", 0) == 1;
static const char* bootFiles[] =
- {PRODUCT_BOOTANIMATION_FILE, OEM_BOOTANIMATION_FILE, SYSTEM_BOOTANIMATION_FILE};
+ {APEX_BOOTANIMATION_FILE, playDarkAnim ? PRODUCT_BOOTANIMATION_DARK_FILE : PRODUCT_BOOTANIMATION_FILE,
+ OEM_BOOTANIMATION_FILE, SYSTEM_BOOTANIMATION_FILE};
static const char* shutdownFiles[] =
- {PRODUCT_SHUTDOWNANIMATION_FILE, OEM_SHUTDOWNANIMATION_FILE, SYSTEM_SHUTDOWNANIMATION_FILE};
+ {PRODUCT_SHUTDOWNANIMATION_FILE, OEM_SHUTDOWNANIMATION_FILE, SYSTEM_SHUTDOWNANIMATION_FILE, ""};
for (const char* f : (!mShuttingDown ? bootFiles : shutdownFiles)) {
if (access(f, R_OK) == 0) {
mZipFileName = f;
- return NO_ERROR;
+ return;
}
}
- return NO_ERROR;
}
bool BootAnimation::threadLoop()
@@ -364,7 +400,7 @@ bool BootAnimation::threadLoop()
bool BootAnimation::android()
{
- ALOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",
+ SLOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",
elapsedRealtime());
initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png");
initTexture(&mAndroid[1], mAssets, "images/android-logo-shine.png");
@@ -512,14 +548,14 @@ static bool parseColor(const char str[7], float color[3]) {
static bool readFile(ZipFileRO* zip, const char* name, String8& outString)
{
ZipEntryRO entry = zip->findEntryByName(name);
- ALOGE_IF(!entry, "couldn't find %s", name);
+ SLOGE_IF(!entry, "couldn't find %s", name);
if (!entry) {
return false;
}
FileMap* entryMap = zip->createEntryFileMap(entry);
zip->releaseEntry(entry);
- ALOGE_IF(!entryMap, "entryMap is null");
+ SLOGE_IF(!entryMap, "entryMap is null");
if (!entryMap) {
return false;
}
@@ -620,7 +656,7 @@ void BootAnimation::drawClock(const Font& font, const int xPos, const int yPos)
size_t length = strftime(timeBuff, TIME_LENGTH, timeFormat, timeInfo);
if (length != TIME_LENGTH - 1) {
- ALOGE("Couldn't format time; abandoning boot animation clock");
+ SLOGE("Couldn't format time; abandoning boot animation clock");
mClockEnabled = false;
return;
}
@@ -643,7 +679,7 @@ bool BootAnimation::parseAnimationDesc(Animation& animation)
// Parse the description file
for (;;) {
const char* endl = strstr(s, "\n");
- if (endl == NULL) break;
+ if (endl == nullptr) break;
String8 line(s, endl - s);
const char* l = line.string();
int fps = 0;
@@ -658,23 +694,23 @@ bool BootAnimation::parseAnimationDesc(Animation& animation)
char pathType;
if (sscanf(l, "%d %d %d", &width, &height, &fps) == 3) {
- // ALOGD("> w=%d, h=%d, fps=%d", width, height, fps);
+ // SLOGD("> 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 %" STRTO(ANIM_PATH_MAX) "s #%6s %16s %16s",
&pathType, &count, &pause, path, color, clockPos1, clockPos2) >= 4) {
- //ALOGD("> type=%c, count=%d, pause=%d, path=%s, color=%s, clockPos1=%s, clockPos2=%s",
+ //SLOGD("> type=%c, count=%d, pause=%d, path=%s, color=%s, clockPos1=%s, clockPos2=%s",
// pathType, count, pause, path, color, clockPos1, clockPos2);
Animation::Part part;
part.playUntilComplete = pathType == 'c';
part.count = count;
part.pause = pause;
part.path = path;
- part.audioData = NULL;
- part.animation = NULL;
+ part.audioData = nullptr;
+ part.animation = nullptr;
if (!parseColor(color, part.backgroundColor)) {
- ALOGE("> invalid color '#%s'", color);
+ SLOGE("> invalid color '#%s'", color);
part.backgroundColor[0] = 0.0f;
part.backgroundColor[1] = 0.0f;
part.backgroundColor[2] = 0.0f;
@@ -683,14 +719,14 @@ bool BootAnimation::parseAnimationDesc(Animation& animation)
animation.parts.add(part);
}
else if (strcmp(l, "$SYSTEM") == 0) {
- // ALOGD("> SYSTEM");
+ // SLOGD("> SYSTEM");
Animation::Part part;
part.playUntilComplete = false;
part.count = 1;
part.pause = 0;
- part.audioData = NULL;
+ part.audioData = nullptr;
part.animation = loadAnimation(String8(SYSTEM_BOOTANIMATION_FILE));
- if (part.animation != NULL)
+ if (part.animation != nullptr)
animation.parts.add(part);
}
s = ++endl;
@@ -703,7 +739,7 @@ bool BootAnimation::preloadZip(Animation& animation)
{
// read all the data structures
const size_t pcount = animation.parts.size();
- void *cookie = NULL;
+ void *cookie = nullptr;
ZipFileRO* zip = animation.zip;
if (!zip->startIteration(&cookie)) {
return false;
@@ -711,10 +747,10 @@ bool BootAnimation::preloadZip(Animation& animation)
ZipEntryRO entry;
char name[ANIM_ENTRY_NAME_MAX];
- while ((entry = zip->nextEntry(cookie)) != NULL) {
+ while ((entry = zip->nextEntry(cookie)) != nullptr) {
const int foundEntryName = zip->getEntryFileName(entry, name, ANIM_ENTRY_NAME_MAX);
if (foundEntryName > ANIM_ENTRY_NAME_MAX || foundEntryName == -1) {
- ALOGE("Error fetching entry file name");
+ SLOGE("Error fetching entry file name");
continue;
}
@@ -734,7 +770,7 @@ bool BootAnimation::preloadZip(Animation& animation)
if (path == animation.parts[j].path) {
uint16_t method;
// supports only stored png files
- if (zip->getEntryInfo(entry, &method, NULL, NULL, NULL, NULL, NULL)) {
+ if (zip->getEntryInfo(entry, &method, nullptr, nullptr, nullptr, nullptr, nullptr)) {
if (method == ZipFileRO::kCompressStored) {
FileMap* map = zip->createEntryFileMap(entry);
if (map) {
@@ -758,7 +794,7 @@ bool BootAnimation::preloadZip(Animation& animation)
}
}
} else {
- ALOGE("bootanimation.zip is compressed; must be only stored");
+ SLOGE("bootanimation.zip is compressed; must be only stored");
}
}
}
@@ -772,7 +808,7 @@ bool BootAnimation::preloadZip(Animation& animation)
for (size_t frameIdx = 0; frameIdx < part.frames.size(); frameIdx++) {
const char* endl = strstr(trimDataStr, "\n");
// No more trimData for this part.
- if (endl == NULL) {
+ if (endl == nullptr) {
break;
}
String8 line(trimDataStr, endl - trimDataStr);
@@ -786,14 +822,12 @@ bool BootAnimation::preloadZip(Animation& animation)
frame.trimX = x;
frame.trimY = y;
} else {
- ALOGE("Error parsing trim.txt, line: %s", lineStr);
+ SLOGE("Error parsing trim.txt, line: %s", lineStr);
break;
}
}
}
- mCallbacks->init(animation.parts);
-
zip->endIteration(cookie);
return true;
@@ -801,13 +835,25 @@ bool BootAnimation::preloadZip(Animation& animation)
bool BootAnimation::movie()
{
- Animation* animation = loadAnimation(mZipFileName);
- if (animation == NULL)
+ if (mAnimation == nullptr) {
+ mAnimation = loadAnimation(mZipFileName);
+ }
+
+ if (mAnimation == nullptr)
return false;
+ // mCallbacks->init() may get called recursively,
+ // this loop is needed to get the same results
+ for (const Animation::Part& part : mAnimation->parts) {
+ if (part.animation != nullptr) {
+ mCallbacks->init(part.animation->parts);
+ }
+ }
+ mCallbacks->init(mAnimation->parts);
+
bool anyPartHasClock = false;
- for (size_t i=0; i < animation->parts.size(); i++) {
- if(validClock(animation->parts[i])) {
+ for (size_t i=0; i < mAnimation->parts.size(); i++) {
+ if(validClock(mAnimation->parts[i])) {
anyPartHasClock = true;
break;
}
@@ -848,7 +894,7 @@ bool BootAnimation::movie()
bool clockFontInitialized = false;
if (mClockEnabled) {
clockFontInitialized =
- (initFont(&animation->clockFont, CLOCK_FONT_ASSET) == NO_ERROR);
+ (initFont(&mAnimation->clockFont, CLOCK_FONT_ASSET) == NO_ERROR);
mClockEnabled = clockFontInitialized;
}
@@ -857,19 +903,20 @@ bool BootAnimation::movie()
mTimeCheckThread->run("BootAnimation::TimeCheckThread", PRIORITY_NORMAL);
}
- playAnimation(*animation);
+ playAnimation(*mAnimation);
if (mTimeCheckThread != nullptr) {
mTimeCheckThread->requestExit();
mTimeCheckThread = nullptr;
}
- releaseAnimation(animation);
-
if (clockFontInitialized) {
- glDeleteTextures(1, &animation->clockFont.texture.name);
+ glDeleteTextures(1, &mAnimation->clockFont.texture.name);
}
+ releaseAnimation(mAnimation);
+ mAnimation = nullptr;
+
return false;
}
@@ -880,7 +927,7 @@ bool BootAnimation::playAnimation(const Animation& animation)
const int animationX = (mWidth - animation.width) / 2;
const int animationY = (mHeight - animation.height) / 2;
- ALOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",
+ SLOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",
elapsedRealtime());
for (size_t i=0 ; i<pcount ; i++) {
const Animation::Part& part(animation.parts[i]);
@@ -888,7 +935,7 @@ bool BootAnimation::playAnimation(const Animation& animation)
glBindTexture(GL_TEXTURE_2D, 0);
// Handle animation package
- if (part.animation != NULL) {
+ if (part.animation != nullptr) {
playAnimation(*part.animation);
if (exitPending())
break;
@@ -953,7 +1000,7 @@ bool BootAnimation::playAnimation(const Animation& animation)
nsecs_t now = systemTime();
nsecs_t delay = frameDuration - (now - lastFrame);
- //ALOGD("%lld, %lld", ns2ms(now - lastFrame), ns2ms(delay));
+ //SLOGD("%lld, %lld", ns2ms(now - lastFrame), ns2ms(delay));
lastFrame = now;
if (delay > 0) {
@@ -962,7 +1009,7 @@ bool BootAnimation::playAnimation(const Animation& animation)
spec.tv_nsec = (now + delay) % 1000000000;
int err;
do {
- err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL);
+ err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, nullptr);
} while (err<0 && errno == EINTR);
}
@@ -1018,16 +1065,13 @@ void BootAnimation::handleViewport(nsecs_t timestep) {
// At the end of the animation, we switch to the viewport that DisplayManager will apply
// later. This changes the coordinate system, and means we must move the surface up by
// the inset amount.
- sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(
- ISurfaceComposer::eDisplayIdMain));
-
Rect layerStackRect(0, 0, mWidth, mHeight - mTargetInset);
Rect displayRect(0, mTargetInset, mWidth, mHeight);
SurfaceComposerClient::Transaction t;
t.setPosition(mFlingerSurfaceControl, 0, -mTargetInset)
.setCrop(mFlingerSurfaceControl, Rect(0, mTargetInset, mWidth, mHeight));
- t.setDisplayProjection(dtoken, 0 /* orientation */, layerStackRect, displayRect);
+ t.setDisplayProjection(mDisplayToken, 0 /* orientation */, layerStackRect, displayRect);
t.apply();
mTargetInset = mCurrentInset = 0;
@@ -1052,15 +1096,15 @@ void BootAnimation::releaseAnimation(Animation* animation) const
BootAnimation::Animation* BootAnimation::loadAnimation(const String8& fn)
{
if (mLoadedFiles.indexOf(fn) >= 0) {
- ALOGE("File \"%s\" is already loaded. Cyclic ref is not allowed",
+ SLOGE("File \"%s\" is already loaded. Cyclic ref is not allowed",
fn.string());
- return NULL;
+ return nullptr;
}
ZipFileRO *zip = ZipFileRO::open(fn);
- if (zip == NULL) {
- ALOGE("Failed to open animation zip \"%s\": %s",
+ if (zip == nullptr) {
+ SLOGE("Failed to open animation zip \"%s\": %s",
fn.string(), strerror(errno));
- return NULL;
+ return nullptr;
}
Animation *animation = new Animation;
@@ -1071,7 +1115,7 @@ BootAnimation::Animation* BootAnimation::loadAnimation(const String8& fn)
parseAnimationDesc(*animation);
if (!preloadZip(*animation)) {
- return NULL;
+ return nullptr;
}
@@ -1099,7 +1143,7 @@ bool BootAnimation::updateIsTimeAccurate() {
}
FILE* file = fopen(LAST_TIME_CHANGED_FILE_PATH, "r");
- if (file != NULL) {
+ if (file != nullptr) {
long long lastChangedTime = 0;
fscanf(file, "%lld", &lastChangedTime);
fclose(file);
@@ -1147,7 +1191,7 @@ bool BootAnimation::TimeCheckThread::doThreadLoop() {
if (pollResult == 0) {
return true;
} else if (pollResult < 0) {
- ALOGE("Could not poll inotify events");
+ SLOGE("Could not poll inotify events");
return false;
}
@@ -1156,7 +1200,7 @@ bool BootAnimation::TimeCheckThread::doThreadLoop() {
if (length == 0) {
return true;
} else if (length < 0) {
- ALOGE("Could not read inotify events");
+ SLOGE("Could not read inotify events");
return false;
}
@@ -1187,7 +1231,7 @@ void BootAnimation::TimeCheckThread::addTimeDirWatch() {
status_t BootAnimation::TimeCheckThread::readyToRun() {
mInotifyFd = inotify_init();
if (mInotifyFd < 0) {
- ALOGE("Could not initialize inotify fd");
+ SLOGE("Could not initialize inotify fd");
return NO_INIT;
}
@@ -1195,7 +1239,7 @@ status_t BootAnimation::TimeCheckThread::readyToRun() {
if (mSystemWd < 0) {
close(mInotifyFd);
mInotifyFd = -1;
- ALOGE("Could not add watch for %s", SYSTEM_DATA_DIR_PATH);
+ SLOGE("Could not add watch for %s", SYSTEM_DATA_DIR_PATH);
return NO_INIT;
}