6

My device is Nexus 4 running Jelly Bean 4.2. I'm trying to record the screen and send it out. Most codes on internet do the cap by read /dev/graphics/fb0. It works fine in some devices and the older systems. But when I try it on my device, it fail. It only gives me blackscreen and all "0" in the raw data. I have run "adb root" to get the root permission, tried "chmod 777 fb0", "cat fb0 > /sdcard/fb0". Also I have tried codes like "mmap" and "memcpy" to get the data. But all fail. I have searched on internet and there seems no solution. And some threads said that the kernel may forbid you reading the fb0. Anyone have idea on that?

user1659072
  • 121
  • 4
  • 9
  • 1
    With more modern GPUs, the framebuffer is probably just not trivially accessible (at least not in its entirety) to the main CPU most of the time. Most implementations of ADBD long ago moved to using an external device-unique executable called something like screencap to do the actual work of capturing the framebuffer. You can either use that, try to find documentation/source, or try to reverse engineer the executable. Normally I'd say "good luck" on the source, but for a Nexus device it might actually be available (or they may just provide the binary along with the other closed bits) – Chris Stratton Jun 25 '13 at 19:06
  • 1
    Thanks for reply. Actually, Android's original codes contains two executables name: screencap and screenshot. And there are two ways in their codes. One is by reading the fb0, another is by calling glPixel() provided by Android native library. The second one is quite slow. Actually I have implemented one with the second method, but the fps is not ideal. So I go back and try to do it in the first way. There is no restriction in my project. I can even hack the kernel to implement it. Stuck by the problem for weeks. Need help. – user1659072 Jun 25 '13 at 19:10
  • What you need is low-level GPU programming information which, sadly, is generally not released by manufacturers. I don't believe they gave up on the simple fb read to be difficult or even for security; they did it because the hardware no longer easily (or at least portably) exposed the whole thing as a contiguous buffer. I traced through yet another implementation right after this change that sort of read the real framebuffer in chunks interacting with some low level code - more efficient than the pixel by pixel approach, but again unique to specific hardware. – Chris Stratton Jun 25 '13 at 19:14
  • I have tried change the fb_post function in framebuffer and gralloc codes. But still not work. I only get the first frame when a new app was open. Is there any codes sample or links that talk about this in detail? – user1659072 Jun 25 '13 at 22:33

1 Answers1

6

As the hardware advances, you're less and less likely to find an actual framebuffer with the screen contents in it.

As noted in the comments, adb uses the "screencap" command, which contacts surfaceflinger through a Binder call, falling back on /dev/graphcs/fb0 if that fails. The latter path is rarely used now.

If you really want to dig into how this works, you need to examine how surfaceflinger does composition, especially the hwcomposer HAL. The hardware composer takes multiple gralloc surfaces and composites them during scan-out. How this works differs from device to device; the hwcomposer implementation is usually done by the graphics chip manufacturer.

Screen shot generation, used by the app framework to generate the thumbnails for the "recent apps" feature, applies the same composition steps HWC does but exclusively with GLES. As of Android 4.2, the hardware composer isn't able to composite into a buffer.

Sometimes the hardware composer "punts", e.g. because there are more layers to composite than the hardware can handle. In that case, surfaceflinger reverts to GLES composition, and there will be a buffer somewhere that has the complete image; whether or not you'll find it by opening /dev/graphics/fb0 is a different matter.

Some starting points:

fadden
  • 51,356
  • 5
  • 116
  • 166