ScreenshotClient error after upgrading to 4.3

1.7k Views Asked by At

I developed a native process that uses ScreenshotClient to capture the device screen ( rooted devices only ) I have a loop where ScreenshotClient does update() every cycle. Everything works well until 4.3. when I run it on 4.3 the first call to update succeeds, but in the second call the call result is -2 , and I get these errors in logcat:

E/BufferQueue( 8166): [ScreenshotClient] connect: already connected (cur=1,req=1)
E/libEGL ( 2463): EGLNativeWindowType 0x4116d5f8 already connected to another API
E/libEGL ( 2463): eglCreateWindowSurface:376 error 300b (EGL_BAD_NATIVE_WINDOW)
E/SurfaceFlinger( 2463): captureScreenImplLocked: eglCreateWindowSurface() failed 0x300b

Any idea what changed in 4.3 that causes this, or what these errors mean.

My code looks roughly like this:

int main(int argc, char** argv) {

    ProcessState::self()->startThreadPool();

    sp < IBinder > display = SurfaceComposerClient::getBuiltInDisplay(
            DEFAULT_DISPLAY_ID);

    ScreenshotClient client;
    while (true) {
        client.update(display);
        pixels = screenshot.getPixels();
        // do something with the data
    }
}
1

There are 1 best solutions below

1
On

We had similar problems in our product, and we were able to partially solve this (it now works for Galaxy Nexus, but still has problems with other Nexus devices on 4.3) by using the updated version of the headers

Eg: frameworks/native/include/gui/SurfaceComposerClient.h

This has changed since 4.2 and so the executable needs to be recompiled again for 4.3.

I am still trying to understand why the same does not work for N4 and N7, but atleast am able to make progress on my GN.

Hope this helps.

Edit: On further checks, this looks like a bug in the SurfaceFlinger interface to do screen capture. The SurfaceComposerClient internally calls into the SurfaceFlinger and tries to grab the screen. In 4.3 version of the SurfaceFlinger, there are two ways of doing the screen capture. One for modern devices like N4/N7 (which uses some kindof an optimzed GL->CPU route to grab the frame) and a traditional version (which internally uses a method called 'glReadPixels' which uses a more expensive CPU->CPU route to grab screen) which is used for devices like Galaxy Nexus.

Now on the optimized code path, there is a call to a method native_window_api_connect which is what fails when update() is called for the second time. This is because the previous call to update also called this and got a connection to the native window, which was never released. Its supposed to be released by making a call to native_window_api_disconnect, which never happen.

But in the unoptimized code path, the calls to connect and subsequently disconnect happens, and so everything works quite well (assuming you have built your native module using the 4.3 headers in the first place).

:-)