Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e7d85994 authored by Kevin Hester's avatar Kevin Hester
Browse files

Exit boot animation cleanly. DO NOT MERGE

The desc.txt file can now mark parts as 'must finish cleanly' by using
'c' as the part line prefix rather than 'p'.  If so indicated, if the
bootanimation is asked to quit it will do so only after waiting to
finish that part.

I considered either making init.c service killing smarter or promoting
bootanim to be a bindable service with a requestExit method.  However,
these changes are probably too big/risky given our ship date.  So
I used a property as a mailbox between SurfaceFlinger and bootanim.

Change-Id: I40b219c9117c97c3fc94855059ea13fe4ceb3d2b
parent f4b6628e
Loading
Loading
Loading
Loading
+35 −5
Original line number Original line Diff line number Diff line
@@ -54,6 +54,7 @@
#define USER_BOOTANIMATION_FILE "/data/local/bootanimation.zip"
#define USER_BOOTANIMATION_FILE "/data/local/bootanimation.zip"
#define SYSTEM_BOOTANIMATION_FILE "/system/media/bootanimation.zip"
#define SYSTEM_BOOTANIMATION_FILE "/system/media/bootanimation.zip"
#define SYSTEM_ENCRYPTED_BOOTANIMATION_FILE "/system/media/bootanimation-encrypted.zip"
#define SYSTEM_ENCRYPTED_BOOTANIMATION_FILE "/system/media/bootanimation-encrypted.zip"
#define EXIT_PROP_NAME "service.bootanim.exit"


namespace android {
namespace android {


@@ -293,6 +294,9 @@ bool BootAnimation::threadLoop()
        r = movie();
        r = movie();
    }
    }


    // No need to force exit anymore
    property_set(EXIT_PROP_NAME, "0");

    eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    eglDestroyContext(mDisplay, mContext);
    eglDestroyContext(mDisplay, mContext);
    eglDestroySurface(mDisplay, mSurface);
    eglDestroySurface(mDisplay, mSurface);
@@ -359,6 +363,8 @@ bool BootAnimation::android()
        const nsecs_t sleepTime = 83333 - ns2us(systemTime() - now);
        const nsecs_t sleepTime = 83333 - ns2us(systemTime() - now);
        if (sleepTime > 0)
        if (sleepTime > 0)
            usleep(sleepTime);
            usleep(sleepTime);

        checkExit();
    } while (!exitPending());
    } while (!exitPending());


    glDeleteTextures(1, &mAndroid[0].name);
    glDeleteTextures(1, &mAndroid[0].name);
@@ -367,6 +373,16 @@ bool BootAnimation::android()
}
}




void BootAnimation::checkExit() {
    // Allow surface flinger to gracefully request shutdown
    char value[PROPERTY_VALUE_MAX];
    property_get(EXIT_PROP_NAME, value, "0");
    int exitnow = atoi(value);
    if (exitnow) {
        requestExit();
    }
}

bool BootAnimation::movie()
bool BootAnimation::movie()
{
{
    ZipFileRO& zip(mZip);
    ZipFileRO& zip(mZip);
@@ -393,20 +409,23 @@ bool BootAnimation::movie()
        const char* l = line.string();
        const char* l = line.string();
        int fps, width, height, count, pause;
        int fps, width, height, count, pause;
        char path[256];
        char path[256];
        char pathType;
        if (sscanf(l, "%d %d %d", &width, &height, &fps) == 3) {
        if (sscanf(l, "%d %d %d", &width, &height, &fps) == 3) {
            //LOGD("> w=%d, h=%d, fps=%d", fps, width, height);
            //LOGD("> w=%d, h=%d, fps=%d", width, height, fps);
            animation.width = width;
            animation.width = width;
            animation.height = height;
            animation.height = height;
            animation.fps = fps;
            animation.fps = fps;
        }
        }
        if (sscanf(l, "p %d %d %s", &count, &pause, path) == 3) {
        else if (sscanf(l, " %c %d %d %s", &pathType, &count, &pause, path) == 4) {
            //LOGD("> count=%d, pause=%d, path=%s", count, pause, path);
            //LOGD("> type=%c, count=%d, pause=%d, path=%s", pathType, count, pause, path);
            Animation::Part part;
            Animation::Part part;
            part.playUntilComplete = pathType == 'c';
            part.count = count;
            part.count = count;
            part.pause = pause;
            part.pause = pause;
            part.path = path;
            part.path = path;
            animation.parts.add(part);
            animation.parts.add(part);
        }
        }

        s = ++endl;
        s = ++endl;
    }
    }


@@ -468,13 +487,17 @@ bool BootAnimation::movie()
    Region clearReg(Rect(mWidth, mHeight));
    Region clearReg(Rect(mWidth, mHeight));
    clearReg.subtractSelf(Rect(xc, yc, xc+animation.width, yc+animation.height));
    clearReg.subtractSelf(Rect(xc, yc, xc+animation.width, yc+animation.height));


    for (int i=0 ; i<pcount && !exitPending() ; i++) {
    for (int i=0 ; i<pcount ; i++) {
        const Animation::Part& part(animation.parts[i]);
        const Animation::Part& part(animation.parts[i]);
        const size_t fcount = part.frames.size();
        const size_t fcount = part.frames.size();
        glBindTexture(GL_TEXTURE_2D, 0);
        glBindTexture(GL_TEXTURE_2D, 0);


        for (int r=0 ; !part.count || r<part.count ; r++) {
        for (int r=0 ; !part.count || r<part.count ; r++) {
            for (int j=0 ; j<fcount && !exitPending(); j++) {
            // Exit any non playuntil complete parts immediately
            if(exitPending() && !part.playUntilComplete)
                break;

            for (int j=0 ; j<fcount && (!exitPending() || part.playUntilComplete) ; j++) {
                const Animation::Frame& frame(part.frames[j]);
                const Animation::Frame& frame(part.frames[j]);


                if (r > 0) {
                if (r > 0) {
@@ -512,8 +535,15 @@ bool BootAnimation::movie()
                long wait = ns2us(delay);
                long wait = ns2us(delay);
                if (wait > 0)
                if (wait > 0)
                    usleep(wait);
                    usleep(wait);

                checkExit();
            }
            }

            usleep(part.pause * ns2us(frameDuration));
            usleep(part.pause * ns2us(frameDuration));

            // For infinite parts, we've now played them at least once, so perhaps exit
            if(exitPending() && !part.count)
                break;
        }
        }


        // free the textures for this part
        // free the textures for this part
+3 −0
Original line number Original line Diff line number Diff line
@@ -71,6 +71,7 @@ private:
            int pause;
            int pause;
            String8 path;
            String8 path;
            SortedVector<Frame> frames;
            SortedVector<Frame> frames;
            bool playUntilComplete;
        };
        };
        int fps;
        int fps;
        int width;
        int width;
@@ -83,6 +84,8 @@ private:
    bool android();
    bool android();
    bool movie();
    bool movie();


    void checkExit();

    sp<SurfaceComposerClient>       mSession;
    sp<SurfaceComposerClient>       mSession;
    AssetManager mAssets;
    AssetManager mAssets;
    Texture     mAndroid[2];
    Texture     mAndroid[2];
+11 −4
Original line number Original line Diff line number Diff line
@@ -183,7 +183,9 @@ void SurfaceFlinger::bootFinished()
    }
    }


    // stop boot animation
    // stop boot animation
    property_set("ctl.stop", "bootanim");
    // formerly we would just kill the process, but we now ask it to exit so it
    // can choose where to stop the animation.
    property_set("service.bootanim.exit", "1");
}
}


void SurfaceFlinger::binderDied(const wp<IBinder>& who)
void SurfaceFlinger::binderDied(const wp<IBinder>& who)
@@ -194,7 +196,7 @@ void SurfaceFlinger::binderDied(const wp<IBinder>& who)
    setOrientation(0, eOrientationDefault, 0);
    setOrientation(0, eOrientationDefault, 0);


    // restart the boot-animation
    // restart the boot-animation
    property_set("ctl.start", "bootanim");
    startBootAnim();
}
}


void SurfaceFlinger::onFirstRef()
void SurfaceFlinger::onFirstRef()
@@ -300,11 +302,16 @@ status_t SurfaceFlinger::readyToRun()
    /*
    /*
     *  We're now ready to accept clients...
     *  We're now ready to accept clients...
     */
     */
    startBootAnim();

    return NO_ERROR;
}


void SurfaceFlinger::startBootAnim()
{
    // start boot animation
    // start boot animation
    property_set("service.bootanim.exit", "0");
    property_set("ctl.start", "bootanim");
    property_set("ctl.start", "bootanim");

    return NO_ERROR;
}
}


// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
+2 −1
Original line number Original line Diff line number Diff line
@@ -335,6 +335,7 @@ private:
            void        debugShowFPS() const;
            void        debugShowFPS() const;
            void        drawWormhole() const;
            void        drawWormhole() const;


            void        startBootAnim();


    mutable     MessageQueue    mEventQueue;
    mutable     MessageQueue    mEventQueue;