Loading cmds/bootanimation/BootAnimation.cpp +150 −56 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ #include <ui/Region.h> #include <gui/ISurfaceComposer.h> #include <gui/DisplayEventReceiver.h> #include <gui/Surface.h> #include <gui/SurfaceComposerClient.h> Loading Loading @@ -113,8 +114,8 @@ static constexpr size_t TEXT_POS_LEN_MAX = 16; // --------------------------------------------------------------------------- BootAnimation::BootAnimation(sp<Callbacks> callbacks) : Thread(false), mClockEnabled(true), mTimeIsAccurate(false), mTimeFormat12Hour(false), mTimeCheckThread(nullptr), mCallbacks(callbacks) { : Thread(false), mClockEnabled(true), mTimeIsAccurate(false), mTimeFormat12Hour(false), mTimeCheckThread(nullptr), mCallbacks(callbacks), mLooper(new Looper(false)) { mSession = new SurfaceComposerClient(); std::string powerCtl = android::base::GetProperty("sys.powerctl", ""); Loading Loading @@ -154,8 +155,7 @@ sp<SurfaceComposerClient> BootAnimation::session() const { return mSession; } void BootAnimation::binderDied(const wp<IBinder>&) { void BootAnimation::binderDied(const wp<IBinder>&) { // woah, surfaceflinger died! SLOGD("SurfaceFlinger died, exiting..."); Loading Loading @@ -219,8 +219,7 @@ status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets, return NO_ERROR; } status_t BootAnimation::initTexture(FileMap* map, int* width, int* height) { status_t BootAnimation::initTexture(FileMap* map, int* width, int* height) { SkBitmap bitmap; sk_sp<SkData> data = SkData::MakeWithoutCopy(map->getDataPtr(), map->getDataLength()); Loading Loading @@ -278,6 +277,78 @@ status_t BootAnimation::initTexture(FileMap* map, int* width, int* height) return NO_ERROR; } class BootAnimation::DisplayEventCallback : public LooperCallback { BootAnimation* mBootAnimation; public: DisplayEventCallback(BootAnimation* bootAnimation) { mBootAnimation = bootAnimation; } int handleEvent(int /* fd */, int events, void* /* data */) { if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) { ALOGE("Display event receiver pipe was closed or an error occurred. events=0x%x", events); return 0; // remove the callback } if (!(events & Looper::EVENT_INPUT)) { ALOGW("Received spurious callback for unhandled poll event. events=0x%x", events); return 1; // keep the callback } constexpr int kBufferSize = 100; DisplayEventReceiver::Event buffer[kBufferSize]; ssize_t numEvents; do { numEvents = mBootAnimation->mDisplayEventReceiver->getEvents(buffer, kBufferSize); for (size_t i = 0; i < static_cast<size_t>(numEvents); i++) { const auto& event = buffer[i]; if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG) { SLOGV("Hotplug received"); if (!event.hotplug.connected) { // ignore hotplug disconnect continue; } auto token = SurfaceComposerClient::getPhysicalDisplayToken( event.header.displayId); if (token != mBootAnimation->mDisplayToken) { // ignore hotplug of a secondary display continue; } DisplayConfig displayConfig; const status_t error = SurfaceComposerClient::getActiveDisplayConfig( mBootAnimation->mDisplayToken, &displayConfig); if (error != NO_ERROR) { SLOGE("Can't get active display configuration."); } mBootAnimation->resizeSurface(displayConfig.resolution.getWidth(), displayConfig.resolution.getHeight()); } } } while (numEvents > 0); return 1; // keep the callback } }; EGLConfig BootAnimation::getEglConfig(const EGLDisplay& display) { const EGLint attribs[] = { EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_DEPTH_SIZE, 0, EGL_NONE }; EGLint numConfigs; EGLConfig config; eglChooseConfig(display, attribs, &config, 1, &numConfigs); return config; } status_t BootAnimation::readyToRun() { mAssets.addDefaultAssets(); Loading Loading @@ -346,25 +417,12 @@ status_t BootAnimation::readyToRun() { sp<Surface> s = control->getSurface(); // initialize opengl and egl const EGLint attribs[] = { EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_DEPTH_SIZE, 0, EGL_NONE }; EGLint w, h; EGLint numConfigs; EGLConfig config; EGLSurface surface; EGLContext context; EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); eglInitialize(display, nullptr, nullptr); eglChooseConfig(display, attribs, &config, 1, &numConfigs); surface = eglCreateWindowSurface(display, config, s.get(), nullptr); context = eglCreateContext(display, config, nullptr, nullptr); EGLConfig config = getEglConfig(display); EGLSurface surface = eglCreateWindowSurface(display, config, s.get(), nullptr); EGLContext context = eglCreateContext(display, config, nullptr, nullptr); EGLint w, h; eglQuerySurface(display, surface, EGL_WIDTH, &w); eglQuerySurface(display, surface, EGL_HEIGHT, &h); Loading @@ -380,9 +438,46 @@ status_t BootAnimation::readyToRun() { mFlingerSurface = s; mTargetInset = -1; // Register a display event receiver mDisplayEventReceiver = std::make_unique<DisplayEventReceiver>(); status_t status = mDisplayEventReceiver->initCheck(); SLOGE_IF(status != NO_ERROR, "Initialization of DisplayEventReceiver failed with status: %d", status); mLooper->addFd(mDisplayEventReceiver->getFd(), 0, Looper::EVENT_INPUT, new DisplayEventCallback(this), nullptr); return NO_ERROR; } void BootAnimation::resizeSurface(int newWidth, int newHeight) { // We assume this function is called on the animation thread. if (newWidth == mWidth && newHeight == mHeight) { return; } SLOGV("Resizing the boot animation surface to %d %d", newWidth, newHeight); eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglDestroySurface(mDisplay, mSurface); mWidth = newWidth; mHeight = newHeight; SurfaceComposerClient::Transaction t; t.setSize(mFlingerSurfaceControl, mWidth, mHeight); t.apply(); EGLConfig config = getEglConfig(mDisplay); EGLSurface surface = eglCreateWindowSurface(mDisplay, config, mFlingerSurface.get(), nullptr); if (eglMakeCurrent(mDisplay, surface, surface, mContext) == EGL_FALSE) { SLOGE("Can't make the new surface current. Error %d", eglGetError()); return; } glViewport(0, 0, mWidth, mHeight); glScissor(0, 0, mWidth, mHeight); mSurface = surface; } bool BootAnimation::preloadAnimation() { findBootAnimationFile(); if (!mZipFileName.isEmpty()) { Loading Loading @@ -443,15 +538,14 @@ void BootAnimation::findBootAnimationFile() { } } bool BootAnimation::threadLoop() { bool r; bool BootAnimation::threadLoop() { bool result; // We have no bootanimation file, so we use the stock android logo // animation. if (mZipFileName.isEmpty()) { r = android(); result = android(); } else { r = movie(); result = movie(); } eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); Loading @@ -462,11 +556,10 @@ bool BootAnimation::threadLoop() eglTerminate(mDisplay); eglReleaseThread(); IPCThreadState::self()->stopProcess(); return r; return result; } bool BootAnimation::android() { bool BootAnimation::android() { SLOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot", elapsedRealtime()); initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png"); Loading @@ -485,19 +578,19 @@ bool BootAnimation::android() glEnable(GL_TEXTURE_2D); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); const GLint xc = (mWidth - mAndroid[0].w) / 2; const GLint yc = (mHeight - mAndroid[0].h) / 2; const Rect updateRect(xc, yc, xc + mAndroid[0].w, yc + mAndroid[0].h); glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(), updateRect.height()); // Blend state glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); const nsecs_t startTime = systemTime(); do { processDisplayEvents(); const GLint xc = (mWidth - mAndroid[0].w) / 2; const GLint yc = (mHeight - mAndroid[0].h) / 2; const Rect updateRect(xc, yc, xc + mAndroid[0].w, yc + mAndroid[0].h); glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(), updateRect.height()); nsecs_t now = systemTime(); double time = now - startTime; float t = 4.0f * float(time / us2ns(16667)) / mAndroid[1].w; Loading Loading @@ -612,8 +705,7 @@ static bool parseColor(const char str[7], float color[3]) { } static bool readFile(ZipFileRO* zip, const char* name, String8& outString) { static bool readFile(ZipFileRO* zip, const char* name, String8& outString) { ZipEntryRO entry = zip->findEntryByName(name); SLOGE_IF(!entry, "couldn't find %s", name); if (!entry) { Loading Loading @@ -734,8 +826,7 @@ void BootAnimation::drawClock(const Font& font, const int xPos, const int yPos) drawText(out, font, false, &x, &y); } bool BootAnimation::parseAnimationDesc(Animation& animation) { bool BootAnimation::parseAnimationDesc(Animation& animation) { String8 desString; if (!readFile(animation.zip, "desc.txt", desString)) { Loading Loading @@ -802,8 +893,7 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) return true; } bool BootAnimation::preloadZip(Animation& animation) { bool BootAnimation::preloadZip(Animation& animation) { // read all the data structures const size_t pcount = animation.parts.size(); void *cookie = nullptr; Loading Loading @@ -900,8 +990,7 @@ bool BootAnimation::preloadZip(Animation& animation) return true; } bool BootAnimation::movie() { bool BootAnimation::movie() { if (mAnimation == nullptr) { mAnimation = loadAnimation(mZipFileName); } Loading Loading @@ -987,12 +1076,9 @@ bool BootAnimation::movie() return false; } bool BootAnimation::playAnimation(const Animation& animation) { bool BootAnimation::playAnimation(const Animation& animation) { const size_t pcount = animation.parts.size(); nsecs_t frameDuration = s2ns(1) / animation.fps; const int animationX = (mWidth - animation.width) / 2; const int animationY = (mHeight - animation.height) / 2; SLOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot", elapsedRealtime()); Loading Loading @@ -1023,6 +1109,11 @@ bool BootAnimation::playAnimation(const Animation& animation) 1.0f); for (size_t j=0 ; j<fcount && (!exitPending() || part.playUntilComplete) ; j++) { processDisplayEvents(); const int animationX = (mWidth - animation.width) / 2; const int animationY = (mHeight - animation.height) / 2; const Animation::Frame& frame(part.frames[j]); nsecs_t lastFrame = systemTime(); Loading Loading @@ -1106,6 +1197,12 @@ bool BootAnimation::playAnimation(const Animation& animation) return true; } void BootAnimation::processDisplayEvents() { // This will poll mDisplayEventReceiver and if there are new events it'll call // displayEventCallback synchronously. mLooper->pollOnce(0); } void BootAnimation::handleViewport(nsecs_t timestep) { if (mShuttingDown || !mFlingerSurfaceControl || mTargetInset == 0) { return; Loading Loading @@ -1148,8 +1245,7 @@ void BootAnimation::handleViewport(nsecs_t timestep) { mCurrentInset += delta; } void BootAnimation::releaseAnimation(Animation* animation) const { void BootAnimation::releaseAnimation(Animation* animation) const { for (Vector<Animation::Part>::iterator it = animation->parts.begin(), e = animation->parts.end(); it != e; ++it) { if (it->animation) Loading @@ -1160,8 +1256,7 @@ void BootAnimation::releaseAnimation(Animation* animation) const delete animation; } BootAnimation::Animation* BootAnimation::loadAnimation(const String8& fn) { BootAnimation::Animation* BootAnimation::loadAnimation(const String8& fn) { if (mLoadedFiles.indexOf(fn) >= 0) { SLOGE("File \"%s\" is already loaded. Cyclic ref is not allowed", fn.string()); Loading Loading @@ -1323,5 +1418,4 @@ status_t BootAnimation::TimeCheckThread::readyToRun() { // --------------------------------------------------------------------------- } ; // namespace android } // namespace android cmds/bootanimation/BootAnimation.h +12 −0 Original line number Diff line number Diff line Loading @@ -18,11 +18,14 @@ #define ANDROID_BOOTANIMATION_H #include <vector> #include <queue> #include <stdint.h> #include <sys/types.h> #include <androidfw/AssetManager.h> #include <gui/DisplayEventReceiver.h> #include <utils/Looper.h> #include <utils/Thread.h> #include <binder/IBinder.h> Loading Loading @@ -145,6 +148,11 @@ private: BootAnimation* mBootAnimation; }; // Display event handling class DisplayEventCallback; int displayEventCallback(int fd, int events, void* data); void processDisplayEvents(); status_t initTexture(Texture* texture, AssetManager& asset, const char* name); status_t initTexture(FileMap* map, int* width, int* height); status_t initFont(Font* font, const char* fallback); Loading @@ -161,6 +169,8 @@ private: void findBootAnimationFile(); bool findBootAnimationFileInternal(const std::vector<std::string>& files); bool preloadAnimation(); EGLConfig getEglConfig(const EGLDisplay&); void resizeSurface(int newWidth, int newHeight); void checkExit(); Loading Loading @@ -189,6 +199,8 @@ private: sp<TimeCheckThread> mTimeCheckThread = nullptr; sp<Callbacks> mCallbacks; Animation* mAnimation = nullptr; std::unique_ptr<DisplayEventReceiver> mDisplayEventReceiver; sp<Looper> mLooper; }; // --------------------------------------------------------------------------- Loading Loading
cmds/bootanimation/BootAnimation.cpp +150 −56 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ #include <ui/Region.h> #include <gui/ISurfaceComposer.h> #include <gui/DisplayEventReceiver.h> #include <gui/Surface.h> #include <gui/SurfaceComposerClient.h> Loading Loading @@ -113,8 +114,8 @@ static constexpr size_t TEXT_POS_LEN_MAX = 16; // --------------------------------------------------------------------------- BootAnimation::BootAnimation(sp<Callbacks> callbacks) : Thread(false), mClockEnabled(true), mTimeIsAccurate(false), mTimeFormat12Hour(false), mTimeCheckThread(nullptr), mCallbacks(callbacks) { : Thread(false), mClockEnabled(true), mTimeIsAccurate(false), mTimeFormat12Hour(false), mTimeCheckThread(nullptr), mCallbacks(callbacks), mLooper(new Looper(false)) { mSession = new SurfaceComposerClient(); std::string powerCtl = android::base::GetProperty("sys.powerctl", ""); Loading Loading @@ -154,8 +155,7 @@ sp<SurfaceComposerClient> BootAnimation::session() const { return mSession; } void BootAnimation::binderDied(const wp<IBinder>&) { void BootAnimation::binderDied(const wp<IBinder>&) { // woah, surfaceflinger died! SLOGD("SurfaceFlinger died, exiting..."); Loading Loading @@ -219,8 +219,7 @@ status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets, return NO_ERROR; } status_t BootAnimation::initTexture(FileMap* map, int* width, int* height) { status_t BootAnimation::initTexture(FileMap* map, int* width, int* height) { SkBitmap bitmap; sk_sp<SkData> data = SkData::MakeWithoutCopy(map->getDataPtr(), map->getDataLength()); Loading Loading @@ -278,6 +277,78 @@ status_t BootAnimation::initTexture(FileMap* map, int* width, int* height) return NO_ERROR; } class BootAnimation::DisplayEventCallback : public LooperCallback { BootAnimation* mBootAnimation; public: DisplayEventCallback(BootAnimation* bootAnimation) { mBootAnimation = bootAnimation; } int handleEvent(int /* fd */, int events, void* /* data */) { if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) { ALOGE("Display event receiver pipe was closed or an error occurred. events=0x%x", events); return 0; // remove the callback } if (!(events & Looper::EVENT_INPUT)) { ALOGW("Received spurious callback for unhandled poll event. events=0x%x", events); return 1; // keep the callback } constexpr int kBufferSize = 100; DisplayEventReceiver::Event buffer[kBufferSize]; ssize_t numEvents; do { numEvents = mBootAnimation->mDisplayEventReceiver->getEvents(buffer, kBufferSize); for (size_t i = 0; i < static_cast<size_t>(numEvents); i++) { const auto& event = buffer[i]; if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG) { SLOGV("Hotplug received"); if (!event.hotplug.connected) { // ignore hotplug disconnect continue; } auto token = SurfaceComposerClient::getPhysicalDisplayToken( event.header.displayId); if (token != mBootAnimation->mDisplayToken) { // ignore hotplug of a secondary display continue; } DisplayConfig displayConfig; const status_t error = SurfaceComposerClient::getActiveDisplayConfig( mBootAnimation->mDisplayToken, &displayConfig); if (error != NO_ERROR) { SLOGE("Can't get active display configuration."); } mBootAnimation->resizeSurface(displayConfig.resolution.getWidth(), displayConfig.resolution.getHeight()); } } } while (numEvents > 0); return 1; // keep the callback } }; EGLConfig BootAnimation::getEglConfig(const EGLDisplay& display) { const EGLint attribs[] = { EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_DEPTH_SIZE, 0, EGL_NONE }; EGLint numConfigs; EGLConfig config; eglChooseConfig(display, attribs, &config, 1, &numConfigs); return config; } status_t BootAnimation::readyToRun() { mAssets.addDefaultAssets(); Loading Loading @@ -346,25 +417,12 @@ status_t BootAnimation::readyToRun() { sp<Surface> s = control->getSurface(); // initialize opengl and egl const EGLint attribs[] = { EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_DEPTH_SIZE, 0, EGL_NONE }; EGLint w, h; EGLint numConfigs; EGLConfig config; EGLSurface surface; EGLContext context; EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); eglInitialize(display, nullptr, nullptr); eglChooseConfig(display, attribs, &config, 1, &numConfigs); surface = eglCreateWindowSurface(display, config, s.get(), nullptr); context = eglCreateContext(display, config, nullptr, nullptr); EGLConfig config = getEglConfig(display); EGLSurface surface = eglCreateWindowSurface(display, config, s.get(), nullptr); EGLContext context = eglCreateContext(display, config, nullptr, nullptr); EGLint w, h; eglQuerySurface(display, surface, EGL_WIDTH, &w); eglQuerySurface(display, surface, EGL_HEIGHT, &h); Loading @@ -380,9 +438,46 @@ status_t BootAnimation::readyToRun() { mFlingerSurface = s; mTargetInset = -1; // Register a display event receiver mDisplayEventReceiver = std::make_unique<DisplayEventReceiver>(); status_t status = mDisplayEventReceiver->initCheck(); SLOGE_IF(status != NO_ERROR, "Initialization of DisplayEventReceiver failed with status: %d", status); mLooper->addFd(mDisplayEventReceiver->getFd(), 0, Looper::EVENT_INPUT, new DisplayEventCallback(this), nullptr); return NO_ERROR; } void BootAnimation::resizeSurface(int newWidth, int newHeight) { // We assume this function is called on the animation thread. if (newWidth == mWidth && newHeight == mHeight) { return; } SLOGV("Resizing the boot animation surface to %d %d", newWidth, newHeight); eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglDestroySurface(mDisplay, mSurface); mWidth = newWidth; mHeight = newHeight; SurfaceComposerClient::Transaction t; t.setSize(mFlingerSurfaceControl, mWidth, mHeight); t.apply(); EGLConfig config = getEglConfig(mDisplay); EGLSurface surface = eglCreateWindowSurface(mDisplay, config, mFlingerSurface.get(), nullptr); if (eglMakeCurrent(mDisplay, surface, surface, mContext) == EGL_FALSE) { SLOGE("Can't make the new surface current. Error %d", eglGetError()); return; } glViewport(0, 0, mWidth, mHeight); glScissor(0, 0, mWidth, mHeight); mSurface = surface; } bool BootAnimation::preloadAnimation() { findBootAnimationFile(); if (!mZipFileName.isEmpty()) { Loading Loading @@ -443,15 +538,14 @@ void BootAnimation::findBootAnimationFile() { } } bool BootAnimation::threadLoop() { bool r; bool BootAnimation::threadLoop() { bool result; // We have no bootanimation file, so we use the stock android logo // animation. if (mZipFileName.isEmpty()) { r = android(); result = android(); } else { r = movie(); result = movie(); } eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); Loading @@ -462,11 +556,10 @@ bool BootAnimation::threadLoop() eglTerminate(mDisplay); eglReleaseThread(); IPCThreadState::self()->stopProcess(); return r; return result; } bool BootAnimation::android() { bool BootAnimation::android() { SLOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot", elapsedRealtime()); initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png"); Loading @@ -485,19 +578,19 @@ bool BootAnimation::android() glEnable(GL_TEXTURE_2D); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); const GLint xc = (mWidth - mAndroid[0].w) / 2; const GLint yc = (mHeight - mAndroid[0].h) / 2; const Rect updateRect(xc, yc, xc + mAndroid[0].w, yc + mAndroid[0].h); glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(), updateRect.height()); // Blend state glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); const nsecs_t startTime = systemTime(); do { processDisplayEvents(); const GLint xc = (mWidth - mAndroid[0].w) / 2; const GLint yc = (mHeight - mAndroid[0].h) / 2; const Rect updateRect(xc, yc, xc + mAndroid[0].w, yc + mAndroid[0].h); glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(), updateRect.height()); nsecs_t now = systemTime(); double time = now - startTime; float t = 4.0f * float(time / us2ns(16667)) / mAndroid[1].w; Loading Loading @@ -612,8 +705,7 @@ static bool parseColor(const char str[7], float color[3]) { } static bool readFile(ZipFileRO* zip, const char* name, String8& outString) { static bool readFile(ZipFileRO* zip, const char* name, String8& outString) { ZipEntryRO entry = zip->findEntryByName(name); SLOGE_IF(!entry, "couldn't find %s", name); if (!entry) { Loading Loading @@ -734,8 +826,7 @@ void BootAnimation::drawClock(const Font& font, const int xPos, const int yPos) drawText(out, font, false, &x, &y); } bool BootAnimation::parseAnimationDesc(Animation& animation) { bool BootAnimation::parseAnimationDesc(Animation& animation) { String8 desString; if (!readFile(animation.zip, "desc.txt", desString)) { Loading Loading @@ -802,8 +893,7 @@ bool BootAnimation::parseAnimationDesc(Animation& animation) return true; } bool BootAnimation::preloadZip(Animation& animation) { bool BootAnimation::preloadZip(Animation& animation) { // read all the data structures const size_t pcount = animation.parts.size(); void *cookie = nullptr; Loading Loading @@ -900,8 +990,7 @@ bool BootAnimation::preloadZip(Animation& animation) return true; } bool BootAnimation::movie() { bool BootAnimation::movie() { if (mAnimation == nullptr) { mAnimation = loadAnimation(mZipFileName); } Loading Loading @@ -987,12 +1076,9 @@ bool BootAnimation::movie() return false; } bool BootAnimation::playAnimation(const Animation& animation) { bool BootAnimation::playAnimation(const Animation& animation) { const size_t pcount = animation.parts.size(); nsecs_t frameDuration = s2ns(1) / animation.fps; const int animationX = (mWidth - animation.width) / 2; const int animationY = (mHeight - animation.height) / 2; SLOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot", elapsedRealtime()); Loading Loading @@ -1023,6 +1109,11 @@ bool BootAnimation::playAnimation(const Animation& animation) 1.0f); for (size_t j=0 ; j<fcount && (!exitPending() || part.playUntilComplete) ; j++) { processDisplayEvents(); const int animationX = (mWidth - animation.width) / 2; const int animationY = (mHeight - animation.height) / 2; const Animation::Frame& frame(part.frames[j]); nsecs_t lastFrame = systemTime(); Loading Loading @@ -1106,6 +1197,12 @@ bool BootAnimation::playAnimation(const Animation& animation) return true; } void BootAnimation::processDisplayEvents() { // This will poll mDisplayEventReceiver and if there are new events it'll call // displayEventCallback synchronously. mLooper->pollOnce(0); } void BootAnimation::handleViewport(nsecs_t timestep) { if (mShuttingDown || !mFlingerSurfaceControl || mTargetInset == 0) { return; Loading Loading @@ -1148,8 +1245,7 @@ void BootAnimation::handleViewport(nsecs_t timestep) { mCurrentInset += delta; } void BootAnimation::releaseAnimation(Animation* animation) const { void BootAnimation::releaseAnimation(Animation* animation) const { for (Vector<Animation::Part>::iterator it = animation->parts.begin(), e = animation->parts.end(); it != e; ++it) { if (it->animation) Loading @@ -1160,8 +1256,7 @@ void BootAnimation::releaseAnimation(Animation* animation) const delete animation; } BootAnimation::Animation* BootAnimation::loadAnimation(const String8& fn) { BootAnimation::Animation* BootAnimation::loadAnimation(const String8& fn) { if (mLoadedFiles.indexOf(fn) >= 0) { SLOGE("File \"%s\" is already loaded. Cyclic ref is not allowed", fn.string()); Loading Loading @@ -1323,5 +1418,4 @@ status_t BootAnimation::TimeCheckThread::readyToRun() { // --------------------------------------------------------------------------- } ; // namespace android } // namespace android
cmds/bootanimation/BootAnimation.h +12 −0 Original line number Diff line number Diff line Loading @@ -18,11 +18,14 @@ #define ANDROID_BOOTANIMATION_H #include <vector> #include <queue> #include <stdint.h> #include <sys/types.h> #include <androidfw/AssetManager.h> #include <gui/DisplayEventReceiver.h> #include <utils/Looper.h> #include <utils/Thread.h> #include <binder/IBinder.h> Loading Loading @@ -145,6 +148,11 @@ private: BootAnimation* mBootAnimation; }; // Display event handling class DisplayEventCallback; int displayEventCallback(int fd, int events, void* data); void processDisplayEvents(); status_t initTexture(Texture* texture, AssetManager& asset, const char* name); status_t initTexture(FileMap* map, int* width, int* height); status_t initFont(Font* font, const char* fallback); Loading @@ -161,6 +169,8 @@ private: void findBootAnimationFile(); bool findBootAnimationFileInternal(const std::vector<std::string>& files); bool preloadAnimation(); EGLConfig getEglConfig(const EGLDisplay&); void resizeSurface(int newWidth, int newHeight); void checkExit(); Loading Loading @@ -189,6 +199,8 @@ private: sp<TimeCheckThread> mTimeCheckThread = nullptr; sp<Callbacks> mCallbacks; Animation* mAnimation = nullptr; std::unique_ptr<DisplayEventReceiver> mDisplayEventReceiver; sp<Looper> mLooper; }; // --------------------------------------------------------------------------- Loading