我开发了一个本机进程,该进程使用ScreenshotClient
来捕获设备屏幕(仅限根设备)我有一个循环,其中ScreenshotClient
在每个循环中执行update()
。4.3之前一切正常。当我在4.3上运行它时,第一次更新调用成功了,但在第二次调用中,调用结果是-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
}
}
我们的产品中也遇到了类似的问题,通过使用更新版本的头,我们能够部分解决这个问题(它现在适用于Galaxy Nexus,但在4.3上与其他Nexus设备仍然存在问题)
例如:frameworks/native/include/gui/SurfaceComposerClient.h
自4.2以来,这种情况已经发生了变化,因此需要重新编译4.3版的可执行文件。
我仍在努力理解为什么N4和N7同样不起作用,但至少我能够在GN.上取得进展
希望这能有所帮助。
编辑:经过进一步检查,这看起来像是SurfaceFlinger界面中的一个错误。SurfaceComposerClient在内部调用SurfaceFlinger并尝试抓取屏幕。在SurfaceFlinger的4.3版本中,有两种方法可以进行屏幕捕捉。一个用于N4/N7等现代设备(使用某种优化的GL->CPU路线来抓取帧),另一个用于Galaxy Nexus等设备的传统版本(内部使用一种称为"glReadPixels"的方法,使用更昂贵的CPU->CPU路线抓取屏幕)。
现在,在优化的代码路径上,有一个对方法native_window_api_connect的调用,这是第二次调用update()时失败的方法。这是因为之前的更新调用也调用了这个,并获得了与本机窗口的连接,而本机窗口从未发布。它应该通过调用native_window_api_disconnect来释放,但这从未发生过。
但在未优化的代码路径中,会发生连接和随后断开连接的调用,因此一切都很好(假设您首先使用4.3标头构建了本地模块)。
:-)