3

我开发了一个ScreenshotClient用于捕获设备屏幕的本机进程(仅限有根设备) 我有一个循环,ScreenshotClient每个update()循环都在其中。在 4.3 之前一切正常。当我在 4.3 上运行它时,第一次调用 update 成功,但在第二次调用中,调用结果是 -2 ,我在 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

知道导致此问题的 4.3 中发生了什么变化,或者这些错误意味着什么。

我的代码大致如下:

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
    }
}
4

1 回答 1

2

我们在产品中遇到了类似的问题,我们能够通过使用标头的更新版本部分解决这个问题(它现在适用于 Galaxy Nexus,但在 4.3 上的其他 Nexus 设备上仍然存在问题)

例如:frameworks/native/include/gui/SurfaceComposerClient.h

这从 4.2 开始发生了变化,因此需要为 4.3 重新编译可执行文件。

我仍在试图理解为什么同样的方法不适用于 N4 和 N7,但至少我能够在我的 GN 上取得进展。

希望这可以帮助。

编辑:在进一步检查中,这看起来像是 SurfaceFlinger 界面中用于进行屏幕捕获的错误。SurfaceComposerClient 在内部调用 SurfaceFlinger 并尝试抓取屏幕。在 4.3 版本的 SurfaceFlinger 中,有两种截屏方式。一种适用于现代设备,例如 N4/N7(它使用某种优化的 GL->CPU 路由来抓取帧)和传统版本(内部使用一种称为“glReadPixels”的方法,该方法使用更昂贵的 CPU->CPU 路由抓取屏幕),用于 Galaxy Nexus 等设备。

现在在优化的代码路径上,调用了 native_window_api_connect 方法,这是第二次调用 update() 时失败的原因。这是因为之前的 update 调用也调用了 this 并获得了与从未释放的本机窗口的连接。它应该通过调用 native_window_api_disconnect 来释放,但这永远不会发生。

但是在未优化的代码路径中,会发生连接调用和随后断开连接的调用,因此一切正常(假设您首先使用 4.3 头文件构建了本机模块)。

:-)

于 2013-09-28T11:21:12.853 回答