diff options
author | TreeHugger Robot <treehugger-gerrit@google.com> | 2020-05-26 19:21:50 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2020-05-26 19:21:50 +0000 |
commit | 8f631886c59427e4272e49fdc26c5d6489dadcab (patch) | |
tree | 37d791827acc6e541a795db8f563d18e6350ac94 /cmds/bootanimation/BootAnimation.cpp | |
parent | 44a80126ac807e37073ca0ebc0c84a7f619429be (diff) | |
parent | 9070c055b66839151fddd30cfb94a37751436330 (diff) |
Merge "Resize boot animation on display changes"
Diffstat (limited to 'cmds/bootanimation/BootAnimation.cpp')
-rw-r--r-- | cmds/bootanimation/BootAnimation.cpp | 204 |
1 files changed, 149 insertions, 55 deletions
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 589d5c90041a..d8e25accdaaf 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -49,6 +49,7 @@ #include <ui/Region.h> #include <gui/ISurfaceComposer.h> +#include <gui/DisplayEventReceiver.h> #include <gui/Surface.h> #include <gui/SurfaceComposerClient.h> @@ -106,7 +107,7 @@ static constexpr size_t TEXT_POS_LEN_MAX = 16; // --------------------------------------------------------------------------- BootAnimation::BootAnimation(sp<Callbacks> callbacks) - : Thread(false), mClockEnabled(true), mTimeIsAccurate(false), + : Thread(false), mLooper(new Looper(false)), mClockEnabled(true), mTimeIsAccurate(false), mTimeFormat12Hour(false), mTimeCheckThread(nullptr), mCallbacks(callbacks) { mSession = new SurfaceComposerClient(); @@ -147,8 +148,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..."); @@ -241,8 +241,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) { AndroidBitmapInfo bitmapInfo; void* pixels = decodeImage(map->getDataPtr(), map->getDataLength(), &bitmapInfo); auto pixelDeleter = std::unique_ptr<void, decltype(free)*>{ pixels, free }; @@ -301,6 +300,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(); @@ -369,25 +440,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); @@ -403,9 +461,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()) { @@ -466,15 +561,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); @@ -485,11 +579,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"); @@ -508,19 +601,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; @@ -635,8 +728,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) { @@ -757,8 +849,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)) { @@ -825,8 +916,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; @@ -923,8 +1013,7 @@ bool BootAnimation::preloadZip(Animation& animation) return true; } -bool BootAnimation::movie() -{ +bool BootAnimation::movie() { if (mAnimation == nullptr) { mAnimation = loadAnimation(mZipFileName); } @@ -1010,12 +1099,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()); @@ -1046,6 +1132,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(); @@ -1129,6 +1220,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; @@ -1171,8 +1268,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) @@ -1183,8 +1279,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()); @@ -1346,5 +1441,4 @@ status_t BootAnimation::TimeCheckThread::readyToRun() { // --------------------------------------------------------------------------- -} -; // namespace android +} // namespace android |