TextureView keeps getting SIGSEGV 11

1k views Asked by At

I have found this Solution, but unfortunately, it didn't work for me. When I'm only displaying a small moving rectangle, so no taxing animations, it works fine, but I want to display some animation frames that I load in with a .png, and whenever I minimize my app or press the back button, I immediately get a SIGSEV error.

For one screen where I draw a graph with a lot of points I found a solution in which I just stop the thread after I'm done drawing the lines, but since I need to display a moving animation I can't do it in this particular fragment.

My code for for the render thread looks like this:

private class RenderThread extends Thread {
    private volatile boolean mRunning = true;
    int framecount = 1;

    @Override
    public void run() {


        while (mRunning && !Thread.interrupted()) {

            final Canvas canvas = mSimulationAnimationView.lockCanvas(null);

            try {
                canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
                drawCar(canvas);
            } finally {
                mSimulationAnimationView.unlockCanvasAndPost(canvas);
            }

            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                // Sleep if the Thread is interrupted
            }
        }
    }

    public void stopRendering() {
        interrupt();
        mRunning = false;
    }


    private void drawCar(Canvas canvas){

        if(framecount==1){
            canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.piston_frame_one), 10, 10, null);
            framecount++;
        }
        else{
            canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.piston_frame_two), 10, 10, null);
            framecount--;

        }



    }

}//RenderThread

This is obviously based on Romain Guy's example which can be found here

Help is very much appreciated!

Edit: the crash dump is this one:

********** Crash dump: **********
Build fingerprint: 'google/hammerhead/hammerhead:5.1.1/LMY48B/1863243:user/release-keys'
pid: 16130, tid: 16343, name: Thread-19966  >>> package.package.package <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x9ee3ad10
Stack frame #00 pc 001b474a  /system/lib/libskia.so (S32A_Opaque_BlitRow32_neon_src_alpha(unsigned int*, unsigned int const*, int, unsigned int)+109)
Stack frame #01 pc 001072fb  /system/lib/libskia.so
Stack frame #02 pc 00103793  /system/lib/libskia.so
Stack frame #03 pc 0010385f  /system/lib/libskia.so (SkScan::FillIRect(SkIRect const&, SkRegion const*, SkBlitter*)+198)
Stack frame #04 pc 0010395f  /system/lib/libskia.so (SkScan::FillIRect(SkIRect const&, SkRasterClip const&, SkBlitter*)+36)
Stack frame #05 pc 000e0e27  /system/lib/libskia.so (SkDraw::drawBitmap(SkBitmap const&, SkMatrix const&, SkPaint const&) const+464)
Stack frame #06 pc 000d90c9  /system/lib/libskia.so
Stack frame #07 pc 000d91b1  /system/lib/libskia.so (SkCanvas::drawBitmap(SkBitmap const&, float, float, SkPaint const*)+116)
Stack frame #08 pc 000947d1  /system/lib/libandroid_runtime.so (android::SkiaCanvas::drawBitmap(SkBitmap const&, float, float, SkPaint const*)+12)
Stack frame #09 pc 0008a7b7  /system/lib/libandroid_runtime.so
Stack frame #10 pc 007eff33  /data/dalvik-cache/arm/system@[email protected]
2

There are 2 answers

2
fadden On BEST ANSWER

It's important to stop rendering before onPause() returns, as the framework will start tearing things down. A simple and effective way to do this is to ask the renderer thread to stop, and wait for it to do so with Thread#join().

An alternative to the "sleep for a while" approach is to use Choreographer (API 16+), which invokes a callback on VSYNC. You may still want to do the rendering in a separate thread for better performance on multi-core devices. The "record GL app" activity in Grafika uses Choreographer to signal a renderer thread that uses the standard Android Looper/Handler mechanism. It consistently renders at 60fps, and demonstrates a crude mechanism for dropping frames when the system slows down.

(Note the Grafika examples uses SurfaceView, not TextureView, for which the rules are slightly different -- the SurfaceView Surface's lifecycle is not tied to onPause(), so the thread stop and join actually happen in the surfaceDestroyed() callback.)

See also the "game loops" section in the graphics architecture doc.

5
marcinj On

I would switch lines in stopRendering function, from:

public void stopRendering() {
    interrupt();
    mRunning = false;
}

to:

public void stopRendering() {
    mRunning = false;
    interrupt();
}

the reason is that it is possible that interrupt() will break sleep() in your thread, then render thread will continue execution and will find out that mRunning is still true. I am not sure if this is the problem causing your crashes .

[edit]

hints to make code more reliable:

  1. As fadden has written in comments, its good idea to wait in stopRendering() for rendering thread to end.
  2. You might check mSimulationAnimationView.getSurface().isValid() before locking it, if its false then continue looping your rendering thread.
  3. Once you have called lockCanvas(null) check if result is non null before using it. In docs it says:

If null is not returned, this function internally holds a lock until the corresponding unlockCanvasAndPost(Canvas) call, preventing SurfaceView from creating, destroying, or modifying the surface while it is being drawn.

so once you have a lock, you should be safe