In my application I have a SurfaceView
in my Activity layout so its surface is not affected by any Fragment lifecycles. I use the surface to draw to it from JNI using following code (some of the varialbes are global):
void onDraw() {
int height=0, width=0;
ANativeWindow_Buffer nativeBuffer;
ARect redrawRect;
if (nativeWindow != NULL) {
height = ANativeWindow_getHeight(nativeWindow);
width = ANativeWindow_getWidth(nativeWindow);
redrawRect.left = 0;
redrawRect.top = 0;
redrawRect.right = width;
redrawRect.bottom = height;
if (ANativeWindow_lock(nativeWindow, &nativeBuffer, &redrawRect) == 0) {
height = (redrawRect.bottom - redrawRect.top);
width = (redrawRect.right - redrawRect.left);
bufferSize= height * width * 4;
memcpy(nativeBuffer.bits, pbuf, bufferSize);
ANativeWindow_unlockAndPost(nativeWindow);
}
}
}
As long as I do not change the size and position of the SurfaceView
this works great. However, when I start drawing, adjust the SurfaceView
in size and position (content is adjusted fine), stop the drawing and then start it again I get the following error:
E/BufferQueue: [SurfaceView] connect: already connected (cur=2, req=2)
What I understand from the documentation so far is that my SurfaceView
is the consumer and the ANativeWindow
the producer. The SurfaceView holds a BufferQueue
which send the display data (copied by memcpy) from the producer to the consumer side. So after the size and location change one of them (I'm not sure which) is trying to connect to that BufferQueue again. Since in my code I'm not calling queue/acquire
etc. specifically I'm not sure how to prevent this.
What I do not know: Is connect called from ANativeWindow_lock
or ANativeWindow_fromSurface
on the NDK side? Could the buffer received by the lock method leak somehow to prevent the connect next time? I also added log messages to the lock and unlock results and found that after the size and location change ANativeWindow_lock
fails. This seems odd to me because my unlock is only performed when the lock was successful and I'm not locking the surface from the Java side at all. If I try to unlock it then from JNI I get:
Surface::unlockAndPost failed, no locked buffer
I also thought about other memory leaks and analysed it with LeakCanary. This does not find any leaks, even when I do a heap dump manually tho I'm not sure how good it works with native code.
If I do not draw at all this error does not appear. Do you have any ideas for this?
If it matters I'm developing on Android KitKat (4.4.2). Any help is highly appreciated.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…